diff --git a/.env.development.example b/.env.development.example index 3631af262..99c7dc612 100644 --- a/.env.development.example +++ b/.env.development.example @@ -1,4 +1,34 @@ -# Using dotenv-rails to set development environment variables -# Example use below: -SOLR_VERSION = 6.2.1 -SOLR_URL: http://127.0.0.1:8983/solr/geoportal-core-development +GEOBLACKLIGHT_DB_HOST=localhost +GEOBLACKLIGHT_DB_DATABASE=geoportal_admin +GEOBLACKLIGHT_DB_USER= +GEOBLACKLIGHT_DB_PASSWORD= + +SOLR_VERSION=8.11.1 + +# Solr - Local development +SOLR_URL=http://127.0.0.1:8983/solr/blacklight-core + +# Solr - Remote development +# SOLR_URL=https://remote_server/solr/core +# SOLR_BASIC_AUTH_USER=user +# SOLR_BASIC_AUTH_PASSWORD=password + +# BL API +BLACKLIGHT_URL=/ +BLACKLIGHT_JSON_API=/admin/api.json +BLACKLIGHT_JSON_API_IDS=/admin/api/ids.json +BLACKLIGHT_JSON_API_FACETS=/admin/advanced_search/facets.json + +# BL IDS +BLACKLIGHT_JSON_IDS=/admin/ids.json + +GEOMG_DB_DATABASE=geoblacklight_development +GEOMG_DB_USER= +GEOMG_DB_PASSWORD= + +GEOMG_DEVISE_SECRET_KEY=generated-by-rake-secret + +# Blazer +BLAZER_UPLOADS_URL=postgresql://127.0.0.1:5432/geoblacklight_development +MAPBOX_ACCESS_TOKEN=your-key-here + diff --git a/.env.test.example b/.env.test.example index ebbc33bee..f4e44bfe3 100644 --- a/.env.test.example +++ b/.env.test.example @@ -1,3 +1,9 @@ # Using dotenv-rails to set test environment variables SOLR_VERSION = 6.2.1 SOLR_URL: http://127.0.0.1:8985/solr/geoportal-core-test + +POSTGRES_HOST = localhost +POSTGRES_PORT = 5432 +POSTGRES_DB = geoblacklight_test +POSTGRES_USER = postgres +POSTGRES_PASSWORD = postgres \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea9873da5..b58374f63 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,25 @@ jobs: strategy: matrix: ruby: ['3.0'] + + services: + postgres: + image: postgres:latest + env: + POSTGRES_HOST: 127.0.0.1 + POSTGRES_PORT: 5432 + POSTGRES_DB: geoblacklight_test + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + # Set health checks to wait until postgres has started + options: + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: - uses: actions/checkout@v2 diff --git a/.solr_wrapper b/.solr_wrapper.yml similarity index 92% rename from .solr_wrapper rename to .solr_wrapper.yml index 060e8b244..7f0ec4b69 100644 --- a/.solr_wrapper +++ b/.solr_wrapper.yml @@ -5,3 +5,4 @@ download_dir: tmp/solr collection: dir: solr/conf/ name: geoportal-core-test + persist: true \ No newline at end of file diff --git a/Gemfile b/Gemfile index aae8f9cdf..56878034f 100644 --- a/Gemfile +++ b/Gemfile @@ -45,6 +45,8 @@ gem 'stackprof', '~> 0.2.12' # ruby 2.1+ only gem 'memory_profiler', '~> 0.9.12' group :development, :test do + gem 'active_record_query_trace' + # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' @@ -73,23 +75,35 @@ gem 'blacklight', '~> 7.33.0' gem "blacklight_advanced_search", git: "https://github.com/ewlarson/blacklight_advanced_search.git", branch: "bl7-fix-gentle-hands" gem 'blacklight_range_limit', '~> 7.0.0' -gem 'chosen-rails' # jquery multiselect plugin for advanced search +gem 'chosen-rails', '~> 1.10' # jquery multiselect plugin for advanced search gem 'bootstrap', '~> 4.0' gem 'popper_js' gem 'twitter-typeahead-rails', '0.11.1.pre.corejavascript' gem 'geoblacklight', '~> 4.1' +gem 'geoblacklight_admin', '~> 0.3' gem "rubyzip", ">= 1.3.0" gem "awesome_print" +# GBL Admin dependencies _not_ automatically loading... +gem 'active_storage_validations' +gem 'awesome_print' +# gem 'blacklight_advanced_search' +gem 'dotenv-rails' +gem 'haml' +gem 'inline_svg' +gem 'kithe', '~> 2.0' +gem 'noticed' +gem 'paper_trail' + # Image migration -gem 'geoblacklight_sidecar_images', '~> 1.0' +gem 'geoblacklight_sidecar_images', git: "https://github.com/geoblacklight/geoblacklight_sidecar_images.git", branch: "feature/statesman-update" gem 'carrierwave', '~> 1.2' gem 'mini_magick', '~> 4.9.4' -gem 'statesman', '~> 3.4.1' +gem 'statesman', '~> 10.0' gem 'sidekiq', '~> 6.4' gem 'sidekiq-failures', '~> 1.0.0' -gem 'down', '~> 4.4' +gem 'down', '~> 5.0' gem 'addressable', '~> 2.5.0' gem 'handlebars_assets', '~> 0.23.0' gem 'geoblacklight-icons', git: 'https://github.com/geoblacklight/geoblacklight-icons.git', :ref => '84da81140e7ef93e7241b7753c01d7f709216f2b' @@ -97,8 +111,15 @@ gem 'solr_wrapper', git: 'https://github.com/cbeer/solr_wrapper.git', branch: 'm gem 'rsolr', '>= 1.0' gem 'jquery-rails' -gem "devise", ">= 4.7.1" + +# Auth +gem "devise", "4.7.3" +gem 'devise-bootstrap-views', '~> 1.0' gem 'devise-guests', '~> 0.6' +gem 'devise_invitable', '~> 2.0.0' + +# Reporting +gem 'blazer' gem 'haml' gem 'chronic' diff --git a/Gemfile.lock b/Gemfile.lock index fd6398881..aed6c10f9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,63 +25,87 @@ GIT specs: geoblacklight-icons (1.3.1) +GIT + remote: https://github.com/geoblacklight/geoblacklight_sidecar_images.git + revision: 089e2a4a677a5d522b9d88fef0ef46cfa69961a0 + branch: feature/statesman-update + specs: + geoblacklight_sidecar_images (1.0.0) + faraday (>= 2.0) + geoblacklight (~> 4.0) + image_processing (~> 1.6) + mimemagic (~> 0.3) + mini_magick (~> 4.9.4) + rails (>= 5.2, < 7.1) + statesman (~> 10.0.0) + GEM remote: https://rubygems.org/ specs: - actioncable (6.1.7.3) - actionpack (= 6.1.7.3) - activesupport (= 6.1.7.3) + Ascii85 (1.1.0) + actioncable (6.1.7.6) + actionpack (= 6.1.7.6) + activesupport (= 6.1.7.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.1.7.3) - actionpack (= 6.1.7.3) - activejob (= 6.1.7.3) - activerecord (= 6.1.7.3) - activestorage (= 6.1.7.3) - activesupport (= 6.1.7.3) + actionmailbox (6.1.7.6) + actionpack (= 6.1.7.6) + activejob (= 6.1.7.6) + activerecord (= 6.1.7.6) + activestorage (= 6.1.7.6) + activesupport (= 6.1.7.6) mail (>= 2.7.1) - actionmailer (6.1.7.3) - actionpack (= 6.1.7.3) - actionview (= 6.1.7.3) - activejob (= 6.1.7.3) - activesupport (= 6.1.7.3) + actionmailer (6.1.7.6) + actionpack (= 6.1.7.6) + actionview (= 6.1.7.6) + activejob (= 6.1.7.6) + activesupport (= 6.1.7.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.1.7.3) - actionview (= 6.1.7.3) - activesupport (= 6.1.7.3) + actionpack (6.1.7.6) + actionview (= 6.1.7.6) + activesupport (= 6.1.7.6) rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.1.7.3) - actionpack (= 6.1.7.3) - activerecord (= 6.1.7.3) - activestorage (= 6.1.7.3) - activesupport (= 6.1.7.3) + actiontext (6.1.7.6) + actionpack (= 6.1.7.6) + activerecord (= 6.1.7.6) + activestorage (= 6.1.7.6) + activesupport (= 6.1.7.6) nokogiri (>= 1.8.5) - actionview (6.1.7.3) - activesupport (= 6.1.7.3) + actionview (6.1.7.6) + activesupport (= 6.1.7.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.1.7.3) - activesupport (= 6.1.7.3) + active_record_query_trace (1.8.2) + activerecord (>= 6.0.0) + active_storage_validations (1.0.4) + activejob (>= 5.2.0) + activemodel (>= 5.2.0) + activestorage (>= 5.2.0) + activesupport (>= 5.2.0) + activejob (6.1.7.6) + activesupport (= 6.1.7.6) globalid (>= 0.3.6) - activemodel (6.1.7.3) - activesupport (= 6.1.7.3) - activerecord (6.1.7.3) - activemodel (= 6.1.7.3) - activesupport (= 6.1.7.3) - activestorage (6.1.7.3) - actionpack (= 6.1.7.3) - activejob (= 6.1.7.3) - activerecord (= 6.1.7.3) - activesupport (= 6.1.7.3) + activemodel (6.1.7.6) + activesupport (= 6.1.7.6) + activerecord (6.1.7.6) + activemodel (= 6.1.7.6) + activesupport (= 6.1.7.6) + activerecord-import (1.5.0) + activerecord (>= 4.2) + activestorage (6.1.7.6) + actionpack (= 6.1.7.6) + activejob (= 6.1.7.6) + activerecord (= 6.1.7.6) + activesupport (= 6.1.7.6) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (6.1.7.3) + activesupport (6.1.7.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -89,14 +113,18 @@ GEM zeitwerk (~> 2.3) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) + afm (0.2.2) airrecord (1.0.12) faraday (>= 1.0, < 3.0) faraday-net_http_persistent net-http-persistent + amazing_print (1.5.0) ansi (1.5.0) - appsignal (3.4.4) + appsignal (3.4.12) rack - autoprefixer-rails (10.4.13.0) + attr_json (2.2.0) + activerecord (>= 6.0.0, < 7.2) + autoprefixer-rails (10.4.15.0) execjs (~> 2) awesome_print (1.9.2) axe-core-api (4.7.0) @@ -106,7 +134,9 @@ GEM descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) - bcrypt (3.1.18) + base64 (0.1.1) + bcp47_spec (0.2.1) + bcrypt (3.1.19) bindex (0.8.1) blacklight (7.33.1) deprecation @@ -123,6 +153,11 @@ GEM jquery-rails rails (>= 3.0) tether-rails + blazer (2.6.5) + activerecord (>= 5) + chartkick (>= 3.2) + railties (>= 5) + safely_block (>= 0.1.1) bootsnap (1.9.4) msgpack (~> 1.0) bootstrap (4.6.2) @@ -151,11 +186,13 @@ GEM activesupport (>= 4.0.0) mime-types (>= 1.16) ssrf_filter (~> 1.0, < 1.1.0) + chartkick (5.0.4) chosen-rails (1.10.0) coffee-rails (>= 3.2) railties (>= 3.0) sassc-rails (>= 2.1.2) chronic (0.10.2) + cocoon (1.2.15) coderay (1.1.3) coercible (1.0.0) descendants_tracker (~> 0.0.1) @@ -171,6 +208,7 @@ GEM deep_merge (~> 1.2, >= 1.2.1) dry-validation (~> 1.0, >= 1.0.0) connection_pool (2.4.1) + content_disposition (1.0.0) crass (1.0.6) database_cleaner (2.0.2) database_cleaner-active_record (>= 2, < 3) @@ -184,27 +222,33 @@ GEM activesupport descendants_tracker (0.0.4) thread_safe (~> 0.3, >= 0.3.1) - devise (4.9.2) + devise (4.7.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) + devise-bootstrap-views (1.1.0) devise-guests (0.8.1) devise + devise_invitable (2.0.8) + actionmailer (>= 5.0) + devise (>= 4.6) diff-lcs (1.5.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) + dot-properties (0.1.4) + bundler (>= 2.2.33) dotenv (2.8.1) dotenv-rails (2.8.1) dotenv (= 2.8.1) railties (>= 3.2) - down (4.8.1) + down (5.2.2) addressable (~> 2.5) - dry-configurable (1.0.1) + dry-configurable (1.1.0) dry-core (~> 1.0, < 2) zeitwerk (~> 2.6) - dry-core (1.0.0) + dry-core (1.0.1) concurrent-ruby (~> 1.0) zeitwerk (~> 2.6) dry-inflector (1.0.0) @@ -213,7 +257,7 @@ GEM concurrent-ruby (~> 1.0) dry-core (~> 1.0, < 2) zeitwerk (~> 2.6) - dry-schema (1.13.2) + dry-schema (1.13.3) concurrent-ruby (~> 1.0) dry-configurable (~> 1.0, >= 1.0.1) dry-core (~> 1.0, < 2) @@ -240,25 +284,30 @@ GEM exception_notification (4.4.3) actionmailer (>= 4.0, < 7) activesupport (>= 4.0, < 7) - execjs (2.8.1) + execjs (2.9.1) factory_bot (6.2.1) activesupport (>= 5.0.0) factory_bot_rails (6.2.0) factory_bot (~> 6.2.0) railties (>= 5.0.0) - faraday (2.7.6) + faraday (2.7.11) + base64 faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) faraday-net_http (3.0.2) faraday-net_http_persistent (2.1.0) faraday (~> 2.5) net-http-persistent (~> 4.0) - ffi (1.15.5) + fastimage (2.2.7) + ffi (1.16.3) ffi-compiler (1.0.1) ffi (>= 1.0.0) rake flamegraph (0.9.5) foreman (0.87.2) + fx (0.8.0) + activerecord (>= 6.0.0) + railties (>= 6.0.0) geo_combine (0.8.0) activesupport faraday-net_http_persistent (~> 2.0) @@ -279,27 +328,51 @@ GEM mime-types rails (>= 6.1, < 7.1) rgeo-geojson - geoblacklight_sidecar_images (1.0.0) - faraday (>= 2.0) + geoblacklight_admin (0.3.0) + active_storage_validations (~> 1.0) + amazing_print + blacklight (~> 7.33) + blacklight_advanced_search + blacklight_range_limit + bootstrap (~> 4.0) + chosen-rails (~> 1.10) + cocoon (~> 1.2) + config (~> 4.0) + devise (~> 4.7) + devise-bootstrap-views (~> 1.0) + devise_invitable (~> 2.0) + dotenv-rails (~> 2.8) geoblacklight (~> 4.0) - image_processing (~> 1.6) - mimemagic (~> 0.3) - mini_magick (~> 4.9.4) - rails (>= 5.2, < 7.1) - statesman (>= 3.4) + haml (~> 5.2) + httparty (~> 0.21) + inline_svg (~> 1.9) + jquery-rails (~> 4.4) + kithe (~> 2.0) + noticed (~> 1.6) + pagy (~> 6.0) + paper_trail (~> 14.0) + pg (~> 1.4) + qa (~> 5.0) + rails (>= 6.1, < 7.1) + ruby-progressbar + simple_form (~> 5.0) + sprockets (< 4) + statesman (~> 10.0) + geocoder (1.8.2) git (1.11.0) rchardet (~> 1.8) - globalid (1.1.0) - activesupport (>= 5.0) - haml (6.1.1) - temple (>= 0.8.2) - thor + globalid (1.2.1) + activesupport (>= 6.1) + haml (5.2.2) + temple (>= 0.8.0) tilt handlebars_assets (0.23.9) execjs (~> 2.0) sprockets (>= 2.0.0) tilt (>= 1.2) hashdiff (1.0.1) + hashery (2.1.2) + hashie (5.0.0) http (5.0.1) addressable (~> 2.3) http-cookie (~> 1.0) @@ -308,16 +381,23 @@ GEM http-cookie (1.0.5) domain_name (~> 0.5) http-form_data (2.3.0) + httparty (0.21.0) + mini_mime (>= 1.0.0) + multi_xml (>= 0.5.2) + httpclient (2.8.3) i18n (1.14.1) concurrent-ruby (~> 1.0) ice_nine (0.11.2) image_processing (1.12.2) mini_magick (>= 4.9.5, < 5) ruby-vips (>= 2.0.17, < 3) + inline_svg (1.9.0) + activesupport (>= 3.0) + nokogiri (>= 1.6) jbuilder (2.11.5) actionview (>= 5.0.0) activesupport (>= 5.0.0) - jquery-rails (4.5.1) + jquery-rails (4.6.0) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -335,10 +415,31 @@ GEM activerecord kaminari-core (= 1.2.2) kaminari-core (1.2.2) + kithe (2.11.0) + attr_json (< 3.0.0) + fastimage (~> 2.0) + fx (>= 0.6.0, < 1) + marcel + mini_mime + pdf-reader (~> 2.0) + rails (>= 5.2.1, < 7.1) + rsolr (~> 2.2) + ruby-progressbar (~> 1.0) + shrine (~> 3.3) + shrine-url (~> 2.0) + simple_form (>= 4.0, < 6.0) + traject (~> 3.0, >= 3.1.0.rc1) + tty-command (>= 0.8.2, < 2) launchy (2.4.3) addressable (~> 2.3) + ldpath (1.2.0) + nokogiri (~> 1.8) + parslet + rdf (~> 3.0) + rdf-vocab (~> 3.0) letter_opener (1.8.1) launchy (>= 2.2, < 3) + link_header (0.0.8) listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) @@ -356,48 +457,70 @@ GEM net-imap net-pop net-smtp + marc (1.2.0) + rexml + scrub_rb (>= 1.0.1, < 2) + unf + marc-fastxmlwriter (1.1.0) + marc (~> 1.0) marcel (1.0.2) matrix (0.4.2) memory_profiler (0.9.14) method_source (1.0.0) - mime-types (3.4.1) + mime-types (3.5.1) mime-types-data (~> 3.2015) - mime-types-data (3.2023.0218.1) + mime-types-data (3.2023.1003) mimemagic (0.4.3) nokogiri (~> 1) rake mini_magick (4.9.5) - mini_mime (1.1.2) - mini_portile2 (2.8.2) + mini_mime (1.1.5) + mini_portile2 (2.8.4) minitar (0.9) - minitest (5.18.0) + minitest (5.20.0) minitest-ci (3.4.0) minitest (>= 5.0.6) - minitest-reporters (1.6.0) + minitest-reporters (1.6.1) ansi builder minitest (>= 5.0) ruby-progressbar - msgpack (1.7.1) + msgpack (1.7.2) + multi_xml (0.6.0) net-http-persistent (4.0.2) connection_pool (~> 2.2) - net-imap (0.3.6) + net-imap (0.4.0) date net-protocol net-pop (0.1.2) net-protocol net-protocol (0.2.1) timeout - net-smtp (0.3.3) + net-smtp (0.4.0) net-protocol nio4r (2.5.9) - nokogiri (1.15.2) + nokogiri (1.15.4) mini_portile2 (~> 2.8.2) racc (~> 1.4) + noticed (1.6.3) + http (>= 4.0.0) + rails (>= 5.2.0) orm_adapter (0.5.0) ostruct (0.5.5) + pagy (6.1.0) + paper_trail (14.0.0) + activerecord (>= 6.0) + request_store (~> 1.4) parslet (2.0.0) - pg (1.5.3) + pastel (0.8.0) + tty-color (~> 0.5) + pdf-reader (2.11.0) + Ascii85 (~> 1.0) + afm (~> 0.2.1) + hashery (~> 2.0) + ruby-rc4 + ttfunk + pg (1.5.4) pointless_feedback (4.1.5) airrecord (~> 1.0) jquery-rails (>= 4.0) @@ -405,42 +528,52 @@ GEM typhoeus (~> 0.7, >= 0.7.3) popper_js (1.16.1) public_suffix (3.1.1) - puma (5.6.5) + puma (5.6.7) nio4r (~> 2.0) + qa (5.10.0) + activerecord-import + deprecation + faraday (< 3.0, != 2.0.0) + geocoder + ldpath + nokogiri (~> 1.6) + rails (>= 5.0, < 7.1) + rdf racc (1.7.1) rack (2.2.8) rack-cors (2.0.1) rack (>= 2.0.0) rack-mini-profiler (2.3.4) rack (>= 1.2.0) - rack-proxy (0.7.6) + rack-proxy (0.7.7) rack rack-test (2.1.0) rack (>= 1.3) - rails (6.1.7.3) - actioncable (= 6.1.7.3) - actionmailbox (= 6.1.7.3) - actionmailer (= 6.1.7.3) - actionpack (= 6.1.7.3) - actiontext (= 6.1.7.3) - actionview (= 6.1.7.3) - activejob (= 6.1.7.3) - activemodel (= 6.1.7.3) - activerecord (= 6.1.7.3) - activestorage (= 6.1.7.3) - activesupport (= 6.1.7.3) + rails (6.1.7.6) + actioncable (= 6.1.7.6) + actionmailbox (= 6.1.7.6) + actionmailer (= 6.1.7.6) + actionpack (= 6.1.7.6) + actiontext (= 6.1.7.6) + actionview (= 6.1.7.6) + activejob (= 6.1.7.6) + activemodel (= 6.1.7.6) + activerecord (= 6.1.7.6) + activestorage (= 6.1.7.6) + activesupport (= 6.1.7.6) bundler (>= 1.15.0) - railties (= 6.1.7.3) + railties (= 6.1.7.6) sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) rails-html-sanitizer (1.6.0) loofah (~> 2.21) nokogiri (~> 1.14) - railties (6.1.7.3) - actionpack (= 6.1.7.3) - activesupport (= 6.1.7.3) + railties (6.1.7.6) + actionpack (= 6.1.7.6) + activesupport (= 6.1.7.6) method_source rake (>= 12.2) thor (~> 1.0) @@ -449,8 +582,15 @@ GEM rb-inotify (0.10.1) ffi (~> 1.0) rchardet (1.8.0) + rdf (3.3.1) + bcp47_spec (~> 0.2) + link_header (~> 0.0, >= 0.0.8) + rdf-vocab (3.3.0) + rdf (~> 3.3) redis (4.8.1) regexp_parser (2.8.1) + request_store (1.5.1) + rack (>= 1.4) responders (3.1.0) actionpack (>= 5.2) railties (>= 5.2) @@ -480,11 +620,13 @@ GEM rspec-support (~> 3.9.0) rspec-support (3.9.4) ruby-progressbar (1.13.0) + ruby-rc4 (0.1.5) ruby-vips (2.1.4) ffi (~> 1.12) ruby2_keywords (0.0.5) rubyzip (2.3.2) - sanitize (6.0.1) + safely_block (0.4.0) + sanitize (6.1.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) sass (3.7.4) @@ -506,19 +648,31 @@ GEM sprockets (> 3.0) sprockets-rails tilt + scrub_rb (1.0.1) sd_notify (0.1.1) selenium-webdriver (4.12.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) + shrine (3.5.0) + content_disposition (~> 1.0) + down (~> 5.1) + shrine-url (2.4.1) + down (~> 5.0) + http (>= 3.2, < 6) + shrine (>= 3.0.0.rc, < 4) sidekiq (6.5.9) connection_pool (>= 2.2.5, < 3) rack (~> 2.0) redis (>= 4.5.0, < 5) sidekiq-failures (1.0.4) sidekiq (>= 4.0.0) + simple_form (5.2.0) + actionpack (>= 5.2) + activemodel (>= 5.2) sitemap_generator (6.0.2) builder (~> 3.0) + slop (4.10.1) spring (4.1.1) sprockets (3.7.2) concurrent-ruby (~> 1.0) @@ -527,18 +681,33 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.6.3) + sqlite3 (1.6.4) mini_portile2 (~> 2.8.0) ssrf_filter (1.0.8) stackprof (0.2.25) - statesman (3.4.1) - temple (0.10.2) + statesman (10.0.0) + temple (0.10.3) tether-rails (1.4.0) rails (>= 3.1) thor (1.2.2) thread_safe (0.3.6) - tilt (2.2.0) - timeout (0.3.2) + tilt (2.3.0) + timeout (0.4.0) + traject (3.8.1) + concurrent-ruby (>= 0.8.0) + dot-properties (>= 0.1.1) + hashie (>= 3.1, < 6) + http (>= 3.0, < 6) + httpclient (~> 2.5) + marc (~> 1.0) + marc-fastxmlwriter (~> 1.0) + nokogiri (~> 1.9) + slop (~> 4.0) + yell + ttfunk (1.7.0) + tty-color (0.6.0) + tty-command (0.10.1) + pastel (~> 0.8) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) @@ -565,7 +734,7 @@ GEM descendants_tracker (~> 0.0, >= 0.0.3) warden (1.2.9) rack (>= 2.0.9) - web-console (4.2.0) + web-console (4.2.1) actionview (>= 6.0.0) activemodel (>= 6.0.0) bindex (>= 0.4.0) @@ -575,19 +744,22 @@ GEM rack-proxy (>= 0.6.1) railties (>= 4.2) websocket (1.2.9) - websocket-driver (0.7.5) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) whenever (1.0.0) chronic (>= 0.6.3) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.6.8) + yell (2.2.2) + zeitwerk (2.6.12) PLATFORMS ruby DEPENDENCIES + active_record_query_trace + active_storage_validations addressable (~> 2.5.0) appsignal awesome_print @@ -595,6 +767,7 @@ DEPENDENCIES blacklight (~> 7.33.0) blacklight_advanced_search! blacklight_range_limit (~> 7.0.0) + blazer bootsnap (~> 1.9.3) bootstrap (~> 4.0) byebug @@ -602,25 +775,30 @@ DEPENDENCIES capybara-screenshot capybara-selenium carrierwave (~> 1.2) - chosen-rails + chosen-rails (~> 1.10) chronic coffee-rails (~> 4.2) database_cleaner - devise (>= 4.7.1) + devise (= 4.7.3) + devise-bootstrap-views (~> 1.0) devise-guests (~> 0.6) + devise_invitable (~> 2.0.0) dotenv-rails - down (~> 4.4) + down (~> 5.0) exception_notification (~> 4.4.0) factory_bot_rails flamegraph (~> 0.9.5) foreman geoblacklight (~> 4.1) geoblacklight-icons! - geoblacklight_sidecar_images (~> 1.0) + geoblacklight_admin (~> 0.3) + geoblacklight_sidecar_images! haml handlebars_assets (~> 0.23.0) + inline_svg jbuilder (~> 2.5) jquery-rails + kithe (~> 2.0) letter_opener listen (~> 3.0) m (~> 1.5.0) @@ -629,6 +807,8 @@ DEPENDENCIES minitest minitest-ci (~> 3.4.0) minitest-reporters + noticed + paper_trail pg pointless_feedback popper_js @@ -650,7 +830,7 @@ DEPENDENCIES spring sqlite3 (~> 1.4) stackprof (~> 0.2.12) - statesman (~> 3.4.1) + statesman (~> 10.0) turbolinks twitter-typeahead-rails (= 0.11.1.pre.corejavascript) uglifier (>= 1.3.0) diff --git a/app/assets/images/archive-solid.svg b/app/assets/images/archive-solid.svg new file mode 100644 index 000000000..c0d7043f0 --- /dev/null +++ b/app/assets/images/archive-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/bookmark-regular.svg b/app/assets/images/bookmark-regular.svg new file mode 100644 index 000000000..18400f8c0 --- /dev/null +++ b/app/assets/images/bookmark-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/bookmark-solid.svg b/app/assets/images/bookmark-solid.svg new file mode 100644 index 000000000..7b61fb8ce --- /dev/null +++ b/app/assets/images/bookmark-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/cloud-download-alt-solid.svg b/app/assets/images/cloud-download-alt-solid.svg new file mode 100644 index 000000000..5e47b4566 --- /dev/null +++ b/app/assets/images/cloud-download-alt-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/file-import-solid.svg b/app/assets/images/file-import-solid.svg new file mode 100644 index 000000000..1fca7b5c1 --- /dev/null +++ b/app/assets/images/file-import-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/trash-alt-solid.svg b/app/assets/images/trash-alt-solid.svg new file mode 100644 index 000000000..34730835c --- /dev/null +++ b/app/assets/images/trash-alt-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 1ec922a30..bda58a46f 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -84,3 +84,6 @@ //= require js-cookie/src/js.cookie.js //= require geoportal + +// Required by GBL Admin +//= require activestorage \ No newline at end of file diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index d3133caa2..a1a737aa0 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -6,5 +6,22 @@ @import 'bootstrap'; @import 'blacklight'; @import 'geoblacklight'; +@import 'geoblacklight_admin/core'; @import 'geoportal'; @import 'gblsci'; + +// GBL Admin - override defaults +div.container-fluid { + margin-top: 0 !important; +} + +footer { + border-top: none; + margin-top: 4rem; + background: none; + box-shadow: none; + + background-color: rgb(204, 204, 204); + padding-top: 2rem; + padding-bottom: 2rem; +} \ No newline at end of file diff --git a/app/assets/stylesheets/geoportal/_homepage.scss b/app/assets/stylesheets/geoportal/_homepage.scss index 354333592..238e1572d 100644 --- a/app/assets/stylesheets/geoportal/_homepage.scss +++ b/app/assets/stylesheets/geoportal/_homepage.scss @@ -16,9 +16,11 @@ $radius: 4px; } } -main { +main.homepage { background:lighten($black, 12%) asset_url('aerial_photo_dark.jpg') repeat; padding:0px; + padding-left:15px; + padding-right:15px; #home-content { margin-top:5.5rem; diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 000000000..9aec23053 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 000000000..2c84e59bf --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module ApplicationCable + # Connect! + class Connection < ActionCable::Connection::Base + identified_by :current_user + + def connect + self.current_user = find_verified_user + end + + private + + # check for authenticated user via devise + def find_verified_user + if verified_user = env['warden'].user + verified_user + else + reject_unauthorized_connection + end + end + end +end diff --git a/app/channels/export_channel.rb b/app/channels/export_channel.rb new file mode 100644 index 000000000..742084409 --- /dev/null +++ b/app/channels/export_channel.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# ExportChannel +class ExportChannel < ApplicationCable::Channel + def subscribed + stream_from 'export_channel' + end + + def unsubscribed + # Any cleanup needed when channel is unsubscribed + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index be028787b..0325bfe0b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,4 +1,5 @@ class ApplicationController < ActionController::Base + include Pagy::Backend # Adds a few additional behaviors into the application controller include Blacklight::Controller layout :determine_layout if respond_to? :layout diff --git a/app/javascript/channels/consumer.js b/app/javascript/channels/consumer.js new file mode 100644 index 000000000..8ec3aad3a --- /dev/null +++ b/app/javascript/channels/consumer.js @@ -0,0 +1,6 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the `bin/rails generate channel` command. + +import { createConsumer } from "@rails/actioncable" + +export default createConsumer() diff --git a/app/javascript/channels/export_channel.js b/app/javascript/channels/export_channel.js new file mode 100644 index 000000000..b58579644 --- /dev/null +++ b/app/javascript/channels/export_channel.js @@ -0,0 +1,30 @@ +import consumer from "./consumer" + +consumer.subscriptions.create({ channel: "ExportChannel" }, { + connected() { + // Called when the subscription is ready for use on the server + console.log('Export Channel Connected'); + }, + + disconnected() { + // Called when the subscription has been terminated by the server + console.log('Export Channel Disconnected'); + }, + + received(data) { + console.log('Export Channel Received'); + console.log(data); + + if (data['progress']) { + console.log(data['progress']); + } + + if (data['actions']) { + for (let index = 0; index < data.actions.length; ++index) { + var fnstring = data.actions[index].method; + var fn = window["GBLADMIN"][fnstring]; + if (typeof fn === "function") fn(data.actions[index].payload); + } + } + } +}); diff --git a/app/javascript/channels/index.js b/app/javascript/channels/index.js new file mode 100644 index 000000000..0cfcf7491 --- /dev/null +++ b/app/javascript/channels/index.js @@ -0,0 +1,5 @@ +// Load all the channels within this directory and all subdirectories. +// Channel files must be named *_channel.js. + +const channels = require.context('.', true, /_channel\.js$/) +channels.keys().forEach(channels) diff --git a/app/javascript/controllers/application_controller.js b/app/javascript/controllers/application_controller.js new file mode 100644 index 000000000..fe0cf32fe --- /dev/null +++ b/app/javascript/controllers/application_controller.js @@ -0,0 +1,19 @@ +import { Controller } from 'stimulus' + +/* This is your application's ApplicationController. + * All StimulusReflex controllers should inherit from this class. + * + * Example: + * + * import ApplicationController from './application_controller' + * + * export default class extends ApplicationController { ... } + * + * Learn more at: https://docs.stimulusreflex.com + */ + +// Adding a comment here +export default class extends Controller { + connect () { + } +} diff --git a/app/javascript/controllers/document_controller.js b/app/javascript/controllers/document_controller.js new file mode 100644 index 000000000..8e74525e9 --- /dev/null +++ b/app/javascript/controllers/document_controller.js @@ -0,0 +1,26 @@ +// Visit The Stimulus Handbook for more details +// https://stimulusjs.org/handbook/introduction +// +// This example controller works with specially annotated HTML like: +// +//
+//

+//
+ +import { Application } from "stimulus" +import ScrollTo from "stimulus-scroll-to" + +export default class extends ScrollTo { + connect() { + } + + // You can set default options in this getter for all your anchors. + get defaultOptions () { + return { + behavior: 'smooth' + } + } +} + +const application = Application.start() +application.register("scroll-to", ScrollTo) diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js new file mode 100644 index 000000000..2961be9a8 --- /dev/null +++ b/app/javascript/controllers/index.js @@ -0,0 +1,10 @@ +// Load all the controllers within this directory and all subdirectories. +// Controller files must be named *_controller.js. + +import { Application } from "stimulus" +import { definitionsFromContext } from "stimulus/webpack-helpers" +import controller from './application_controller' + +const application = Application.start() +const context = require.context("controllers", true, /_controller\.js$/) +application.load(definitionsFromContext(context)) diff --git a/app/javascript/controllers/results_controller.js b/app/javascript/controllers/results_controller.js new file mode 100644 index 000000000..53556a5a4 --- /dev/null +++ b/app/javascript/controllers/results_controller.js @@ -0,0 +1,320 @@ +// Visit The Stimulus Handbook for more details +// https://stimulusjs.org/handbook/introduction +// +// This example controller works with specially annotated HTML like: +// +//
+//

+//
+ +import { Controller } from "stimulus" + +export default class extends Controller { + + connect() { + } + + checkedState(checked, selector='input[type=checkbox]') { + var aa = document.querySelectorAll(selector); + for (var i = 0; i < aa.length; i++){ + aa[i].checked = checked; + } + } + + setResultActionsVisibility(state) { + switch(state) { + case 'hide': + document.getElementById('result-selected-options').classList.add('hidden'); + break; + case 'show': + document.getElementById('result-selected-options').classList.remove('hidden'); + break; + default: + document.getElementById('result-selected-options').classList.add('hidden'); + } + } + + setResultSelectionVisibility(state) { + switch(state) { + case 'hide': + document.getElementById('result-selection-options').classList.add('hidden'); + break; + case 'show': + document.getElementById('result-selection-options').classList.remove('hidden'); + break; + default: + document.getElementById('result-selection-options').classList.add('hidden'); + } + } + + setResultOptionsVisibility(state) { + switch(state) { + case true: + this.setResultSelectionVisibility('show') + this.setResultActionsVisibility('show') + break; + case false: + this.setResultSelectionVisibility('hide') + this.setResultActionsVisibility('hide') + document.getElementById('select-resultset').classList.add('hidden'); + document.getElementById('select-pageset').classList.remove('hidden'); + break; + default: + this.setResultSelectionVisibility('hide') + this.setResultActionsVisibility('hide') + } + } + + selectResultSet() { + document.getElementById('select-pageset').classList.add('hidden'); + document.getElementById('select-resultset').classList.remove('hidden'); + + // Set scope to full resultset + var el = document.querySelector('#result-selected-options'); + el.setAttribute('data-scope', 'resultset'); + } + + removeResultSet() { + document.getElementById('select-pageset').classList.remove('hidden'); + document.getElementById('select-resultset').classList.add('hidden'); + + // Set scope to just pageset + var el = document.querySelector('#result-selected-options'); + el.setAttribute('data-scope', 'pageset'); + } + + toggleAll() { + var checked = document.querySelectorAll("input[type=checkbox]")[0].checked + this.checkedState(checked); + this.setResultOptionsVisibility(checked); + this.setPagesetURL(); + } + + selectAll() { + this.checkedState(true); + this.setResultSelectionVisibility('show'); + this.setResultActionsVisibility('show') + this.setPagesetURL(); + } + + selectNone() { + this.checkedState(false); + this.setResultSelectionVisibility('hide'); + this.setResultActionsVisibility('hide') + this.removeResultSet(); + + // Set selection scope + var el = document.querySelector('div#result-selection-options'); + el.setAttribute('data-scope', 'pageset'); + } + + selectBookmarked() { + this.checkedState(false); + this.checkedState(true, 'li.bookmarked > input[type=checkbox]'); + this.setResultSelectionVisibility('hide'); + this.setResultActionsVisibility('show'); + this.removeResultSet(); + this.setPagesetURL(); + } + + checkChecked() { + var checked = document.querySelectorAll('#results input[type="checkbox"]:checked'); + if(checked.length < 1) { + this.setResultActionsVisibility('hide'); + } else { + this.setResultActionsVisibility('show'); + } + + // Guard deselection + if (checked.length < 20) { + this.setResultSelectionVisibility('hide'); + // Set selection scope + var el = document.querySelector('div#result-selection-options'); + el.setAttribute('data-scope', 'pageset'); + } else { + this.setResultActionsVisibility('show'); + } + + // @TODO: make aware fo resultset count + // Guard deselection and reselection + if (checked.length === 20) { + this.setResultSelectionVisibility('show'); + } + + this.setPagesetURL(); + } + + checkSelectionScope() { + var el = document.querySelector('#result-selected-options'); + return el.dataset.scope + } + + setPagesetURL() { + // Find all checked checkboxes + var checked = document.querySelectorAll('#results input[type="checkbox"]:checked'); + + // Array of friendlier_ids + var selected = Array.from(checked).map(d => d.dataset.id); + + // Create params for fetch + var params = new URLSearchParams() + selected.forEach(function(item, index, array) { + params.append('ids[]', item) + }) + + // Set attribute value + var el = document.querySelector('#result-selected-options'); + el.setAttribute('data-pageset', '/admin/documents/fetch?' + params); + } + + exportCSV() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=csv" + } else { + window.location = el.dataset.resultset + "&format=csv" + } + } + + exportJSON() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=json" + } else { + window.location = el.dataset.resultset + "&format=json" + } + } + + exportJsonGBLv1() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=json_gbl_v1" + } else { + window.location = el.dataset.resultset + "&format=json_gbl_v1" + } + } + + exportJsonFile() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=json_file" + } else { + window.location = el.dataset.resultset + "&format=json_file" + } + } + + exportJsonAardvark() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=json_aardvark" + } else { + window.location = el.dataset.resultset + "&format=json_aardvark" + } + } + + exportJsonBtaaAardvark() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=json_btaa_aardvark" + } else { + window.location = el.dataset.resultset + "&format=json_btaa_aardvark" + } + } + + exportCsvDocumentDownloads() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=csv_document_downloads" + } else { + window.location = el.dataset.resultset + "&format=csv_document_downloads" + } + } + + exportCsvDocumentAccessLinks() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + window.location = el.dataset.pageset + "&format=csv_document_access_links" + } else { + window.location = el.dataset.resultset + "&format=csv_document_access_links" + } + } + + bulkAction() { + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + console.log('/admin/bulk_actions/new?scope=' + el.dataset.pageset) + window.location = '/admin/bulk_actions/new?scope=' + encodeURIComponent(el.dataset.pageset) + } else { + console.log('/admin/bulk_actions/new?scope=' + el.dataset.resultset) + window.location = '/admin/bulk_actions/new?scope=' + encodeURIComponent(el.dataset.resultset) + } + } + + setPubState(event) { + event.preventDefault(); + + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + scope = encodeURIComponent(el.dataset.pageset) + } else { + scope = encodeURIComponent(el.dataset.resultset) + } + + var el = document.querySelector('#bulk_action_scope'); + el.setAttribute('value', scope); + } + + setPubFieldNameValue(event) { + var el = document.querySelector('#bulk_action_field_name'); + el.setAttribute('value', "Publication State"); + + // Set field value + var el = document.querySelector('#bulk_action_field_value'); + el.setAttribute( + 'value', + event.currentTarget.innerHTML.toLowerCase().trim() + ); + + // Set scope value + this.setPubState(event); + + // Submit form + var form = document.querySelector('#result-action-form'); + form.submit(); + } + + bulkActionDelete(event) { + event.preventDefault(); + + var scope = this.checkSelectionScope(); + var el = document.querySelector('#result-selected-options'); + if(scope === 'pageset') { + scope = encodeURIComponent(el.dataset.pageset) + } else { + scope = encodeURIComponent(el.dataset.resultset) + } + + var el = document.querySelector('#bulk_action_scope'); + el.setAttribute('value', scope); + + var el = document.querySelector('#bulk_action_field_name'); + el.setAttribute('value', "Delete"); + + var el = document.querySelector('#bulk_action_field_value'); + el.setAttribute('value', "delete"); + + // Submit form + var form = document.querySelector('#result-action-form'); + form.submit(); + } +} diff --git a/app/javascript/m3/plugins/customIconPlugin.js b/app/javascript/m3/plugins/customIconPlugin.js index ec618e48b..3123c889d 100644 --- a/app/javascript/m3/plugins/customIconPlugin.js +++ b/app/javascript/m3/plugins/customIconPlugin.js @@ -1,3 +1,4 @@ +import 'url-polyfill/url-polyfill'; import { WindowTopBarPluginMenuCustomIcon } from '../components/WindowTopBarPluginMenuCustomIcon'; export default { diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js new file mode 100644 index 000000000..166de6d1c --- /dev/null +++ b/app/javascript/packs/application.js @@ -0,0 +1,23 @@ +// This file is automatically compiled by Webpack, along with any other files +// present in this directory. You're encouraged to place your actual application logic in +// a relevant structure within app/javascript and only use these pack files to reference +// that code so it'll be compiled. + +// @TODO: already loaded elsewhere? +// require("@rails/ujs").start() +require("turbolinks").start() +require("@rails/activestorage").start() +require("channels") + +import "bootstrap" + +// Uncomment to copy all static images under ../images to the output folder and reference +// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) +// or the `imagePath` JavaScript helper below. +// +// const images = require.context('../images', true) +// const imagePath = (name) => images(name, true) + +import "controllers" + +import '../src/js/admin/qa_autocomplete.js'; \ No newline at end of file diff --git a/app/javascript/src/js/admin/qa_autocomplete.js b/app/javascript/src/js/admin/qa_autocomplete.js new file mode 100644 index 000000000..922cb1065 --- /dev/null +++ b/app/javascript/src/js/admin/qa_autocomplete.js @@ -0,0 +1,1134 @@ +// Provide auto-suggest from qa (questioning authority) endpoints. (Or really anything that returns results +// in the same format as qa, but qa is what it is intended for). +// +// Add to a text field the HTML attribute `data-scihist-qa-autocomplete=/path/to/qa/search`, and your +// text field, as you type in it, will get dropdown menu of sugggestions from the QA-delivered vocabulary. +// You can still enter 'manual' entries that were not from vocabulary. +// +// For qa vocabularly sources that return a :label and a :value, like FAST, the :label shows up +// in the suggestions, but when chosen the :value is what gets put in the textbox. For FAST, +// qa delivers results such as label=`Pennsylvania--Philadelphie USE Pennsylvania--Philadelphia`, +// value=`Pennsylvania--Philadelphia`. +// +// The `id` attribute returned in qa JSON response (which might be unique identifier from FAST or +// other vocabulary) -- is currently ignored, not displayed or preserved in any way. +// +// All this behavior is meant to match what we had in chf_sufia with hydra-editor or whatever other samvera +// dependencies were providing (not sure) +// +// +// ## Implementation +// +// The auto-suggest from remote AJAX source uses the devbridge-autocomplete/jquery-autocomplete +// jQuery plugin. https://github.com/devbridge/jQuery-Autocomplete . This was the most suitable +// pre-made thing I found with extensive looking (including trying to find things not dependent +// on jQuery). +// +// It still required a bit of hacking to get it to work. In particular, to get the behavior above +// for "USE" examples, where the string shown in the suggestions is not the thing that ends up +// in your text box if you select it -- that really confused the jquery-autocomplete plugin, +// it kept wanting to show a new set of suggestions when to our UX nothing had changed. +// +// This was made worse by a bug around onFocus (https://github.com/devbridge/jQuery-Autocomplete/issues/766) +// -- although really we wanted to disable "show suggestions onFocus" altogether to match +// chf_sufia behavior. +// +// We fix things up mostly with a few kind of hacky private API interventions into the plugin -- +// but hey, this still isn't much code, and the plugin isn't getting much development so +// it probably won't break. +// +// We could try to add features we need upstream (https://github.com/devbridge/jQuery-Autocomplete/issues/769), +// we could consider forking this (it's not actually much code), or we could in the future provide a +// better alternate tool for a JS auto-suggest UI. + +import 'jquery' + +// https://github.com/devbridge/jQuery-Autocomplete +/** +* Ajax Autocomplete for jQuery, version 1.4.10 +* (c) 2017 Tomas Kirda +* +* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license. +* For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete +*/ + +/*jslint browser: true, white: true, single: true, this: true, multivar: true */ +/*global define, window, document, jQuery, exports, require */ + +// Expose plugin as an AMD module if AMD loader is present: +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof exports === 'object' && typeof require === 'function') { + // Browserify + factory(require('jquery')); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + 'use strict'; + + var + utils = (function () { + return { + escapeRegExChars: function (value) { + return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); + }, + createNode: function (containerClass) { + var div = document.createElement('div'); + div.className = containerClass; + div.style.position = 'absolute'; + div.style.display = 'none'; + return div; + } + }; + }()), + + keys = { + ESC: 27, + TAB: 9, + RETURN: 13, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40 + }, + + noop = $.noop; + + function Autocomplete(el, options) { + var that = this; + + // Shared variables: + that.element = el; + that.el = $(el); + that.suggestions = []; + that.badQueries = []; + that.selectedIndex = -1; + that.currentValue = that.element.value; + that.timeoutId = null; + that.cachedResponse = {}; + that.onChangeTimeout = null; + that.onChange = null; + that.isLocal = false; + that.suggestionsContainer = null; + that.noSuggestionsContainer = null; + that.options = $.extend(true, {}, Autocomplete.defaults, options); + that.classes = { + selected: 'autocomplete-selected', + suggestion: 'autocomplete-suggestion' + }; + that.hint = null; + that.hintValue = ''; + that.selection = null; + + // Initialize and set options: + that.initialize(); + that.setOptions(options); + } + + Autocomplete.utils = utils; + + $.Autocomplete = Autocomplete; + + Autocomplete.defaults = { + ajaxSettings: {}, + autoSelectFirst: false, + appendTo: 'body', + serviceUrl: null, + lookup: null, + onSelect: null, + width: 'auto', + minChars: 1, + maxHeight: 300, + deferRequestBy: 0, + params: {}, + formatResult: _formatResult, + formatGroup: _formatGroup, + delimiter: null, + zIndex: 9999, + type: 'GET', + noCache: false, + onSearchStart: noop, + onSearchComplete: noop, + onSearchError: noop, + preserveInput: false, + containerClass: 'autocomplete-suggestions', + tabDisabled: false, + dataType: 'text', + currentRequest: null, + triggerSelectOnValidInput: true, + preventBadQueries: true, + lookupFilter: _lookupFilter, + paramName: 'query', + transformResult: _transformResult, + showNoSuggestionNotice: false, + noSuggestionNotice: 'No results', + orientation: 'bottom', + forceFixPosition: false + }; + + function _lookupFilter(suggestion, originalQuery, queryLowerCase) { + return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1; + }; + + function _transformResult(response) { + return typeof response === 'string' ? $.parseJSON(response) : response; + }; + + function _formatResult(suggestion, currentValue) { + // Do not replace anything if the current value is empty + if (!currentValue) { + return suggestion.value; + } + + var pattern = '(' + utils.escapeRegExChars(currentValue) + ')'; + + return suggestion.value + .replace(new RegExp(pattern, 'gi'), '$1<\/strong>') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/<(\/?strong)>/g, '<$1>'); + }; + + function _formatGroup(suggestion, category) { + return '
' + category + '
'; + }; + + Autocomplete.prototype = { + + initialize: function () { + var that = this, + suggestionSelector = '.' + that.classes.suggestion, + selected = that.classes.selected, + options = that.options, + container; + + that.element.setAttribute('autocomplete', 'off'); + + // html() deals with many types: htmlString or Element or Array or jQuery + that.noSuggestionsContainer = $('
') + .html(this.options.noSuggestionNotice).get(0); + + that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass); + + container = $(that.suggestionsContainer); + + container.appendTo(options.appendTo || 'body'); + + // Only set width if it was provided: + if (options.width !== 'auto') { + container.css('width', options.width); + } + + // Listen for mouse over event on suggestions list: + container.on('mouseover.autocomplete', suggestionSelector, function () { + that.activate($(this).data('index')); + }); + + // Deselect active element when mouse leaves suggestions container: + container.on('mouseout.autocomplete', function () { + that.selectedIndex = -1; + container.children('.' + selected).removeClass(selected); + }); + + // Listen for click event on suggestions list: + container.on('click.autocomplete', suggestionSelector, function () { + that.select($(this).data('index')); + }); + + container.on('click.autocomplete', function () { + clearTimeout(that.blurTimeoutId); + }) + + that.fixPositionCapture = function () { + if (that.visible) { + that.fixPosition(); + } + }; + + $(window).on('resize.autocomplete', that.fixPositionCapture); + + that.el.on('keydown.autocomplete', function (e) { that.onKeyPress(e); }); + that.el.on('keyup.autocomplete', function (e) { that.onKeyUp(e); }); + that.el.on('blur.autocomplete', function () { that.onBlur(); }); + that.el.on('focus.autocomplete', function () { that.onFocus(); }); + that.el.on('change.autocomplete', function (e) { that.onKeyUp(e); }); + that.el.on('input.autocomplete', function (e) { that.onKeyUp(e); }); + }, + + onFocus: function () { + var that = this; + + that.fixPosition(); + + if (that.el.val().length >= that.options.minChars) { + that.onValueChange(); + } + }, + + onBlur: function () { + var that = this, + options = that.options, + value = that.el.val(), + query = that.getQuery(value); + + // If user clicked on a suggestion, hide() will + // be canceled, otherwise close suggestions + that.blurTimeoutId = setTimeout(function () { + that.hide(); + + if (that.selection && that.currentValue !== query) { + (options.onInvalidateSelection || $.noop).call(that.element); + } + }, 200); + }, + + abortAjax: function () { + var that = this; + if (that.currentRequest) { + that.currentRequest.abort(); + that.currentRequest = null; + } + }, + + setOptions: function (suppliedOptions) { + var that = this, + options = $.extend({}, that.options, suppliedOptions); + + that.isLocal = Array.isArray(options.lookup); + + if (that.isLocal) { + options.lookup = that.verifySuggestionsFormat(options.lookup); + } + + options.orientation = that.validateOrientation(options.orientation, 'bottom'); + + // Adjust height, width and z-index: + $(that.suggestionsContainer).css({ + 'max-height': options.maxHeight + 'px', + 'width': options.width + 'px', + 'z-index': options.zIndex + }); + + this.options = options; + }, + + + clearCache: function () { + this.cachedResponse = {}; + this.badQueries = []; + }, + + clear: function () { + this.clearCache(); + this.currentValue = ''; + this.suggestions = []; + }, + + disable: function () { + var that = this; + that.disabled = true; + clearTimeout(that.onChangeTimeout); + that.abortAjax(); + }, + + enable: function () { + this.disabled = false; + }, + + fixPosition: function () { + // Use only when container has already its content + + var that = this, + $container = $(that.suggestionsContainer), + containerParent = $container.parent().get(0); + // Fix position automatically when appended to body. + // In other cases force parameter must be given. + if (containerParent !== document.body && !that.options.forceFixPosition) { + return; + } + + // Choose orientation + var orientation = that.options.orientation, + containerHeight = $container.outerHeight(), + height = that.el.outerHeight(), + offset = that.el.offset(), + styles = { 'top': offset.top, 'left': offset.left }; + + if (orientation === 'auto') { + var viewPortHeight = $(window).height(), + scrollTop = $(window).scrollTop(), + topOverflow = -scrollTop + offset.top - containerHeight, + bottomOverflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight); + + orientation = (Math.max(topOverflow, bottomOverflow) === topOverflow) ? 'top' : 'bottom'; + } + + if (orientation === 'top') { + styles.top += -containerHeight; + } else { + styles.top += height; + } + + // If container is not positioned to body, + // correct its position using offset parent offset + if(containerParent !== document.body) { + var opacity = $container.css('opacity'), + parentOffsetDiff; + + if (!that.visible){ + $container.css('opacity', 0).show(); + } + + parentOffsetDiff = $container.offsetParent().offset(); + styles.top -= parentOffsetDiff.top; + styles.top += containerParent.scrollTop; + styles.left -= parentOffsetDiff.left; + + if (!that.visible){ + $container.css('opacity', opacity).hide(); + } + } + + if (that.options.width === 'auto') { + styles.width = that.el.outerWidth() + 'px'; + } + + $container.css(styles); + }, + + isCursorAtEnd: function () { + var that = this, + valLength = that.el.val().length, + selectionStart = that.element.selectionStart, + range; + + if (typeof selectionStart === 'number') { + return selectionStart === valLength; + } + if (document.selection) { + range = document.selection.createRange(); + range.moveStart('character', -valLength); + return valLength === range.text.length; + } + return true; + }, + + onKeyPress: function (e) { + var that = this; + + // If suggestions are hidden and user presses arrow down, display suggestions: + if (!that.disabled && !that.visible && e.which === keys.DOWN && that.currentValue) { + that.suggest(); + return; + } + + if (that.disabled || !that.visible) { + return; + } + + switch (e.which) { + case keys.ESC: + that.el.val(that.currentValue); + that.hide(); + break; + case keys.RIGHT: + if (that.hint && that.options.onHint && that.isCursorAtEnd()) { + that.selectHint(); + break; + } + return; + case keys.TAB: + if (that.hint && that.options.onHint) { + that.selectHint(); + return; + } + if (that.selectedIndex === -1) { + that.hide(); + return; + } + that.select(that.selectedIndex); + if (that.options.tabDisabled === false) { + return; + } + break; + case keys.RETURN: + if (that.selectedIndex === -1) { + that.hide(); + return; + } + that.select(that.selectedIndex); + break; + case keys.UP: + that.moveUp(); + break; + case keys.DOWN: + that.moveDown(); + break; + default: + return; + } + + // Cancel event if function did not return: + e.stopImmediatePropagation(); + e.preventDefault(); + }, + + onKeyUp: function (e) { + var that = this; + + if (that.disabled) { + return; + } + + switch (e.which) { + case keys.UP: + case keys.DOWN: + return; + } + + clearTimeout(that.onChangeTimeout); + + if (that.currentValue !== that.el.val()) { + that.findBestHint(); + if (that.options.deferRequestBy > 0) { + // Defer lookup in case when value changes very quickly: + that.onChangeTimeout = setTimeout(function () { + that.onValueChange(); + }, that.options.deferRequestBy); + } else { + that.onValueChange(); + } + } + }, + + onValueChange: function () { + if (this.ignoreValueChange) { + this.ignoreValueChange = false; + return; + } + + var that = this, + options = that.options, + value = that.el.val(), + query = that.getQuery(value); + + if (that.selection && that.currentValue !== query) { + that.selection = null; + (options.onInvalidateSelection || $.noop).call(that.element); + } + + clearTimeout(that.onChangeTimeout); + that.currentValue = value; + that.selectedIndex = -1; + + // Check existing suggestion for the match before proceeding: + if (options.triggerSelectOnValidInput && that.isExactMatch(query)) { + that.select(0); + return; + } + + if (query.length < options.minChars) { + that.hide(); + } else { + that.getSuggestions(query); + } + }, + + isExactMatch: function (query) { + var suggestions = this.suggestions; + + return (suggestions.length === 1 && suggestions[0].value.toLowerCase() === query.toLowerCase()); + }, + + getQuery: function (value) { + var delimiter = this.options.delimiter, + parts; + + if (!delimiter) { + return value; + } + parts = value.split(delimiter); + return $.trim(parts[parts.length - 1]); + }, + + getSuggestionsLocal: function (query) { + var that = this, + options = that.options, + queryLowerCase = query.toLowerCase(), + filter = options.lookupFilter, + limit = parseInt(options.lookupLimit, 10), + data; + + data = { + suggestions: $.grep(options.lookup, function (suggestion) { + return filter(suggestion, query, queryLowerCase); + }) + }; + + if (limit && data.suggestions.length > limit) { + data.suggestions = data.suggestions.slice(0, limit); + } + + return data; + }, + + getSuggestions: function (q) { + var response, + that = this, + options = that.options, + serviceUrl = options.serviceUrl, + params, + cacheKey, + ajaxSettings; + + options.params[options.paramName] = q; + + if (options.onSearchStart.call(that.element, options.params) === false) { + return; + } + + params = options.ignoreParams ? null : options.params; + + if ($.isFunction(options.lookup)){ + options.lookup(q, function (data) { + that.suggestions = data.suggestions; + that.suggest(); + options.onSearchComplete.call(that.element, q, data.suggestions); + }); + return; + } + + if (that.isLocal) { + response = that.getSuggestionsLocal(q); + } else { + if ($.isFunction(serviceUrl)) { + serviceUrl = serviceUrl.call(that.element, q); + } + cacheKey = serviceUrl + '?' + $.param(params || {}); + response = that.cachedResponse[cacheKey]; + } + + if (response && Array.isArray(response.suggestions)) { + that.suggestions = response.suggestions; + that.suggest(); + options.onSearchComplete.call(that.element, q, response.suggestions); + } else if (!that.isBadQuery(q)) { + that.abortAjax(); + + ajaxSettings = { + url: serviceUrl, + data: params, + type: options.type, + dataType: options.dataType + }; + + $.extend(ajaxSettings, options.ajaxSettings); + + that.currentRequest = $.ajax(ajaxSettings).done(function (data) { + var result; + that.currentRequest = null; + result = options.transformResult(data, q); + that.processResponse(result, q, cacheKey); + options.onSearchComplete.call(that.element, q, result.suggestions); + }).fail(function (jqXHR, textStatus, errorThrown) { + options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown); + }); + } else { + options.onSearchComplete.call(that.element, q, []); + } + }, + + isBadQuery: function (q) { + if (!this.options.preventBadQueries){ + return false; + } + + var badQueries = this.badQueries, + i = badQueries.length; + + while (i--) { + if (q.indexOf(badQueries[i]) === 0) { + return true; + } + } + + return false; + }, + + hide: function () { + var that = this, + container = $(that.suggestionsContainer); + + if ($.isFunction(that.options.onHide) && that.visible) { + that.options.onHide.call(that.element, container); + } + + that.visible = false; + that.selectedIndex = -1; + clearTimeout(that.onChangeTimeout); + $(that.suggestionsContainer).hide(); + that.signalHint(null); + }, + + suggest: function () { + if (!this.suggestions.length) { + if (this.options.showNoSuggestionNotice) { + this.noSuggestions(); + } else { + this.hide(); + } + return; + } + + var that = this, + options = that.options, + groupBy = options.groupBy, + formatResult = options.formatResult, + value = that.getQuery(that.currentValue), + className = that.classes.suggestion, + classSelected = that.classes.selected, + container = $(that.suggestionsContainer), + noSuggestionsContainer = $(that.noSuggestionsContainer), + beforeRender = options.beforeRender, + html = '', + category, + formatGroup = function (suggestion, index) { + var currentCategory = suggestion.data[groupBy]; + + if (category === currentCategory){ + return ''; + } + + category = currentCategory; + + return options.formatGroup(suggestion, category); + }; + + if (options.triggerSelectOnValidInput && that.isExactMatch(value)) { + that.select(0); + return; + } + + // Build suggestions inner HTML: + $.each(that.suggestions, function (i, suggestion) { + if (groupBy){ + html += formatGroup(suggestion, value, i); + } + + html += '
' + formatResult(suggestion, value, i) + '
'; + }); + + this.adjustContainerWidth(); + + noSuggestionsContainer.detach(); + container.html(html); + + if ($.isFunction(beforeRender)) { + beforeRender.call(that.element, container, that.suggestions); + } + + that.fixPosition(); + container.show(); + + // Select first value by default: + if (options.autoSelectFirst) { + that.selectedIndex = 0; + container.scrollTop(0); + container.children('.' + className).first().addClass(classSelected); + } + + that.visible = true; + that.findBestHint(); + }, + + noSuggestions: function() { + var that = this, + beforeRender = that.options.beforeRender, + container = $(that.suggestionsContainer), + noSuggestionsContainer = $(that.noSuggestionsContainer); + + this.adjustContainerWidth(); + + // Some explicit steps. Be careful here as it easy to get + // noSuggestionsContainer removed from DOM if not detached properly. + noSuggestionsContainer.detach(); + + // clean suggestions if any + container.empty(); + container.append(noSuggestionsContainer); + + if ($.isFunction(beforeRender)) { + beforeRender.call(that.element, container, that.suggestions); + } + + that.fixPosition(); + + container.show(); + that.visible = true; + }, + + adjustContainerWidth: function() { + var that = this, + options = that.options, + width, + container = $(that.suggestionsContainer); + + // If width is auto, adjust width before displaying suggestions, + // because if instance was created before input had width, it will be zero. + // Also it adjusts if input width has changed. + if (options.width === 'auto') { + width = that.el.outerWidth(); + container.css('width', width > 0 ? width : 300); + } else if(options.width === 'flex') { + // Trust the source! Unset the width property so it will be the max length + // the containing elements. + container.css('width', ''); + } + }, + + findBestHint: function () { + var that = this, + value = that.el.val().toLowerCase(), + bestMatch = null; + + if (!value) { + return; + } + + $.each(that.suggestions, function (i, suggestion) { + var foundMatch = suggestion.value.toLowerCase().indexOf(value) === 0; + if (foundMatch) { + bestMatch = suggestion; + } + return !foundMatch; + }); + + that.signalHint(bestMatch); + }, + + signalHint: function (suggestion) { + var hintValue = '', + that = this; + if (suggestion) { + hintValue = that.currentValue + suggestion.value.substr(that.currentValue.length); + } + if (that.hintValue !== hintValue) { + that.hintValue = hintValue; + that.hint = suggestion; + (this.options.onHint || $.noop)(hintValue); + } + }, + + verifySuggestionsFormat: function (suggestions) { + // If suggestions is string array, convert them to supported format: + if (suggestions.length && typeof suggestions[0] === 'string') { + return $.map(suggestions, function (value) { + return { value: value, data: null }; + }); + } + + return suggestions; + }, + + validateOrientation: function(orientation, fallback) { + orientation = $.trim(orientation || '').toLowerCase(); + + if($.inArray(orientation, ['auto', 'bottom', 'top']) === -1){ + orientation = fallback; + } + + return orientation; + }, + + processResponse: function (result, originalQuery, cacheKey) { + var that = this, + options = that.options; + + result.suggestions = that.verifySuggestionsFormat(result.suggestions); + + // Cache results if cache is not disabled: + if (!options.noCache) { + that.cachedResponse[cacheKey] = result; + if (options.preventBadQueries && !result.suggestions.length) { + that.badQueries.push(originalQuery); + } + } + + // Return if originalQuery is not matching current query: + if (originalQuery !== that.getQuery(that.currentValue)) { + return; + } + + that.suggestions = result.suggestions; + that.suggest(); + }, + + activate: function (index) { + var that = this, + activeItem, + selected = that.classes.selected, + container = $(that.suggestionsContainer), + children = container.find('.' + that.classes.suggestion); + + container.find('.' + selected).removeClass(selected); + + that.selectedIndex = index; + + if (that.selectedIndex !== -1 && children.length > that.selectedIndex) { + activeItem = children.get(that.selectedIndex); + $(activeItem).addClass(selected); + return activeItem; + } + + return null; + }, + + selectHint: function () { + var that = this, + i = $.inArray(that.hint, that.suggestions); + + that.select(i); + }, + + select: function (i) { + var that = this; + that.hide(); + that.onSelect(i); + }, + + moveUp: function () { + var that = this; + + if (that.selectedIndex === -1) { + return; + } + + if (that.selectedIndex === 0) { + $(that.suggestionsContainer).children('.' + that.classes.suggestion).first().removeClass(that.classes.selected); + that.selectedIndex = -1; + that.ignoreValueChange = false; + that.el.val(that.currentValue); + that.findBestHint(); + return; + } + + that.adjustScroll(that.selectedIndex - 1); + }, + + moveDown: function () { + var that = this; + + if (that.selectedIndex === (that.suggestions.length - 1)) { + return; + } + + that.adjustScroll(that.selectedIndex + 1); + }, + + adjustScroll: function (index) { + var that = this, + activeItem = that.activate(index); + + if (!activeItem) { + return; + } + + var offsetTop, + upperBound, + lowerBound, + heightDelta = $(activeItem).outerHeight(); + + offsetTop = activeItem.offsetTop; + upperBound = $(that.suggestionsContainer).scrollTop(); + lowerBound = upperBound + that.options.maxHeight - heightDelta; + + if (offsetTop < upperBound) { + $(that.suggestionsContainer).scrollTop(offsetTop); + } else if (offsetTop > lowerBound) { + $(that.suggestionsContainer).scrollTop(offsetTop - that.options.maxHeight + heightDelta); + } + + if (!that.options.preserveInput) { + // During onBlur event, browser will trigger "change" event, + // because value has changed, to avoid side effect ignore, + // that event, so that correct suggestion can be selected + // when clicking on suggestion with a mouse + that.ignoreValueChange = true; + that.el.val(that.getValue(that.suggestions[index].value)); + } + + that.signalHint(null); + }, + + onSelect: function (index) { + var that = this, + onSelectCallback = that.options.onSelect, + suggestion = that.suggestions[index]; + + that.currentValue = that.getValue(suggestion.value); + + if (that.currentValue !== that.el.val() && !that.options.preserveInput) { + that.el.val(that.currentValue); + } + + that.signalHint(null); + that.suggestions = []; + that.selection = suggestion; + + if ($.isFunction(onSelectCallback)) { + onSelectCallback.call(that.element, suggestion); + } + }, + + getValue: function (value) { + var that = this, + delimiter = that.options.delimiter, + currentValue, + parts; + + if (!delimiter) { + return value; + } + + currentValue = that.currentValue; + parts = currentValue.split(delimiter); + + if (parts.length === 1) { + return value; + } + + return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value; + }, + + dispose: function () { + var that = this; + that.el.off('.autocomplete').removeData('autocomplete'); + $(window).off('resize.autocomplete', that.fixPositionCapture); + $(that.suggestionsContainer).remove(); + } + }; + + // Create chainable jQuery plugin: + $.fn.devbridgeAutocomplete = function (options, args) { + var dataKey = 'autocomplete'; + // If function invoked without argument return + // instance of the first matched element: + if (!arguments.length) { + return this.first().data(dataKey); + } + + return this.each(function () { + var inputElement = $(this), + instance = inputElement.data(dataKey); + + if (typeof options === 'string') { + if (instance && typeof instance[options] === 'function') { + instance[options](args); + } + } else { + // If instance already exists, destroy it: + if (instance && instance.dispose) { + instance.dispose(); + } + instance = new Autocomplete(this, options); + inputElement.data(dataKey, instance); + } + }); + }; + + // Don't overwrite if it already exists + if (!$.fn.autocomplete) { + $.fn.autocomplete = $.fn.devbridgeAutocomplete; + } +})); + +var errorContainer = $('
') + .html(" Error fetching results").get(0); + +function addAutocomplete(element) { + var input_el = $(element); + console.log(input_el); + + var qa_search_url = input_el.data("scihist-qa-autocomplete"); + + input_el.autocomplete({ + deferRequestBy: 600, // bunch keystrokes into 600ms groups for requests + paramName: "q", + minChars: 2, + maxHeight: 700, + preserveInput: true, // our custom onSelect instead + showNoSuggestionNotice: true, + serviceUrl: qa_search_url, + + onSearchError: function (query, jqXHR, textStatus, errorThrown) { + console.log("autocomplete error fetching results: " + textStatus + ": " + errorThrown); + + // Pretty hacky way to show error message in dropdown, reaching into + // autocomplete internals. Based on how autocomplete shows no-results message. + var container = $($(this).autocomplete().suggestionsContainer) + container.empty(); + container.append(errorContainer); + container.show(); + }, + + transformResult: function(response) { + // not sure why it's a string instead of json already... + if (typeof response == "string") { + response = JSON.parse(response); + } + + return { + suggestions: $.map(response, function(dataItem) { + return { value: dataItem.label, data: dataItem.value }; + }) + }; + }, + + onSelect: function(suggestion) { + // Set the text input to `data`, not the `value` that was being shown. + // + // However, the autocomplete JS is confused if we set a value to the textbox + // different than the the string that was displayed in the menu, and wants + // to show suggestions for the new string. We disable and re-enable + // only on additional text entry in the box, to get around this in a hacky way. + // + // Still has SOME weird cases where autosuggest will show up when you don't think + // you've changed anything, but minimized and that's not too horrible. + var input = $(this); + input.autocomplete('disable'); + this.value = suggestion.data || suggestion.value; + + $(this).one("keydown", function() { input.autocomplete("enable") }) + } + }); + + // hack to break in and disable the autocomplete onFocus, cause we don't + // WANT to autocomplete on focus, plus it's broken with 'disabled' state, + // that keeps us from working around re-suggest on select + input_el.autocomplete().onFocus = function() {}; +} + +// Uses jquery, assumes it exists in `window` for now. + +jQuery( document ).ready(function() { + // When an input is focused, see if it already has autocomplete plugin added, + // if not add it. This makes it work for suitable new input elements added + // to the DOM (in response to 'add another' links), even if they weren't + // there on page at load. + $("body").on("focus", "*[data-scihist-qa-autocomplete]", function(event) { + var el = $(event.target); + console.log(el); + + if (! el.data("autocomplete")) { + // hasn't already had autocomplete plugin added, so add it. + addAutocomplete(event.target) + } + }); +}); diff --git a/app/models/solr_document_sidecar.rb b/app/models/solr_document_sidecar.rb index 81bb15301..9fb198a01 100644 --- a/app/models/solr_document_sidecar.rb +++ b/app/models/solr_document_sidecar.rb @@ -3,7 +3,15 @@ ## # Metadata for indexed documents class SolrDocumentSidecar < ApplicationRecord - include Statesman::Adapters::ActiveRecordQueries + include Statesman::Adapters::ActiveRecordQueries[ + transition_class: ImageUploadTransition, + initial_state: :initialized + ] + + include Statesman::Adapters::ActiveRecordQueries[ + transition_class: SidecarImageTransition, + initial_state: :initialized + ] # Deprecated - Carrierwave mount_uploader :cw_image, ImageUploader diff --git a/app/models/solr_document_uri.rb b/app/models/solr_document_uri.rb index 3a7008758..73ba837ca 100644 --- a/app/models/solr_document_uri.rb +++ b/app/models/solr_document_uri.rb @@ -1,7 +1,10 @@ # frozen_string_literal: true class SolrDocumentUri < ApplicationRecord - include Statesman::Adapters::ActiveRecordQueries + include Statesman::Adapters::ActiveRecordQueries[ + transition_class: UriTransition, + initial_state: :initialized + ] belongs_to :document, required: true, polymorphic: true has_many :uri_transitions, autosave: false, dependent: :destroy diff --git a/app/models/user.rb b/app/models/user.rb index 55dec57d6..89307d3de 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,9 +2,9 @@ class User < ApplicationRecord # Connects this user object to Blacklights Bookmarks. include Blacklight::User # Include default devise modules. Others available are: - # :confirmable, :lockable, :timeoutable and :omniauthable - devise :database_authenticatable, :registerable, - :recoverable, :rememberable, :trackable, :validatable + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + devise :invitable, :database_authenticatable, + :recoverable, :rememberable, :validatable # Method added by Blacklight; Blacklight uses #to_s on your # user class to get a user-displayable login/identifier for @@ -12,4 +12,19 @@ class User < ApplicationRecord def to_s email end + + has_many :bookmarks, dependent: :destroy, as: :user + has_many :notifications, dependent: :destroy, as: :recipient + + def bookmarks_for_documents(documents = []) + if documents.any? + bookmarks.where(document_type: documents.first.class.base_class.to_s, document_id: documents.map(&:id)) + else + [] + end + end + + def document_is_bookmarked?(document) + bookmarks_for_documents([document]).any? + end end diff --git a/app/views/catalog/_home_text.html.erb b/app/views/catalog/_home_text.html.erb index a050662df..a2d3b82fc 100644 --- a/app/views/catalog/_home_text.html.erb +++ b/app/views/catalog/_home_text.html.erb @@ -1,4 +1,4 @@ -
+
diff --git a/app/views/catalog/_show_sidebar.html.erb b/app/views/catalog/_show_sidebar.html.erb index 79f5c1a75..0f12b7212 100644 --- a/app/views/catalog/_show_sidebar.html.erb +++ b/app/views/catalog/_show_sidebar.html.erb @@ -7,6 +7,10 @@ <%= render(Blacklight::SearchContextComponent.new(search_context: @search_context, search_session: search_session)) if search_session['document_id'] == @document.id %> +
+ <%= render :partial => "show_gbl_admin" %> +
+ <%= render :partial => 'show_sidebar_static_map' if render_sidebar_map?(@document) %> <%= render :partial => 'show_tools' %> diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb new file mode 100644 index 000000000..cf9dc7355 --- /dev/null +++ b/app/views/devise/confirmations/new.html.erb @@ -0,0 +1,16 @@ +

<%= t('.resend_confirmation_instructions') %>

+ +<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> + <%= bootstrap_devise_error_messages! %> + +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: 'email', value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email), class: 'form-control' %> +
+ +
+ <%= f.submit t('.resend_confirmation_instructions'), class: 'btn btn-primary' %> +
+<% end %> + +<%= render 'devise/shared/links' %> diff --git a/app/views/devise/invitations/edit.html.erb b/app/views/devise/invitations/edit.html.erb new file mode 100644 index 000000000..7b7aec5fe --- /dev/null +++ b/app/views/devise/invitations/edit.html.erb @@ -0,0 +1,15 @@ +

<%= t "devise.invitations.edit.header" %>

+ +<%= simple_form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :put }) do |f| %> + <%= f.error_notification %> + <%= f.hidden_field :invitation_token %> + +
+ <%= f.input :password %> + <%= f.input :password_confirmation %> +
+ +
+ <%= f.button :submit, t("devise.invitations.edit.submit_button"), class: 'btn btn-primary' %> +
+<% end %> diff --git a/app/views/devise/invitations/new.html.erb b/app/views/devise/invitations/new.html.erb new file mode 100644 index 000000000..f4482d4db --- /dev/null +++ b/app/views/devise/invitations/new.html.erb @@ -0,0 +1,15 @@ +

<%= t "devise.invitations.new.header" %>

+ +<%= simple_form_for(resource, as: resource_name, url: invitation_path(resource_name), html: { method: :post }) do |f| %> + <%= f.error_notification %> + + <% resource.class.invite_key_fields.each do |field| -%> +
+ <%= f.input field %> +
+ <% end -%> + +
+ <%= f.button :submit, t("devise.invitations.new.submit_button"), class: 'btn btn-primary' %> +
+<% end %> diff --git a/app/views/devise/mailer/invitation_instructions.html.erb b/app/views/devise/mailer/invitation_instructions.html.erb new file mode 100644 index 000000000..3f1658c68 --- /dev/null +++ b/app/views/devise/mailer/invitation_instructions.html.erb @@ -0,0 +1,11 @@ +

<%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %>

+ +

<%= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url) %>

+ +

<%= link_to t("devise.mailer.invitation_instructions.accept"), accept_admin_user_invitation_url(@resource, invitation_token: @token) %>

+ +<% if @resource.invitation_due_at %> +

<%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %>

+<% end %> + +

<%= t("devise.mailer.invitation_instructions.ignore") %>

diff --git a/app/views/devise/mailer/invitation_instructions.text.erb b/app/views/devise/mailer/invitation_instructions.text.erb new file mode 100644 index 000000000..7eb91ea5f --- /dev/null +++ b/app/views/devise/mailer/invitation_instructions.text.erb @@ -0,0 +1,11 @@ +<%= t("devise.mailer.invitation_instructions.hello", email: @resource.email) %> + +<%= t("devise.mailer.invitation_instructions.someone_invited_you", url: root_url) %> + +<%= accept_admin_user_invitation_url(@resource, invitation_token: @token) %> + +<% if @resource.invitation_due_at %> + <%= t("devise.mailer.invitation_instructions.accept_until", due_date: l(@resource.invitation_due_at, format: :'devise.mailer.invitation_instructions.accept_until_format')) %> +<% end %> + +<%= t("devise.mailer.invitation_instructions.ignore") %> diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 000000000..acdc16797 --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb @@ -0,0 +1,26 @@ +

<%= t('.change_your_password') %>

+ +<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> + <%= bootstrap_devise_error_messages! %> + <%= f.hidden_field :reset_password_token %> + +
+ <%= f.label :password, t('.new_password') %> + <%= f.password_field :password, autofocus: true, class: 'form-control' %> + + <% if @minimum_password_length %> + <%= t('devise.shared.minimum_password_length', count: @minimum_password_length) %> + <% end %> +
+ +
+ <%= f.label :password_confirmation, t('.confirm_new_password') %> + <%= f.password_field :password_confirmation, autocomplete: 'off', class: 'form-control' %> +
+ +
+ <%= f.submit t('.change_my_password'), class: 'btn btn-primary' %> +
+<% end %> + +<%= render 'devise/shared/links' %> diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb new file mode 100644 index 000000000..37e3008ce --- /dev/null +++ b/app/views/devise/passwords/new.html.erb @@ -0,0 +1,16 @@ +

<%= t('.forgot_your_password') %>

+ +<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> + <%= bootstrap_devise_error_messages! %> + +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control' %> +
+ +
+ <%= f.submit t('.send_me_reset_password_instructions'), class: 'btn btn-primary' %> +
+<% end %> + +<%= render 'devise/shared/links' %> diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb new file mode 100644 index 000000000..47c7f5d07 --- /dev/null +++ b/app/views/devise/registrations/edit.html.erb @@ -0,0 +1,37 @@ +

<%= t('.title', resource: resource_name.to_s.humanize) %>

+ +<%= form_for(resource, as: resource_name, url: user_registration_path(resource_name), html: { method: :put }) do |f| %> + <%= bootstrap_devise_error_messages! %> + +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control' %> +
+ +
+ <%= f.label :password %> + <%= f.password_field :password, autocomplete: 'new-password', class: 'form-control' %> + + <%= t('.leave_blank_if_you_don_t_want_to_change_it') %> +
+ +
+ <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation, autocomplete: 'new-password', class: 'form-control' %> +
+ +
+ <%= f.label :current_password %> + <%= f.password_field :current_password, autocomplete: 'current-password', class: 'form-control' %> + + <%= t('.we_need_your_current_password_to_confirm_your_changes') %> +
+ +
+ <%= f.submit t('.update'), class: 'btn btn-primary' %> +
+<% end %> + +

<%= t('.unhappy') %>? <%= link_to t('.cancel_my_account'), user_registration_path(resource_name), data: { confirm: t('.are_you_sure') }, method: :delete %>.

+ +<%= link_to t('.back'), :back %> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb new file mode 100644 index 000000000..3a95df670 --- /dev/null +++ b/app/views/devise/registrations/new.html.erb @@ -0,0 +1,30 @@ +

<%= t('.sign_up') %>

+ +<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> + <%= bootstrap_devise_error_messages! %> + +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control' %> +
+ +
+ <%= f.label :password %> + <%= f.password_field :password, autocomplete: 'current-password', class: 'form-control' %> + + <% if @minimum_password_length %> + <%= t('devise.shared.minimum_password_length', count: @minimum_password_length) %> + <% end %> +
+ +
+ <%= f.label :password_confirmation %> + <%= f.password_field :password_confirmation, autocomplete: 'current-password', class: 'form-control' %> +
+ +
+ <%= f.submit t('.sign_up'), class: 'btn btn-primary' %> +
+<% end %> + +<%= render 'devise/shared/links' %> diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb new file mode 100644 index 000000000..171f46085 --- /dev/null +++ b/app/views/devise/sessions/new.html.erb @@ -0,0 +1,28 @@ +

<%= t('.sign_in') %>

+ +<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control' %> +
+ +
+ <%= f.label :password %> + <%= f.password_field :password, autocomplete: 'current-password', class: 'form-control' %> +
+ + <% if devise_mapping.rememberable? %> +
+ <%= f.check_box :remember_me, class: 'form-check-input' %> + <%= f.label :remember_me, class: 'form-check-label' do %> + <%= resource.class.human_attribute_name('remember_me') %> + <% end %> +
+ <% end %> + +
+ <%= f.submit t('.sign_in'), class: 'btn btn-primary' %> +
+<% end %> + +<%= render 'devise/shared/links' %> diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb new file mode 100644 index 000000000..3c97f4cf7 --- /dev/null +++ b/app/views/devise/shared/_links.html.erb @@ -0,0 +1,27 @@ +
+ <%- if controller_name != 'sessions' %> + <%= link_to t(".sign_in"), new_session_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.registerable? && controller_name != 'registrations' %> + <%= link_to t(".sign_up"), new_registration_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> + <%= link_to t(".forgot_your_password"), new_password_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to t('.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to t('.didn_t_receive_unlock_instructions'), new_unlock_path(resource_name) %>
+ <% end -%> + + <%- if devise_mapping.omniauthable? %> + <%- resource_class.omniauth_providers.each do |provider| %> + <%= link_to t('.sign_in_with_provider', provider: OmniAuth::Utils.camelize(provider)), omniauth_authorize_path(resource_name, provider) %>
+ <% end -%> + <% end -%> +
diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb new file mode 100644 index 000000000..d70aa2f96 --- /dev/null +++ b/app/views/devise/unlocks/new.html.erb @@ -0,0 +1,16 @@ +

<%= t('.resend_unlock_instructions') %>

+ +<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> + <%= bootstrap_devise_error_messages! %> + +
+ <%= f.label :email %> + <%= f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control' %> +
+ +
+ <%= f.submit t('.resend_unlock_instructions'), class: 'btn btn-primary'%> +
+<% end %> + +<%= render 'devise/shared/links' %> diff --git a/app/views/layouts/blazer/application.html.erb b/app/views/layouts/blazer/application.html.erb new file mode 100644 index 000000000..cf8466b0f --- /dev/null +++ b/app/views/layouts/blazer/application.html.erb @@ -0,0 +1,26 @@ + + + + <%= blazer_title ? blazer_title : "Blazer" %> + + + + <%= favicon_link_tag "blazer/favicon.png" %> + <%= stylesheet_link_tag "blazer/application" %> + <%= javascript_include_tag "blazer/application" %> + + <% if blazer_maps? %> + <%= stylesheet_link_tag "https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.css", integrity: "sha384-vxzdEt+wZRPNQbhChjmiaFMLWg86IGuq1NGDehJHsD2mphYkxXll/eSs16WWi6Dq", crossorigin: "anonymous" %> + <%= javascript_include_tag "https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.js", integrity: "sha384-CTBEiDLiZJ8gkAQ3fYGoeiRp81/ecNiBkGz11jXFALOZ6++rbnqmdo6OImkmr1MO", crossorigin: "anonymous" %> + <% end %> + <%= csrf_meta_tags %> + + + <%= render "shared/navbar_blazer" %> +
+ <%= yield %> +
+ + diff --git a/app/views/shared/_navbar_blazer.html.erb b/app/views/shared/_navbar_blazer.html.erb new file mode 100644 index 000000000..693b67bba --- /dev/null +++ b/app/views/shared/_navbar_blazer.html.erb @@ -0,0 +1,18 @@ + diff --git a/app/views/shared/_user_util_links.html.erb b/app/views/shared/_user_util_links.html.erb new file mode 100644 index 000000000..257fc29f6 --- /dev/null +++ b/app/views/shared/_user_util_links.html.erb @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/config/application.rb b/config/application.rb index 3ea4f80a9..a8ea03827 100644 --- a/config/application.rb +++ b/config/application.rb @@ -38,5 +38,8 @@ class Application < Rails::Application resource '*', :headers => :any, :methods => [:get, :options] end end + + # Image Processing + config.active_storage.variant_processor = :vips end end diff --git a/config/blazer.yml b/config/blazer.yml new file mode 100644 index 000000000..f9ea7f1ba --- /dev/null +++ b/config/blazer.yml @@ -0,0 +1,79 @@ +# see https://github.com/ankane/blazer for more info + +data_sources: + main: + url: "<%= ENV['BLAZER_DATABASE_URL'] %>" + + # statement timeout, in seconds + # none by default + # timeout: 15 + + # caching settings + # can greatly improve speed + # off by default + # cache: + # mode: slow # or all + # expires_in: 60 # min + # slow_threshold: 15 # sec, only used in slow mode + + # wrap queries in a transaction for safety + # not necessary if you use a read-only user + # true by default + # use_transaction: false + + smart_variables: + # zone_id: "SELECT id, name FROM zones ORDER BY name ASC" + # period: ["day", "week", "month"] + # status: {0: "Active", 1: "Archived"} + + linked_columns: + # user_id: "/admin/users/{value}" + + smart_columns: + # user_id: "SELECT id, name FROM users WHERE id IN {value}" + +# create audits +audit: true + +# change the time zone +# time_zone: "Pacific Time (US & Canada)" + +# class name of the user model +# user_class: User + +# method name for the current user +# user_method: current_user + +# method name for the display name +# user_name: name + +# custom before_action to use for auth +# before_action_method: require_admin + +# email to send checks from +# from_email: blazer@example.org + +# webhook for Slack +# slack_webhook_url: <%= ENV["BLAZER_SLACK_WEBHOOK_URL"] %> + +check_schedules: + - "1 day" + - "1 hour" + - "5 minutes" + +# enable anomaly detection +# note: with trend, time series are sent to https://trendapi.org +# anomaly_checks: prophet / trend / anomaly_detection + +# enable forecasting +# note: with trend, time series are sent to https://trendapi.org +# forecasting: prophet / trend + +# enable map +mapbox_access_token: "<%= ENV['MAPBOX_ACCESS_TOKEN'] %>" + +# enable uploads +uploads: + url: "<%= ENV['BLAZER_DATABASE_URL'] %>" + schema: blazer_uploads + data_source: main diff --git a/config/database.yml b/config/database.yml index c01ae1e78..41b0e9f11 100644 --- a/config/database.yml +++ b/config/database.yml @@ -5,21 +5,28 @@ # gem 'sqlite3' # default: &default - adapter: sqlite3 + adapter: postgresql + encoding: utf8 pool: 5 timeout: 5000 # Local development with sqlite development: <<: *default - database: db/development.sqlite3 + host: "<%= ENV['GEOBLACKLIGHT_DB_HOST'] %>" + database: "<%= ENV['GEOBLACKLIGHT_DB_DATABASE'] %>" + username: "<%= ENV['GEOBLACKLIGHT_DB_USER'] %>" + password: "<%= ENV['GEOBLACKLIGHT_DB_PASSWORD'] %>" # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default - database: db/test.sqlite3 + host: <%= ENV['POSTGRES_HOST'] || '127.0.0.1' %> + port: <%= ENV['POSTGRES_PORT'] || '5432' %> + username: <%= ENV['POSTGRES_USER'] || 'postgres' %> + password: <%= ENV['POSTGRES_PASSWORD'] || 'postgres' %> production: # Puma is given a lot of threads diff --git a/config/environments/development.rb b/config/environments/development.rb index a53b9a839..71294e150 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -39,6 +39,8 @@ config.action_mailer.default_options = {from: 'no-reply@geo.btaa.org'} config.action_mailer.perform_caching = false + config.action_mailer.default_url_options = { :host => 'localhost:3000' } + # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log diff --git a/config/geomg_aardvark_schema.json b/config/geomg_aardvark_schema.json new file mode 100644 index 000000000..095d30ec1 --- /dev/null +++ b/config/geomg_aardvark_schema.json @@ -0,0 +1,217 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "dct_title_s": { "type": "string" }, + "dct_alternative_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_description_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_language_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "gbl_displayNote_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_creator_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_publisher_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "schema_provider_s": { "type": "string" }, + "gbl_resourceClass_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "gbl_resourceType_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_subject_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dcat_theme_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dcat_keyword_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_temporal_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_issued_s": { "type": "string" }, + "gbl_indexYear_im": { + "type": "array", + "items": { + "type": "integer" + } + }, + "gbl_dateRange_drsim": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_spatial_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "locn_geometry": { "type": "string" }, + "dcat_centroid_ss": { "type": "string" }, + "gbl_georeferenced_b": { "type": "boolean" }, + "dct_relation_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "pcdm_memberOf_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_isPartOf_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_source_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_isVersionOf_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_replaces_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_isReplacedBy_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_rights_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_rightsHolder_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_license_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "dct_accessRights_s": { "type": "string" }, + "dct_format_s": { "type": "string" }, + "gbl_fileSize_s": { "type": "string" }, + "dct_references_s": { + "type": "array", + "items": { + "type": "object" + } + }, + "gbl_wxsIdentifier_s": { "type": "string" }, + "id": { "type": "string" }, + "geomg_id_s": { "type": "string" }, + "dct_identifier_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "gbl_mdModified_dt": { + "type": "string", + "format": "date-time" + }, + "gbl_mdVersion_s": { "type": "string" }, + "gbl_suppressed_b": { "type": "boolean" }, + "b1g_image_ss": { "type": "string" }, + "b1g_geonames_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "b1g_dct_accrualMethod_s": { "type": "string" }, + "b1g_dct_accrualPeriodicity_s": { "type": "string" }, + "b1g_dateAccessioned_sm": { + "type": "array", + "items": { + "type": "string", + "format": "date" + } + }, + "b1g_dateRetired_s": { + "type": "string", + "format": "date" + }, + "b1g_child_record_b": { "type": "boolean" }, + "b1g_status_s": { "type": "string" }, + "b1g_dct_mediator_sm": { + "type": "array", + "items": { + "type": "string" + } + }, + "b1g_access_s": { "type": "string" }, + "b1g_code_s": { "type": "string" } + }, + "required": ["dct_title_s", "gbl_resourceClass_sm", "dct_accessRights_s", "geomg_id_s"] +} diff --git a/config/initializers/active_record_query_trace.rb b/config/initializers/active_record_query_trace.rb new file mode 100644 index 000000000..14eaf6a2a --- /dev/null +++ b/config/initializers/active_record_query_trace.rb @@ -0,0 +1,4 @@ +if Rails.env.development? + ActiveRecordQueryTrace.enabled = true + # Optional: other gem config options go here +end \ No newline at end of file diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 759371e91..bead91b74 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -15,3 +15,8 @@ Rails.application.config.assets.precompile += %w( analytics.js ) Rails.application.config.assets.precompile += %w( favicon.ico ) + +# GBL ADMIN +# Rails.application.config.assets.paths << Rails.root.join('node_modules') +Rails.application.config.assets.precompile += %w( geoblacklight_admin.js ) +Rails.application.config.assets.precompile += %w[application.js] \ No newline at end of file diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 5209ea6d3..32ec0b234 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,14 +1,21 @@ +# frozen_string_literal: true + +require "devise_invitable" + # Use this hook to configure devise mailer, warden hooks and so forth. # Many of these configuration options can be set straight in your model. Devise.setup do |config| # The secret key used by Devise. Devise uses this key to generate # random tokens. Changing this key will render invalid all existing # confirmation, reset password and unlock tokens in the database. - # Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key` + # Devise will use the `secret_key_base` as its `secret_key` # by default. You can change it below and use your own secret key. - # config.secret_key = 'a3d5eece08adb97aabdaf450cfca2f8efe46dfa7e7535ea4e2b53ce782ef8a32f71f1caf129a99d84185abe8dac3fcc05f5ac27fc3bfd735bac8d3f165a76042' config.secret_key = ENV['GEOBLACKLIGHT_SECRET_KEY_DEVISE'] + # ==> Controller configuration + # Configure the parent class to the devise controllers. + # config.parent_controller = 'DeviseController' + # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class @@ -18,6 +25,9 @@ # Configure the class responsible to send e-mails. # config.mailer = 'Devise::Mailer' + # Configure the parent class responsible to send e-mails. + # config.parent_mailer = 'ActionMailer::Base' + # ==> ORM configuration # Load and configure the ORM. Supports :active_record (default) and # :mongoid (bson_ext recommended) by default. Other ORMs may be @@ -88,29 +98,90 @@ # from the server. You can disable this option at your own risk. # config.clean_up_csrf_token_on_authentication = true + # When false, Devise will not attempt to reload routes on eager load. + # This can reduce the time taken to boot the app but if your application + # requires the Devise mappings to be loaded during boot time the application + # won't boot properly. + # config.reload_routes = true + # ==> Configuration for :database_authenticatable - # For bcrypt, this is the cost for hashing the password and defaults to 10. If - # using other encryptors, it sets how many times you want the password re-encrypted. + # For bcrypt, this is the cost for hashing the password and defaults to 11. If + # using other algorithms, it sets how many times you want the password to be hashed. # # Limiting the stretches to just one in testing will increase the performance of # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use # a value less than 10 in other environments. Note that, for bcrypt (the default - # encryptor), the cost increases exponentially with the number of stretches (e.g. + # algorithm), the cost increases exponentially with the number of stretches (e.g. # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). - config.stretches = Rails.env.test? ? 1 : 10 + config.stretches = Rails.env.test? ? 1 : 11 + + # Set up a pepper to generate the hashed password. + # config.pepper = '7b7a67e40ce106e329691684af85c544a729e9b2ecc4a90d6b23351388a03f71ef17efefecc35499fcaf93f662c6bcc10205f3793d5827b8f0d1d4f013f87c36' - # Setup a pepper to generate the encrypted password. - # config.pepper = '2e0595910f034f5eab01f0b66f19f203f90474f29b907d8dcc04da109d16c30d3534ef7588ff05a29a7e5039d7ae62983c9069a89bf26e0533b53b953c01e3ac' + # Send a notification to the original email when the user's email is changed. + # config.send_email_changed_notification = false - # Send a notification email when the user's password is changed + # Send a notification email when the user's password is changed. # config.send_password_change_notification = false + # ==> Configuration for :invitable + # The period the generated invitation token is valid. + # After this period, the invited resource won't be able to accept the invitation. + # When invite_for is 0 (the default), the invitation won't expire. + # config.invite_for = 2.weeks + + # Number of invitations users can send. + # - If invitation_limit is nil, there is no limit for invitations, users can + # send unlimited invitations, invitation_limit column is not used. + # - If invitation_limit is 0, users can't send invitations by default. + # - If invitation_limit n > 0, users can send n invitations. + # You can change invitation_limit column for some users so they can send more + # or less invitations, even with global invitation_limit = 0 + # Default: nil + # config.invitation_limit = 5 + + # The key to be used to check existing users when sending an invitation + # and the regexp used to test it when validate_on_invite is not set. + # config.invite_key = { email: /\A[^@]+@[^@]+\z/ } + # config.invite_key = { email: /\A[^@]+@[^@]+\z/, username: nil } + + # Ensure that invited record is valid. + # The invitation won't be sent if this check fails. + # Default: false + # config.validate_on_invite = true + + # Resend invitation if user with invited status is invited again + # Default: true + # config.resend_invitation = false + + # The class name of the inviting model. If this is nil, + # the #invited_by association is declared to be polymorphic. + # Default: nil + # config.invited_by_class_name = 'User' + + # The foreign key to the inviting model (if invited_by_class_name is set) + # Default: :invited_by_id + # config.invited_by_foreign_key = :invited_by_id + + # The column name used for counter_cache column. If this is nil, + # the #invited_by association is declared without counter_cache. + # Default: nil + # config.invited_by_counter_cache = :invitations_count + + # Auto-login after the user accepts the invite. If this is false, + # the user will need to manually log in after accepting the invite. + # Default: true + # config.allow_insecure_sign_in_after_accept = false + # ==> Configuration for :confirmable # A period that the user is allowed to access the website even without # confirming their account. For instance, if set to 2.days, the user will be # able to access the website for two days without confirming their account, - # access will be blocked just in the third day. Default is 0.days, meaning - # the user cannot access the website without confirming their account. + # access will be blocked just in the third day. + # You can also set it to nil, which will allow the user to access the website + # without confirming their account. + # Default is 0.days, meaning the user cannot access the website without + # confirming their account. # config.allow_unconfirmed_access_for = 2.days # A period that the user is allowed to confirm their account before their @@ -146,14 +217,11 @@ # ==> Configuration for :validatable # Range for password length. - config.password_length = 8..72 + config.password_length = 6..128 # Email regex used to validate email formats. It simply asserts that # one (and only one) @ exists in the given string. This is mainly # to give user feedback and not to assert the e-mail validity. - # config.email_regexp = /\A[^@]+@[^@]+\z/ - # - # New recommended devise email regex default config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ # ==> Configuration for :timeoutable @@ -202,11 +270,11 @@ # config.sign_in_after_reset_password = true # ==> Configuration for :encryptable - # Allow you to use another encryption algorithm besides bcrypt (default). You can use - # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, - # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) - # and :restful_authentication_sha1 (then you should set stretches to 10, and copy - # REST_AUTH_SITE_KEY to pepper). + # Allow you to use another hashing or encryption algorithm besides bcrypt (default). + # You can use :sha1, :sha512 or algorithms from others authentication tools as + # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 + # for default behavior) and :restful_authentication_sha1 (then you should set + # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). # # Require the `devise-encryptable` gem when using anything other than bcrypt # config.encryptor = :sha512 @@ -237,7 +305,7 @@ # config.navigational_formats = ['*/*', :html] # The default HTTP method used to sign out a resource. Default is :delete. - config.sign_out_via = :get + config.sign_out_via = :delete # ==> OmniAuth # Add a new OmniAuth provider. Check the wiki for more information on setting @@ -266,4 +334,17 @@ # When using OmniAuth, Devise cannot automatically set OmniAuth path, # so you need to do it manually. For the users scope, it would be: # config.omniauth_path_prefix = '/my_engine/users/auth' + + # ==> Turbolinks configuration + # If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly: + # + # ActiveSupport.on_load(:devise_failure_app) do + # include Turbolinks::Controller + # end + + # ==> Configuration for :registerable + + # When set to false, does not sign a user in automatically after their password is + # changed. Defaults to true, so a user is signed in automatically after changing a password. + # config.sign_in_after_change_password = true end diff --git a/config/initializers/geoblacklight_admin.rb b/config/initializers/geoblacklight_admin.rb new file mode 100644 index 000000000..f4b9d13fa --- /dev/null +++ b/config/initializers/geoblacklight_admin.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require "json" + +GEOMG_SCHEMA = HashWithIndifferentAccess.new( + JSON.parse( + File.read( + Rails.root.join("config/geomg_aardvark_schema.json") + ) + ) +) + +# GEOMG_SCHEMA_TIMESTAMP +# This constant hold the Time of the last changes to the Element table. +# If the timestamp changes, the rails server and sidekiq will need to be restarted. +unless File.exist?(Rails.root.join("tmp/schema_timestamp.txt").to_s) + File.write(Rails.root.join("tmp/schema_timestamp.txt").to_s, Time.now.to_s) +end +GEOMG_SCHEMA_TIMESTAMP = File.read(Rails.root.join("tmp/schema_timestamp.txt").to_s) + +BLACKLIGHT_URL = ENV["BLACKLIGHT_URL"] +BLACKLIGHT_JSON_API = ENV["BLACKLIGHT_JSON_API"] +BLACKLIGHT_JSON_API_IDS = ENV["BLACKLIGHT_JSON_API_IDS"] +BLACKLIGHT_JSON_API_FACETS = ENV["BLACKLIGHT_JSON_API_FACETS"] + +# Former Controller > Concern +module Admin + module UploadUtil + def self.kithe_upload_data_config(toggle_value: "kithe-upload") + { + toggle: toggle_value, + upload_endpoint: Rails.application.routes.url_helpers.admin_direct_app_upload_path + } + end + end +end diff --git a/config/initializers/kithe.rb b/config/initializers/kithe.rb new file mode 100644 index 000000000..800b2a1cf --- /dev/null +++ b/config/initializers/kithe.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require "kithe" + +traject_logger = ActiveSupport::Logger.new("#{Rails.root}/log/traject.log") + +Kithe.indexable_settings.solr_url = ENV["GEOBLACKLIGHT_SOLR_URL"] + +# Index to solr with solr `id` field being our friendlier_id +Kithe.indexable_settings.solr_id_value_attribute = :friendlier_id + +# Traject settings +Kithe.indexable_settings.writer_settings.merge!({ + "solr_writer.thread_pool" => 0, + "solr_writer.batch_size" => 1, + "solr_writer.solr_update_args" => {softCommit: true}, + "solr_writer.http_timeout" => 3, + "solr_writer.max_skipped" => -1, + "logger" => traject_logger +}) + +# Traject with Basic Auth support +if ENV["SOLR_BASIC_AUTH_USER"].present? + Kithe.indexable_settings.writer_settings.merge!({ + "solr_writer.basic_auth_user" => ENV["SOLR_BASIC_AUTH_USER"], + "solr_writer.basic_auth_password" => ENV["SOLR_BASIC_AUTH_PASSWORD"], + "solr_writer.thread_pool" => 0, + "solr_writer.batch_size" => 1, + "solr_writer.solr_update_args" => {softCommit: true}, "solr_writer.http_timeout" => 3, + "solr_writer.max_skipped" => -1, + "logger" => traject_logger + }) +end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index dc1899682..5b678f929 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -2,3 +2,14 @@ # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf + +# GBL‡ADMIN +## Order is important. ActiveStorage needs :json to be last +Mime::Type.register "application/json", :json_aardvark +Mime::Type.register "application/json", :json_btaa_aardvark +Mime::Type.register "application/json", :json_file +Mime::Type.register "application/json", :json_gbl_v1 +Mime::Type.register "application/json", :json + +Mime::Type.register "text/csv", :csv_document_downloads +Mime::Type.register "text/csv", :csv_document_access_links diff --git a/config/initializers/pagy.rb b/config/initializers/pagy.rb new file mode 100644 index 000000000..6db9229c8 --- /dev/null +++ b/config/initializers/pagy.rb @@ -0,0 +1,242 @@ +# frozen_string_literal: true + +require "pagy" + +# Pagy initializer file (6.0.4) +# Customize only what you really need and notice that the core Pagy works also without any of the following lines. +# Should you just cherry pick part of this file, please maintain the require-order of the extras + +# Pagy DEFAULT Variables +# See https://ddnexus.github.io/pagy/docs/api/pagy#variables +# All the Pagy::DEFAULT are set for all the Pagy instances but can be overridden per instance by just passing them to +# Pagy.new|Pagy::Countless.new|Pagy::Calendar::*.new or any of the #pagy* controller methods + +# Instance variables +# See https://ddnexus.github.io/pagy/docs/api/pagy#instance-variables +# Pagy::DEFAULT[:page] = 1 # default +# Pagy::DEFAULT[:items] = 20 # default +# Pagy::DEFAULT[:outset] = 0 # default + +# Other Variables +# See https://ddnexus.github.io/pagy/docs/api/pagy#other-variables +# Pagy::DEFAULT[:size] = [1,4,4,1] # default +# Pagy::DEFAULT[:page_param] = :page # default +# The :params can be also set as a lambda e.g ->(params){ params.exclude('useless').merge!('custom' => 'useful') } +# Pagy::DEFAULT[:params] = {} # default +# Pagy::DEFAULT[:fragment] = '#fragment' # example +# Pagy::DEFAULT[:link_extra] = 'data-remote="true"' # example +# Pagy::DEFAULT[:i18n_key] = 'pagy.item_name' # default +# Pagy::DEFAULT[:cycle] = true # example +# Pagy::DEFAULT[:request_path] = "/foo" # example + +# Extras +# See https://ddnexus.github.io/pagy/categories/extra + +# Backend Extras + +# Arel extra: For better performance utilizing grouped ActiveRecord collections: +# See: https://ddnexus.github.io/pagy/docs/extras/arel +# require 'pagy/extras/arel' + +# Array extra: Paginate arrays efficiently, avoiding expensive array-wrapping and without overriding +# See https://ddnexus.github.io/pagy/docs/extras/array +# require 'pagy/extras/array' + +# Calendar extra: Add pagination filtering by calendar time unit (year, quarter, month, week, day) +# See https://ddnexus.github.io/pagy/docs/extras/calendar +# require 'pagy/extras/calendar' +# Default for each unit +# Pagy::Calendar::Year::DEFAULT[:order] = :asc # Time direction of pagination +# Pagy::Calendar::Year::DEFAULT[:format] = '%Y' # strftime format +# +# Pagy::Calendar::Quarter::DEFAULT[:order] = :asc # Time direction of pagination +# Pagy::Calendar::Quarter::DEFAULT[:format] = '%Y-Q%q' # strftime format +# +# Pagy::Calendar::Month::DEFAULT[:order] = :asc # Time direction of pagination +# Pagy::Calendar::Month::DEFAULT[:format] = '%Y-%m' # strftime format +# +# Pagy::Calendar::Week::DEFAULT[:order] = :asc # Time direction of pagination +# Pagy::Calendar::Week::DEFAULT[:format] = '%Y-%W' # strftime format +# +# Pagy::Calendar::Day::DEFAULT[:order] = :asc # Time direction of pagination +# Pagy::Calendar::Day::DEFAULT[:format] = '%Y-%m-%d' # strftime format +# +# Uncomment the following lines, if you need calendar localization without using the I18n extra +# module LocalizePagyCalendar +# def localize(time, opts) +# ::I18n.l(time, **opts) +# end +# end +# Pagy::Calendar.prepend LocalizePagyCalendar + +# Countless extra: Paginate without any count, saving one query per rendering +# See https://ddnexus.github.io/pagy/docs/extras/countless +# require 'pagy/extras/countless' +# Pagy::DEFAULT[:countless_minimal] = false # default (eager loading) + +# Elasticsearch Rails extra: Paginate `ElasticsearchRails::Results` objects +# See https://ddnexus.github.io/pagy/docs/extras/elasticsearch_rails +# Default :pagy_search method: change only if you use also +# the searchkick or meilisearch extra that defines the same +# Pagy::DEFAULT[:elasticsearch_rails_pagy_search] = :pagy_search +# Default original :search method called internally to do the actual search +# Pagy::DEFAULT[:elasticsearch_rails_search] = :search +# require 'pagy/extras/elasticsearch_rails' + +# Headers extra: http response headers (and other helpers) useful for API pagination +# See http://ddnexus.github.io/pagy/extras/headers +# require 'pagy/extras/headers' +# Pagy::DEFAULT[:headers] = { page: 'Current-Page', +# items: 'Page-Items', +# count: 'Total-Count', +# pages: 'Total-Pages' } # default + +# Meilisearch extra: Paginate `Meilisearch` result objects +# See https://ddnexus.github.io/pagy/docs/extras/meilisearch +# Default :pagy_search method: change only if you use also +# the elasticsearch_rails or searchkick extra that define the same method +# Pagy::DEFAULT[:meilisearch_pagy_search] = :pagy_search +# Default original :search method called internally to do the actual search +# Pagy::DEFAULT[:meilisearch_search] = :ms_search +# require 'pagy/extras/meilisearch' + +# Metadata extra: Provides the pagination metadata to Javascript frameworks like Vue.js, react.js, etc. +# See https://ddnexus.github.io/pagy/docs/extras/metadata +# you must require the frontend helpers internal extra (BEFORE the metadata extra) ONLY if you need also the :sequels +# require 'pagy/extras/frontend_helpers' +# require 'pagy/extras/metadata' +# For performance reasons, you should explicitly set ONLY the metadata you use in the frontend +# Pagy::DEFAULT[:metadata] = %i[scaffold_url page prev next last] # example + +# Searchkick extra: Paginate `Searchkick::Results` objects +# See https://ddnexus.github.io/pagy/docs/extras/searchkick +# Default :pagy_search method: change only if you use also +# the elasticsearch_rails or meilisearch extra that defines the same +# DEFAULT[:searchkick_pagy_search] = :pagy_search +# Default original :search method called internally to do the actual search +# Pagy::DEFAULT[:searchkick_search] = :search +# require 'pagy/extras/searchkick' +# uncomment if you are going to use Searchkick.pagy_search +# Searchkick.extend Pagy::Searchkick + +# Frontend Extras + +# Bootstrap extra: Add nav, nav_js and combo_nav_js helpers and templates for Bootstrap pagination +# See https://ddnexus.github.io/pagy/docs/extras/bootstrap +require "pagy/extras/bootstrap" + +# Bulma extra: Add nav, nav_js and combo_nav_js helpers and templates for Bulma pagination +# See https://ddnexus.github.io/pagy/docs/extras/bulma +# require 'pagy/extras/bulma' + +# Foundation extra: Add nav, nav_js and combo_nav_js helpers and templates for Foundation pagination +# See https://ddnexus.github.io/pagy/docs/extras/foundation +# require 'pagy/extras/foundation' + +# Materialize extra: Add nav, nav_js and combo_nav_js helpers for Materialize pagination +# See https://ddnexus.github.io/pagy/docs/extras/materialize +# require 'pagy/extras/materialize' + +# Navs extra: Add nav_js and combo_nav_js javascript helpers +# Notice: the other frontend extras add their own framework-styled versions, +# so require this extra only if you need the unstyled version +# See https://ddnexus.github.io/pagy/docs/extras/navs +# require 'pagy/extras/navs' + +# Semantic extra: Add nav, nav_js and combo_nav_js helpers for Semantic UI pagination +# See https://ddnexus.github.io/pagy/docs/extras/semantic +# require 'pagy/extras/semantic' + +# UIkit extra: Add nav helper and templates for UIkit pagination +# See https://ddnexus.github.io/pagy/docs/extras/uikit +# require 'pagy/extras/uikit' + +# Multi size var used by the *_nav_js helpers +# See https://ddnexus.github.io/pagy/docs/extras/navs#steps +# Pagy::DEFAULT[:steps] = { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] } # example + +# Feature Extras + +# Gearbox extra: Automatically change the number of items per page depending on the page number +# See https://ddnexus.github.io/pagy/docs/extras/gearbox +# require 'pagy/extras/gearbox' +# set to false only if you want to make :gearbox_extra an opt-in variable +# Pagy::DEFAULT[:gearbox_extra] = false # default true +# Pagy::DEFAULT[:gearbox_items] = [15, 30, 60, 100] # default + +# Items extra: Allow the client to request a custom number of items per page with an optional selector UI +# See https://ddnexus.github.io/pagy/docs/extras/items +# require 'pagy/extras/items' +# set to false only if you want to make :items_extra an opt-in variable +# Pagy::DEFAULT[:items_extra] = false # default true +# Pagy::DEFAULT[:items_param] = :items # default +# Pagy::DEFAULT[:max_items] = 100 # default + +# Overflow extra: Allow for easy handling of overflowing pages +# See https://ddnexus.github.io/pagy/docs/extras/overflow +# require 'pagy/extras/overflow' +# Pagy::DEFAULT[:overflow] = :empty_page # default (other options: :last_page and :exception) + +# Support extra: Extra support for features like: incremental, infinite, auto-scroll pagination +# See https://ddnexus.github.io/pagy/docs/extras/support +# require 'pagy/extras/support' + +# Trim extra: Remove the page=1 param from links +# See https://ddnexus.github.io/pagy/docs/extras/trim +# require 'pagy/extras/trim' +# set to false only if you want to make :trim_extra an opt-in variable +# Pagy::DEFAULT[:trim_extra] = false # default true + +# Standalone extra: Use pagy in non Rack environment/gem +# See https://ddnexus.github.io/pagy/docs/extras/standalone +# require 'pagy/extras/standalone' +# Pagy::DEFAULT[:url] = 'http://www.example.com/subdir' # optional default + +# Rails +# Enable the .js file required by the helpers that use javascript +# (pagy*_nav_js, pagy*_combo_nav_js, and pagy_items_selector_js) +# See https://ddnexus.github.io/pagy/docs/api/javascript + +# With the asset pipeline +# Sprockets need to look into the pagy javascripts dir, so add it to the assets paths +# Rails.application.config.assets.paths << Pagy.root.join('javascripts') + +# I18n + +# Pagy internal I18n: ~18x faster using ~10x less memory than the i18n gem +# See https://ddnexus.github.io/pagy/docs/api/i18n +# Notice: No need to configure anything in this section if your app uses only "en" +# or if you use the i18n extra below +# +# Examples: +# load the "de" built-in locale: +# Pagy::I18n.load(locale: 'de') +# +# load the "de" locale defined in the custom file at :filepath: +# Pagy::I18n.load(locale: 'de', filepath: 'path/to/pagy-de.yml') +# +# load the "de", "en" and "es" built-in locales: +# (the first passed :locale will be used also as the default_locale) +# Pagy::I18n.load({ locale: 'de' }, +# { locale: 'en' }, +# { locale: 'es' }) +# +# load the "en" built-in locale, a custom "es" locale, +# and a totally custom locale complete with a custom :pluralize proc: +# (the first passed :locale will be used also as the default_locale) +# Pagy::I18n.load({ locale: 'en' }, +# { locale: 'es', filepath: 'path/to/pagy-es.yml' }, +# { locale: 'xyz', # not built-in +# filepath: 'path/to/pagy-xyz.yml', +# pluralize: lambda{ |count| ... } ) + +# I18n extra: uses the standard i18n gem which is ~18x slower using ~10x more memory +# than the default pagy internal i18n (see above) +# See https://ddnexus.github.io/pagy/docs/extras/i18n +# require 'pagy/extras/i18n' + +# Default i18n key +# Pagy::DEFAULT[:i18n_key] = 'pagy.item_name' # default + +# When you are done setting your own default freeze it, so it will not get changed accidentally +Pagy::DEFAULT.freeze diff --git a/config/initializers/shrine.rb b/config/initializers/shrine.rb new file mode 100644 index 000000000..ffe18398e --- /dev/null +++ b/config/initializers/shrine.rb @@ -0,0 +1,12 @@ +require "shrine" +require "shrine/storage/file_system" + +Shrine.storages = { + cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary + store: Shrine::Storage::FileSystem.new("public", prefix: "uploads") # permanent +} + +Shrine.plugin :activerecord +Shrine.plugin :upload_endpoint +Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays +Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb new file mode 100644 index 000000000..0be38945c --- /dev/null +++ b/config/initializers/simple_form.rb @@ -0,0 +1,178 @@ +# frozen_string_literal: true + +require "simple_form" + +# Uncomment this and change the path if necessary to include your own +# components. +# See https://github.com/heartcombo/simple_form#custom-components to know +# more about custom components. +# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f } +# +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + # Wrappers are used by the form builder to generate a + # complete input. You can remove any component from the + # wrapper, change the order or even add your own to the + # stack. The options given below are used to wrap the + # whole input. + config.wrappers :default, class: :input, + hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b| + ## Extensions enabled by default + # Any of these extensions can be disabled for a + # given input by passing: `f.input EXTENSION_NAME => false`. + # You can make any of these extensions optional by + # renaming `b.use` to `b.optional`. + + # Determines whether to use HTML5 (:email, :url, ...) + # and required attributes + b.use :html5 + + # Calculates placeholders automatically from I18n + # You can also pass a string as f.input placeholder: "Placeholder" + b.use :placeholder + + ## Optional extensions + # They are disabled unless you pass `f.input EXTENSION_NAME => true` + # to the input. If so, they will retrieve the values from the model + # if any exists. If you want to enable any of those + # extensions by default, you can change `b.optional` to `b.use`. + + # Calculates maxlength from length validations for string inputs + # and/or database column lengths + b.optional :maxlength + + # Calculate minlength from length validations for string inputs + b.optional :minlength + + # Calculates pattern from format validations for string inputs + b.optional :pattern + + # Calculates min and max from length validations for numeric inputs + b.optional :min_max + + # Calculates readonly automatically from readonly attributes + b.optional :readonly + + ## Inputs + # b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :label_input + b.use :hint, wrap_with: {tag: :span, class: :hint} + b.use :error, wrap_with: {tag: :span, class: :error} + + ## full_messages_for + # If you want to display the full error message for the attribute, you can + # use the component :full_error, like: + # + # b.use :full_error, wrap_with: { tag: :span, class: :error } + end + + # The default wrapper to be used by the FormBuilder. + config.default_wrapper = :default + + # Define the way to render check boxes / radio buttons with labels. + # Defaults to :nested for bootstrap config. + # inline: input + label + # nested: label > input + config.boolean_style = :nested + + # Default class for buttons + config.button_class = "btn" + + # Method used to tidy up errors. Specify any Rails Array method. + # :first lists the first message for each field. + # Use :to_sentence to list all errors for each field. + # config.error_method = :first + + # Default tag used for error notification helper. + config.error_notification_tag = :div + + # CSS class to add for error notification helper. + config.error_notification_class = "error_notification" + + # Series of attempts to detect a default label method for collection. + # config.collection_label_methods = [ :to_label, :name, :title, :to_s ] + + # Series of attempts to detect a default value method for collection. + # config.collection_value_methods = [ :id, :to_s ] + + # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none. + # config.collection_wrapper_tag = nil + + # You can define the class to use on all collection wrappers. Defaulting to none. + # config.collection_wrapper_class = nil + + # You can wrap each item in a collection of radio/check boxes with a tag, + # defaulting to :span. + # config.item_wrapper_tag = :span + + # You can define a class to use in all item wrappers. Defaulting to none. + # config.item_wrapper_class = nil + + # How the label text should be generated altogether with the required text. + # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" } + + # You can define the class to use on all labels. Default is nil. + # config.label_class = nil + + # You can define the default class to be used on forms. Can be overridden + # with `html: { :class }`. Defaulting to none. + # config.default_form_class = nil + + # You can define which elements should obtain additional classes + # config.generate_additional_classes_for = [:wrapper, :label, :input] + + # Whether attributes are required by default (or not). Default is true. + # config.required_by_default = true + + # Tell browsers whether to use the native HTML5 validations (novalidate form option). + # These validations are enabled in SimpleForm's internal config but disabled by default + # in this configuration, which is recommended due to some quirks from different browsers. + # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations, + # change this configuration to true. + config.browser_validations = false + + # Custom mappings for input types. This should be a hash containing a regexp + # to match as key, and the input type that will be used when the field name + # matches the regexp as value. + # config.input_mappings = { /count/ => :integer } + + # Custom wrappers for input types. This should be a hash containing an input + # type as key and the wrapper that will be used for all inputs with specified type. + # config.wrapper_mappings = { string: :prepend } + + # Namespaces where SimpleForm should look for custom input classes that + # override default inputs. + # config.custom_inputs_namespaces << "CustomInputs" + + # Default priority for time_zone inputs. + # config.time_zone_priority = nil + + # Default priority for country inputs. + # config.country_priority = nil + + # When false, do not use translations for labels. + # config.translate_labels = true + + # Automatically discover new inputs in Rails' autoload path. + # config.inputs_discovery = true + + # Cache SimpleForm inputs discovery + # config.cache_discovery = !Rails.env.development? + + # Default class for inputs + # config.input_class = nil + + # Define the default class of the input wrapper of the boolean input. + config.boolean_label_class = "checkbox" + + # Defines if the default input wrapper class should be included in radio + # collection wrappers. + # config.include_default_input_wrapper_class = true + + # Defines which i18n scope will be used in Simple Form. + # config.i18n_scope = 'simple_form' + + # Defines validation classes to the input_field. By default it's nil. + # config.input_field_valid_class = 'is-valid' + # config.input_field_error_class = 'is-invalid' +end diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb new file mode 100644 index 000000000..619decbb0 --- /dev/null +++ b/config/initializers/simple_form_bootstrap.rb @@ -0,0 +1,365 @@ +# frozen_string_literal: true + +# These defaults are defined and maintained by the community at +# https://github.com/heartcombo/simple_form-bootstrap +# Please submit feedback, changes and tests only there. + +# Uncomment this and change the path if necessary to include your own +# components. +# See https://github.com/heartcombo/simple_form#custom-components +# to know more about custom components. +# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f } + +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + # Default class for buttons + config.button_class = "btn" + + # Define the default class of the input wrapper of the boolean input. + config.boolean_label_class = "form-check-label" + + # How the label text should be generated altogether with the required text. + config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" } + + # Define the way to render check boxes / radio buttons with labels. + config.boolean_style = :inline + + # You can wrap each item in a collection of radio/check boxes with a tag + config.item_wrapper_tag = :div + + # Defines if the default input wrapper class should be included in radio + # collection wrappers. + config.include_default_input_wrapper_class = false + + # CSS class to add for error notification helper. + config.error_notification_class = "alert alert-danger" + + # Method used to tidy up errors. Specify any Rails Array method. + # :first lists the first message for each field. + # :to_sentence to list all errors for each field. + config.error_method = :to_sentence + + # add validation classes to `input_field` + config.input_field_error_class = "is-invalid" + config.input_field_valid_class = "is-valid" + + # vertical forms + # + # vertical default_wrapper + config.wrappers :vertical_form, class: "mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: "form-label" + b.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid" + b.use :full_error, wrap_with: {class: "invalid-feedback"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # vertical input for boolean + config.wrappers :vertical_boolean, tag: "fieldset", class: "mb-3" do |b| + b.use :html5 + b.optional :readonly + b.wrapper :form_check_wrapper, class: "form-check" do |bb| + bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + bb.use :label, class: "form-check-label" + bb.use :full_error, wrap_with: {class: "invalid-feedback"} + bb.use :hint, wrap_with: {class: "form-text"} + end + end + + # vertical input for radio buttons and check boxes + config.wrappers :vertical_collection, item_wrapper_class: "form-check", item_label_class: "form-check-label", tag: "fieldset", class: "mb-3" do |b| + b.use :html5 + b.optional :readonly + b.wrapper :legend_tag, tag: "legend", class: "col-form-label pt-0" do |ba| + ba.use :label_text + end + b.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + b.use :full_error, wrap_with: {class: "invalid-feedback d-block"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # vertical input for inline radio buttons and check boxes + config.wrappers :vertical_collection_inline, item_wrapper_class: "form-check form-check-inline", item_label_class: "form-check-label", tag: "fieldset", class: "mb-3" do |b| + b.use :html5 + b.optional :readonly + b.wrapper :legend_tag, tag: "legend", class: "col-form-label pt-0" do |ba| + ba.use :label_text + end + b.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + b.use :full_error, wrap_with: {class: "invalid-feedback d-block"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # vertical file input + config.wrappers :vertical_file, class: "mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :readonly + b.use :label, class: "form-label" + b.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid" + b.use :full_error, wrap_with: {class: "invalid-feedback"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # vertical select input + config.wrappers :vertical_select, class: "mb-3" do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: "form-label" + b.use :input, class: "form-select", error_class: "is-invalid", valid_class: "is-valid" + b.use :full_error, wrap_with: {class: "invalid-feedback"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # vertical multi select + config.wrappers :vertical_multi_select, class: "mb-3" do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: "form-label" + b.wrapper class: "d-flex flex-row justify-content-between align-items-center" do |ba| + ba.use :input, class: "form-select mx-1", error_class: "is-invalid", valid_class: "is-valid" + end + b.use :full_error, wrap_with: {class: "invalid-feedback d-block"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # vertical range input + config.wrappers :vertical_range, class: "mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :readonly + b.optional :step + b.use :label, class: "form-label" + b.use :input, class: "form-range", error_class: "is-invalid", valid_class: "is-valid" + b.use :full_error, wrap_with: {class: "invalid-feedback"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # horizontal forms + # + # horizontal default_wrapper + config.wrappers :horizontal_form, class: "row mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: "col-sm-3 col-form-label" + b.wrapper :grid_wrapper, class: "col-sm-9" do |ba| + ba.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid" + ba.use :full_error, wrap_with: {class: "invalid-feedback"} + ba.use :hint, wrap_with: {class: "form-text"} + end + end + + # horizontal input for boolean + config.wrappers :horizontal_boolean, class: "row mb-3" do |b| + b.use :html5 + b.optional :readonly + b.wrapper :grid_wrapper, class: "col-sm-9 offset-sm-3" do |wr| + wr.wrapper :form_check_wrapper, class: "form-check" do |bb| + bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + bb.use :label, class: "form-check-label" + bb.use :full_error, wrap_with: {class: "invalid-feedback"} + bb.use :hint, wrap_with: {class: "form-text"} + end + end + end + + # horizontal input for radio buttons and check boxes + config.wrappers :horizontal_collection, item_wrapper_class: "form-check", item_label_class: "form-check-label", class: "row mb-3" do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: "col-sm-3 col-form-label pt-0" + b.wrapper :grid_wrapper, class: "col-sm-9" do |ba| + ba.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + ba.use :full_error, wrap_with: {class: "invalid-feedback d-block"} + ba.use :hint, wrap_with: {class: "form-text"} + end + end + + # horizontal input for inline radio buttons and check boxes + config.wrappers :horizontal_collection_inline, item_wrapper_class: "form-check form-check-inline", item_label_class: "form-check-label", class: "row mb-3" do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: "col-sm-3 col-form-label pt-0" + b.wrapper :grid_wrapper, class: "col-sm-9" do |ba| + ba.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + ba.use :full_error, wrap_with: {class: "invalid-feedback d-block"} + ba.use :hint, wrap_with: {class: "form-text"} + end + end + + # horizontal file input + config.wrappers :horizontal_file, class: "row mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :readonly + b.use :label, class: "col-sm-3 col-form-label" + b.wrapper :grid_wrapper, class: "col-sm-9" do |ba| + ba.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid" + ba.use :full_error, wrap_with: {class: "invalid-feedback"} + ba.use :hint, wrap_with: {class: "form-text"} + end + end + + # horizontal select input + config.wrappers :horizontal_select, class: "row mb-3" do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: "col-sm-3 col-form-label" + b.wrapper :grid_wrapper, class: "col-sm-9" do |ba| + ba.use :input, class: "form-select", error_class: "is-invalid", valid_class: "is-valid" + ba.use :full_error, wrap_with: {class: "invalid-feedback"} + ba.use :hint, wrap_with: {class: "form-text"} + end + end + + # horizontal multi select + config.wrappers :horizontal_multi_select, class: "row mb-3" do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: "col-sm-3 col-form-label" + b.wrapper :grid_wrapper, class: "col-sm-9" do |ba| + ba.wrapper class: "d-flex flex-row justify-content-between align-items-center" do |bb| + bb.use :input, class: "form-select mx-1", error_class: "is-invalid", valid_class: "is-valid" + end + ba.use :full_error, wrap_with: {class: "invalid-feedback d-block"} + ba.use :hint, wrap_with: {class: "form-text"} + end + end + + # horizontal range input + config.wrappers :horizontal_range, class: "row mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :readonly + b.optional :step + b.use :label, class: "col-sm-3 col-form-label pt-0" + b.wrapper :grid_wrapper, class: "col-sm-9" do |ba| + ba.use :input, class: "form-range", error_class: "is-invalid", valid_class: "is-valid" + ba.use :full_error, wrap_with: {class: "invalid-feedback"} + ba.use :hint, wrap_with: {class: "form-text"} + end + end + + # inline forms + # + # inline default_wrapper + config.wrappers :inline_form, class: "col-12" do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: "visually-hidden" + + b.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid" + b.use :error, wrap_with: {class: "invalid-feedback"} + b.optional :hint, wrap_with: {class: "form-text"} + end + + # inline input for boolean + config.wrappers :inline_boolean, class: "col-12" do |b| + b.use :html5 + b.optional :readonly + b.wrapper :form_check_wrapper, class: "form-check" do |bb| + bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + bb.use :label, class: "form-check-label" + bb.use :error, wrap_with: {class: "invalid-feedback"} + bb.optional :hint, wrap_with: {class: "form-text"} + end + end + + # bootstrap custom forms + # + # custom input switch for boolean + config.wrappers :custom_boolean_switch, class: "mb-3" do |b| + b.use :html5 + b.optional :readonly + b.wrapper :form_check_wrapper, tag: "div", class: "form-check form-switch" do |bb| + bb.use :input, class: "form-check-input", error_class: "is-invalid", valid_class: "is-valid" + bb.use :label, class: "form-check-label" + bb.use :full_error, wrap_with: {tag: "div", class: "invalid-feedback"} + bb.use :hint, wrap_with: {class: "form-text"} + end + end + + # Input Group - custom component + # see example app and config at https://github.com/heartcombo/simple_form-bootstrap + config.wrappers :input_group, class: "mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: "form-label" + b.wrapper :input_group_tag, class: "input-group" do |ba| + ba.optional :prepend + ba.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid" + ba.optional :append + ba.use :full_error, wrap_with: {class: "invalid-feedback"} + end + b.use :hint, wrap_with: {class: "form-text"} + end + + # Floating Labels form + # + # floating labels default_wrapper + config.wrappers :floating_labels_form, class: "form-floating mb-3" do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :input, class: "form-control", error_class: "is-invalid", valid_class: "is-valid" + b.use :label + b.use :full_error, wrap_with: {class: "invalid-feedback"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # custom multi select + config.wrappers :floating_labels_select, class: "form-floating mb-3" do |b| + b.use :html5 + b.optional :readonly + b.use :input, class: "form-select", error_class: "is-invalid", valid_class: "is-valid" + b.use :label + b.use :full_error, wrap_with: {class: "invalid-feedback"} + b.use :hint, wrap_with: {class: "form-text"} + end + + # The default wrapper to be used by the FormBuilder. + config.default_wrapper = :vertical_form + + # Custom wrappers for input types. This should be a hash containing an input + # type as key and the wrapper that will be used for all inputs with specified type. + config.wrapper_mappings = { + boolean: :vertical_boolean, + check_boxes: :vertical_collection, + date: :vertical_multi_select, + datetime: :vertical_multi_select, + file: :vertical_file, + radio_buttons: :vertical_collection, + range: :vertical_range, + time: :vertical_multi_select, + select: :vertical_select + } +end diff --git a/config/initializers/statesman.rb b/config/initializers/statesman.rb index 852d061fb..6085cf934 100644 --- a/config/initializers/statesman.rb +++ b/config/initializers/statesman.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true + +require "statesman" + Statesman.configure do storage_adapter(Statesman::Adapters::ActiveRecord) end diff --git a/config/routes.rb b/config/routes.rb index 192794875..0c92d6f38 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -22,18 +22,18 @@ # GEOMG // Metadata Toolkit JSON-API # - Only JSON GET requests - namespace :admin do - # AdvancedSearch controller - get '/advanced_search' => 'advanced_search#index', constraints: lambda { |req| req.format == :json } - get '/advanced_search/facets' => 'advanced_search#facets', constraints: lambda { |req| req.format == :json } - get '/advanced_search/facet/:id' => 'advanced_search#facet', constraints: lambda { |req| req.format == :json }, as: 'advanced_search_facet' - - # Ids controller - get '/api/ids' => 'ids#index', constraints: lambda { |req| req.format == :json } - get '/api' => 'api#index', constraints: lambda { |req| req.format == :json } - get '/api/fetch' => 'api#fetch', constraints: lambda { |req| req.format == :json } - get '/api/facet/:id' => 'api#facet', constraints: lambda { |req| req.format == :json } - end + # namespace :admin do + # # AdvancedSearch controller + # get '/advanced_search' => 'advanced_search#index', constraints: lambda { |req| req.format == :json } + # get '/advanced_search/facets' => 'advanced_search#facets', constraints: lambda { |req| req.format == :json } + # get '/advanced_search/facet/:id' => 'advanced_search#facet', constraints: lambda { |req| req.format == :json }, as: 'advanced_search_facet' + + # # Ids controller + # get '/api/ids' => 'ids#index', constraints: lambda { |req| req.format == :json } + # get '/api' => 'api#index', constraints: lambda { |req| req.format == :json } + # get '/api/fetch' => 'api#fetch', constraints: lambda { |req| req.format == :json } + # get '/api/facet/:id' => 'api#facet', constraints: lambda { |req| req.format == :json } + # end resource :catalog, only: [:index], as: 'catalog', path: '/catalog', controller: 'catalog' do concerns :searchable @@ -41,7 +41,7 @@ get '/catalog/:id/admin' => 'catalog#admin', as: 'admin_catalog' - devise_for :users + # devise_for :users resources :suggest, only: :index, defaults: { format: 'json' } @@ -80,6 +80,181 @@ end end + #################### + # GBL‡ADMIN + + # Bulk Actions + resources :bulk_actions do + patch :run, on: :member + patch :revert, on: :member + end + + # Users + devise_for :users, controllers: {invitations: "devise/invitations"}, skip: [:registrations] + as :user do + get "/sign_in" => "devise/sessions#new" # custom path to login/sign_in + get "/sign_up" => "devise/registrations#new", :as => "new_user_registration" # custom path to sign_up/registration + get "users/edit" => "devise/registrations#edit", :as => "edit_user_registration" + put "users" => "devise/registrations#update", :as => "user_registration" + end + + namespace :admin do + devise_for :users, controllers: {invitations: "devise/invitations"}, skip: [:registrations] + # Root + root to: "documents#index" + + # Bulk Actions + resources :bulk_actions do + patch :run, on: :member + patch :revert, on: :member + end + + # Imports + resources :imports do + resources :mappings + resources :import_documents, only: [:show] + patch :run, on: :member + end + + # Elements + resources :elements do + post :sort, on: :collection + end + + # Form Elements + resources :form_elements do + post :sort, on: :collection + end + resources :form_header, path: :form_elements, controller: :form_elements + resources :form_group, path: :form_elements, controller: :form_elements + resources :form_control, path: :form_elements, controller: :form_elements + resources :form_feature, path: :form_elements, controller: :form_elements + + # Notifications + resources :notifications do + put "batch", on: :collection + end + + # Users + get "users/index" + + # Bookmarks + resources :bookmarks + delete "/bookmarks", to: "bookmarks#destroy", as: :bookmarks_destroy_by_fkeys + + # Search controller + get "/search" => "search#index" + + # AdvancedSearch controller + get '/advanced_search' => 'advanced_search#index', constraints: lambda { |req| req.format == :json } + get '/advanced_search/facets' => 'advanced_search#facets', constraints: lambda { |req| req.format == :json } + get '/advanced_search/facet/:id' => 'advanced_search#facet', constraints: lambda { |req| req.format == :json }, as: 'advanced_search_facet' + + # Ids controller + get '/api/ids' => 'ids#index', constraints: lambda { |req| req.format == :json } + get '/api' => 'api#index', constraints: lambda { |req| req.format == :json } + get '/api/fetch' => 'api#fetch', constraints: lambda { |req| req.format == :json } + get '/api/facet/:id' => 'api#facet', constraints: lambda { |req| req.format == :json } + + # Documents + resources :documents do + get "versions" + + # DocumentAccesses + resources :document_accesses, path: "access" do + collection do + get "import" + post "import" + + get "destroy_all" + post "destroy_all" + end + end + + # DocumentDownloads + resources :document_downloads, path: "downloads" do + collection do + get "import" + post "import" + + get "destroy_all" + post "destroy_all" + end + end + + # Document Assets + resources :document_assets, path: "assets" do + collection do + get "display_attach_form" + post "attach_files" + + get "destroy_all" + post "destroy_all" + end + end + + collection do + get "fetch" + end + end + + # Document Accesses + resources :document_accesses, path: "access" do + collection do + get "import" + post "import" + + get "destroy_all" + post "destroy_all" + end + end + + # Document Downloads + resources :document_downloads, path: "downloads" do + collection do + get "import" + post "import" + + get "destroy_all" + post "destroy_all" + end + end + + # Document Assets + resources :document_assets, path: "assets" do + collection do + get "display_attach_form" + post "attach_files" + + get "destroy_all" + post "destroy_all" + end + end + + get "/documents/:id/ingest", to: "document_assets#display_attach_form", as: "asset_ingest" + post "/documents/:id/ingest", to: "document_assets#attach_files" + mount Kithe::AssetUploader.upload_endpoint(:cache) => "/direct_upload", :as => :direct_app_upload + + resources :collections, except: [:show] + + # Note "assets" is Rails reserved word for routing, oops. So we use + # asset_files. + resources :assets, path: "asset_files", except: [:new, :create] do + member do + put "convert_to_child_work" + end + end + + # @TODO + # mount Qa::Engine => "/authorities" + mount ActionCable.server => "/cable" + + # @TODO + authenticate :user, ->(user) { user } do + mount Blazer::Engine, at: "blazer" + end + end + # Blog redirects get '/blog', :to => redirect('https://sites.google.com/umn.edu/btaa-gdp/news') get '/blog/index.html', :to => redirect('https://sites.google.com/umn.edu/btaa-gdp/news') diff --git a/config/schedule.rb b/config/schedule.rb index 76d5d590b..059ad6789 100644 --- a/config/schedule.rb +++ b/config/schedule.rb @@ -36,16 +36,17 @@ every '0 3 * * 1', roles: [:app] do rake 'geoportal:sidecar_states' end -# URI analysis -every '0 1 1 * *', roles: [:prodcron] do - rake 'geoportal:uri_purge' -end -every '0 2 1 * *', roles: [:prodcron] do - rake 'geoportal:uri_process_all' -end -every '0 1 2 * *', roles: [:prodcron] do - rake 'geoportal:uri_queue_incomplete_states' -end -every '0 8 2 * *', roles: [:prodcron] do - rake 'geoportal:uri_report' -end + +# URI analysis - No longer required - EWL 10/11/23 +# every '0 1 1 * *', roles: [:prodcron] do +# rake 'geoportal:uri_purge' +# end +# every '0 2 1 * *', roles: [:prodcron] do +# rake 'geoportal:uri_process_all' +# end +# every '0 1 2 * *', roles: [:prodcron] do +# rake 'geoportal:uri_queue_incomplete_states' +# end +# every '0 8 2 * *', roles: [:prodcron] do +# rake 'geoportal:uri_report' +# end diff --git a/config/webpacker.yml b/config/webpacker.yml index 237a5d033..85eed7036 100644 --- a/config/webpacker.yml +++ b/config/webpacker.yml @@ -6,12 +6,11 @@ default: &default public_root_path: public public_output_path: packs cache_path: tmp/cache/webpacker - check_yarn_integrity: false webpack_compile_output: true # Additional paths webpack should lookup modules # ['app/assets', 'engine/foo/app/assets'] - resolved_paths: ['app/assets'] + additional_paths: ['vendor/yarn'] # Reload manifest.json on all requests so we reload latest compiled packs cache_manifest: false @@ -52,9 +51,6 @@ development: <<: *default compile: true - # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules - check_yarn_integrity: true - # Reference: https://webpack.js.org/configuration/dev-server/ dev_server: https: false @@ -69,6 +65,7 @@ development: disable_host_check: true use_local_ip: false quiet: false + pretty: false headers: 'Access-Control-Allow-Origin': '*' watch_options: diff --git a/db/migrate/20160419175431_create_searches.blacklight.rb b/db/migrate/20160419175431_create_searches.blacklight.rb deleted file mode 100644 index 629ddff07..000000000 --- a/db/migrate/20160419175431_create_searches.blacklight.rb +++ /dev/null @@ -1,19 +0,0 @@ -# This migration comes from blacklight (originally 20140202020201) -# -*- encoding : utf-8 -*- -class CreateSearches < ActiveRecord::Migration[5.1] - def self.up - create_table :searches do |t| - t.text :query_params - t.integer :user_id - t.string :user_type - - t.timestamps null: false - end - - add_index :searches, :user_id - end - - def self.down - drop_table :searches - end -end diff --git a/db/migrate/20160419175432_create_bookmarks.blacklight.rb b/db/migrate/20160419175432_create_bookmarks.blacklight.rb deleted file mode 100644 index fe252b9a3..000000000 --- a/db/migrate/20160419175432_create_bookmarks.blacklight.rb +++ /dev/null @@ -1,18 +0,0 @@ -# This migration comes from blacklight (originally 20140202020202) -# -*- encoding : utf-8 -*- -class CreateBookmarks < ActiveRecord::Migration[5.1] - def self.up - create_table :bookmarks do |t| - t.integer :user_id, :null=>false - t.string :user_type - t.string :document_id - t.string :title - t.timestamps null: false - end - end - - def self.down - drop_table :bookmarks - end - -end diff --git a/db/migrate/20160419175433_add_polymorphic_type_to_bookmarks.blacklight.rb b/db/migrate/20160419175433_add_polymorphic_type_to_bookmarks.blacklight.rb deleted file mode 100644 index efa9f24b9..000000000 --- a/db/migrate/20160419175433_add_polymorphic_type_to_bookmarks.blacklight.rb +++ /dev/null @@ -1,9 +0,0 @@ -# This migration comes from blacklight (originally 20140320000000) -# -*- encoding : utf-8 -*- -class AddPolymorphicTypeToBookmarks < ActiveRecord::Migration[5.1] - def change - add_column(:bookmarks, :document_type, :string) - - add_index :bookmarks, :user_id - end -end diff --git a/db/migrate/20160419175437_devise_create_users.rb b/db/migrate/20160419175437_devise_create_users.rb deleted file mode 100644 index 48be42b87..000000000 --- a/db/migrate/20160419175437_devise_create_users.rb +++ /dev/null @@ -1,42 +0,0 @@ -class DeviseCreateUsers < ActiveRecord::Migration[5.1] - def change - create_table(:users) do |t| - ## Database authenticatable - t.string :email, null: false, default: "" - t.string :encrypted_password, null: false, default: "" - - ## Recoverable - t.string :reset_password_token - t.datetime :reset_password_sent_at - - ## Rememberable - t.datetime :remember_created_at - - ## Trackable - t.integer :sign_in_count, default: 0, null: false - t.datetime :current_sign_in_at - t.datetime :last_sign_in_at - t.string :current_sign_in_ip - t.string :last_sign_in_ip - - ## Confirmable - # t.string :confirmation_token - # t.datetime :confirmed_at - # t.datetime :confirmation_sent_at - # t.string :unconfirmed_email # Only if using reconfirmable - - ## Lockable - # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts - # t.string :unlock_token # Only if unlock strategy is :email or :both - # t.datetime :locked_at - - - t.timestamps null: false - end - - add_index :users, :email, unique: true - add_index :users, :reset_password_token, unique: true - # add_index :users, :confirmation_token, unique: true - # add_index :users, :unlock_token, unique: true - end -end diff --git a/db/migrate/20160419175438_add_devise_guests_to_users.rb b/db/migrate/20160419175438_add_devise_guests_to_users.rb deleted file mode 100644 index b2618a51f..000000000 --- a/db/migrate/20160419175438_add_devise_guests_to_users.rb +++ /dev/null @@ -1,15 +0,0 @@ -class AddDeviseGuestsToUsers < ActiveRecord::Migration[5.1] - def self.up - change_table(:users) do |t| - ## Database authenticatable - t.boolean :guest, :default => false - end - - end - - def self.down - # By default, we don't want to make any assumption about how to roll back a migration when your - # model already existed. Please edit below which fields you would like to remove in this migration. - raise ActiveRecord::IrreversibleMigration - end -end diff --git a/db/migrate/20180627150806_create_pointless_feedback_messages.pointless_feedback.rb b/db/migrate/20180627150806_create_pointless_feedback_messages.pointless_feedback.rb deleted file mode 100644 index 93de839bd..000000000 --- a/db/migrate/20180627150806_create_pointless_feedback_messages.pointless_feedback.rb +++ /dev/null @@ -1,14 +0,0 @@ -# This migration comes from pointless_feedback (originally 20130501182659) -class CreatePointlessFeedbackMessages < ActiveRecord::Migration[5.1] - def change - create_table :pointless_feedback_messages do |t| - t.string :name - t.string :email_address - t.string :topic - t.text :description - t.text :previous_url - - t.timestamps - end - end -end diff --git a/db/migrate/20190822211031_create_active_storage_tables.active_storage.rb b/db/migrate/20190822211031_create_active_storage_tables.active_storage.rb deleted file mode 100644 index 0b2ce257c..000000000 --- a/db/migrate/20190822211031_create_active_storage_tables.active_storage.rb +++ /dev/null @@ -1,27 +0,0 @@ -# This migration comes from active_storage (originally 20170806125915) -class CreateActiveStorageTables < ActiveRecord::Migration[5.2] - def change - create_table :active_storage_blobs do |t| - t.string :key, null: false - t.string :filename, null: false - t.string :content_type - t.text :metadata - t.bigint :byte_size, null: false - t.string :checksum, null: false - t.datetime :created_at, null: false - - t.index [ :key ], unique: true - end - - create_table :active_storage_attachments do |t| - t.string :name, null: false - t.references :record, null: false, polymorphic: true, index: false - t.references :blob, null: false - - t.datetime :created_at, null: false - - t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true - t.foreign_key :active_storage_blobs, column: :blob_id - end - end -end diff --git a/db/migrate/20211006201348_create_active_storage_variant_records.active_storage.rb b/db/migrate/20211006201348_create_active_storage_variant_records.active_storage.rb deleted file mode 100644 index a2862695e..000000000 --- a/db/migrate/20211006201348_create_active_storage_variant_records.active_storage.rb +++ /dev/null @@ -1,12 +0,0 @@ -# This migration comes from active_storage (originally 20191206030411) -class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0] - def change - create_table :active_storage_variant_records do |t| - t.belongs_to :blob, null: false, index: false - t.string :variation_digest, null: false - - t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true - t.foreign_key :active_storage_blobs, column: :blob_id - end - end -end diff --git a/db/migrate/20230911192235_add_statesman_tables.rb b/db/migrate/20230911192235_add_statesman_tables.rb new file mode 100644 index 000000000..edaf96cb7 --- /dev/null +++ b/db/migrate/20230911192235_add_statesman_tables.rb @@ -0,0 +1,75 @@ +class AddStatesmanTables < ActiveRecord::Migration[6.1] + def change + + unless ActiveRecord::Base.connection.table_exists? 'image_upload_transitions' + # Image Upload Transitions + create_table "image_upload_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata" + t.integer "sort_key", null: false + t.bigint "solr_document_sidecar_id" + t.boolean "most_recent", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["solr_document_sidecar_id", "sort_key"], name: "index_image_upload_transitions_parent_sort", unique: true + t.index ["solr_document_sidecar_id"], name: "index_image_upload_transitions_on_solr_document_sidecar_id" + end + end + + unless ActiveRecord::Base.connection.table_exists? 'sidecar_image_transitions' + # Sidecar Image Transitions + create_table "sidecar_image_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata" + t.integer "sort_key", null: false + t.bigint "solr_document_sidecar_id", null: false + t.boolean "most_recent" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["solr_document_sidecar_id", "sort_key"], name: "index_sidecar_image_transitions_parent_sort", unique: true + end + end + + unless ActiveRecord::Base.connection.table_exists? 'solr_document_uris' + # Solr Document URIs + create_table "solr_document_uris", force: :cascade do |t| + t.string "document_id" + t.string "document_type" + t.string "uri_key" + t.string "uri_value" + t.bigint "version" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["document_type", "document_id"], name: "solr_document_uris_solr_document" + end + end + + unless ActiveRecord::Base.connection.table_exists? 'uri_transitions' + # URI Transitions + create_table "uri_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata" + t.integer "sort_key", null: false + t.bigint "solr_document_uri_id" + t.boolean "most_recent", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["solr_document_uri_id", "sort_key"], name: "index_uri_transitions_parent_sort", unique: true + t.index ["solr_document_uri_id"], name: "index_uri_transitions_on_solr_document_uri_id" + end + end + + # Indexes + unless foreign_key_exists?(:image_upload_transitions, :solr_document_sidecars) + add_foreign_key "image_upload_transitions", "solr_document_sidecars" + end + + unless foreign_key_exists?(:sidecar_image_transitions, :solr_document_sidecars) + add_foreign_key "sidecar_image_transitions", "solr_document_sidecars" + end + + unless foreign_key_exists?(:uri_transitions, :solr_document_uris) + add_foreign_key "uri_transitions", "solr_document_uris" + end + end +end diff --git a/db/migrate/20231009160910_add_gbl_admin.rb b/db/migrate/20231009160910_add_gbl_admin.rb new file mode 100644 index 000000000..0c10728a8 --- /dev/null +++ b/db/migrate/20231009160910_add_gbl_admin.rb @@ -0,0 +1,410 @@ +class AddGblAdmin < ActiveRecord::Migration[6.1] + def change + # These are extensions that must be enabled in order to support this database + enable_extension "pgcrypto" + enable_extension "plpgsql" + + create_function :kithe_models_friendlier_id_gen, sql_definition: <<-'SQL' + CREATE OR REPLACE FUNCTION public.kithe_models_friendlier_id_gen(min_value bigint, max_value bigint) + RETURNS text + LANGUAGE plpgsql + AS $function$ + DECLARE + new_id_int bigint; + new_id_str character varying := ''; + done bool; + tries integer; + alphabet char[] := ARRAY['0','1','2','3','4','5','6','7','8','9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; + alphabet_length integer := array_length(alphabet, 1); + + BEGIN + done := false; + tries := 0; + WHILE (NOT done) LOOP + tries := tries + 1; + IF (tries > 3) THEN + RAISE 'Could not find non-conflicting friendlier_id in 3 tries'; + END IF; + + new_id_int := trunc(random() * (max_value - min_value) + min_value); + + -- convert bigint to a Base-36 alphanumeric string + -- see https://web.archive.org/web/20130420084605/http://www.jamiebegin.com/base36-conversion-in-postgresql/ + -- https://gist.github.com/btbytes/7159902 + WHILE new_id_int != 0 LOOP + new_id_str := alphabet[(new_id_int % alphabet_length)+1] || new_id_str; + new_id_int := new_id_int / alphabet_length; + END LOOP; + + done := NOT exists(SELECT 1 FROM kithe_models WHERE friendlier_id=new_id_str); + END LOOP; + RETURN new_id_str; + END; + $function$ + SQL + + # active_storage_attachments: + # * integer to bigint + change_column :active_storage_attachments, :record_id, :bigint, null: false + change_column :active_storage_attachments, :blob_id, :bigint, null: false + + # active_storage_blobs + # * integer to bigint + change_column :active_storage_blobs, :byte_size, :bigint, null: false + + # Blazer + create_table "blazer_audits", force: :cascade do |t| + t.bigint "user_id" + t.bigint "query_id" + t.text "statement" + t.string "data_source" + t.datetime "created_at" + t.index ["query_id"], name: "index_blazer_audits_on_query_id" + t.index ["user_id"], name: "index_blazer_audits_on_user_id" + end + + create_table "blazer_checks", force: :cascade do |t| + t.bigint "creator_id" + t.bigint "query_id" + t.string "state" + t.string "schedule" + t.text "emails" + t.text "slack_channels" + t.string "check_type" + t.text "message" + t.datetime "last_run_at" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_checks_on_creator_id" + t.index ["query_id"], name: "index_blazer_checks_on_query_id" + end + + create_table "blazer_dashboard_queries", force: :cascade do |t| + t.bigint "dashboard_id" + t.bigint "query_id" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["dashboard_id"], name: "index_blazer_dashboard_queries_on_dashboard_id" + t.index ["query_id"], name: "index_blazer_dashboard_queries_on_query_id" + end + + create_table "blazer_dashboards", force: :cascade do |t| + t.bigint "creator_id" + t.string "name" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_dashboards_on_creator_id" + end + + create_table "blazer_queries", force: :cascade do |t| + t.bigint "creator_id" + t.string "name" + t.text "description" + t.text "statement" + t.string "data_source" + t.string "status" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_queries_on_creator_id" + end + + create_table "blazer_uploads", force: :cascade do |t| + t.bigint "creator_id" + t.string "table" + t.text "description" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_uploads_on_creator_id" + end + + # bookmarks + # * string to binary + # * index on document_id + # SKIP change_column :bookmarks, :title, :binary, null: false + # add_index :bookmarks, :document_id + + create_table "bulk_action_document_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "bulk_action_document_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["bulk_action_document_id", "most_recent"], name: "index_bulk_action_document_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["bulk_action_document_id", "sort_key"], name: "index_bulk_action_document_transitions_parent_sort", unique: true + end + + create_table "bulk_action_documents", force: :cascade do |t| + t.string "friendlier_id", null: false + t.integer "version", null: false + t.bigint "bulk_action_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.uuid "document_id" + t.index ["bulk_action_id"], name: "index_bulk_action_documents_on_bulk_action_id" + end + + create_table "bulk_action_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "bulk_action_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["bulk_action_id", "most_recent"], name: "index_bulk_action_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["bulk_action_id", "sort_key"], name: "index_bulk_action_transitions_parent_sort", unique: true + end + + create_table "bulk_actions", force: :cascade do |t| + t.string "name" + t.string "request", null: false + t.string "scope", null: false + t.string "field_name", null: false + t.string "field_value", null: false + t.text "notes" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "document_accesses", force: :cascade do |t| + t.string "friendlier_id", null: false + t.string "institution_code", null: false + t.text "access_url", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "document_downloads", force: :cascade do |t| + t.string "friendlier_id" + t.string "label" + t.string "value" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "document_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.uuid "kithe_model_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["kithe_model_id", "most_recent"], name: "index_document_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["kithe_model_id", "sort_key"], name: "index_document_transitions_parent_sort", unique: true + end + + create_table "elements", force: :cascade do |t| + t.string "label", null: false + t.string "solr_field", null: false + t.string "field_definition" + t.string "field_type", null: false + t.boolean "required", default: false, null: false + t.boolean "repeatable", default: false, null: false + t.boolean "formable", default: true, null: false + t.string "placeholder_text" + t.string "data_entry_hint" + t.string "test_fixture_example" + t.string "controlled_vocabulary" + t.string "js_behaviors" + t.text "html_attributes" + t.boolean "display_only_on_persisted", default: false, null: false + t.boolean "importable", default: true, null: false + t.boolean "import_deliminated", default: false, null: false + t.string "import_transformation_method" + t.boolean "exportable", default: true, null: false + t.string "export_transformation_method" + t.boolean "indexable", default: true, null: false + t.string "index_transformation_method" + t.string "validation_method" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.integer "position" + end + + create_table "form_elements", force: :cascade do |t| + t.string "type", null: false + t.string "label" + t.string "element_solr_field" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + # image_upload_transitions + # * integer to bigint + change_column :image_upload_transitions, :solr_document_sidecar_id, :bigint, null: false + + create_table "import_document_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "import_document_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_document_id", "most_recent"], name: "index_import_document_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["import_document_id", "sort_key"], name: "index_import_document_transitions_parent_sort", unique: true + end + + create_table "import_documents", force: :cascade do |t| + t.string "friendlier_id", null: false + t.string "title", null: false + t.json "json_attributes", default: "{}" + t.bigint "import_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_id"], name: "index_import_documents_on_import_id" + end + + create_table "import_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "import_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_id", "most_recent"], name: "index_import_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["import_id", "sort_key"], name: "index_import_transitions_parent_sort", unique: true + end + + create_table "imports", force: :cascade do |t| + t.string "name", null: false + t.string "source" + t.text "description" + t.string "filename" + t.integer "row_count" + t.text "headers", default: [], array: true + t.string "encoding" + t.string "content_type" + t.string "extension" + t.boolean "validity", default: false, null: false + t.text "validation_result" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.string "type" + end + + create_table "kithe_derivatives", force: :cascade do |t| + t.string "key", null: false + t.jsonb "file_data" + t.uuid "asset_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["asset_id", "key"], name: "index_kithe_derivatives_on_asset_id_and_key", unique: true + t.index ["asset_id"], name: "index_kithe_derivatives_on_asset_id" + end + + create_table "kithe_model_contains", id: false, force: :cascade do |t| + t.uuid "containee_id" + t.uuid "container_id" + t.index ["containee_id"], name: "index_kithe_model_contains_on_containee_id" + t.index ["container_id"], name: "index_kithe_model_contains_on_container_id" + end + + create_table "kithe_models", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + t.string "title", null: false + t.string "type", null: false + t.integer "position" + t.jsonb "json_attributes" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "parent_id" + t.string "friendlier_id", default: -> { "kithe_models_friendlier_id_gen('2821109907456'::bigint, '101559956668415'::bigint)" }, null: false + t.jsonb "file_data" + t.uuid "representative_id" + t.uuid "leaf_representative_id" + t.integer "kithe_model_type", null: false + t.bigint "import_id" + t.string "publication_state", default: "draft" + t.index ["friendlier_id"], name: "index_kithe_models_on_friendlier_id", unique: true + t.index ["import_id"], name: "index_kithe_models_on_import_id" + t.index ["leaf_representative_id"], name: "index_kithe_models_on_leaf_representative_id" + t.index ["parent_id"], name: "index_kithe_models_on_parent_id" + t.index ["representative_id"], name: "index_kithe_models_on_representative_id" + end + + create_table "mappings", force: :cascade do |t| + t.string "source_header" + t.string "destination_field" + t.boolean "delimited" + t.string "transformation_method" + t.bigint "import_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_id"], name: "index_mappings_on_import_id" + end + + create_table "notifications", force: :cascade do |t| + t.string "recipient_type", null: false + t.bigint "recipient_id", null: false + t.string "type", null: false + t.jsonb "params" + t.datetime "read_at" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["read_at"], name: "index_notifications_on_read_at" + t.index ["recipient_type", "recipient_id"], name: "index_notifications_on_recipient" + end + + # searches + # * text to binary + # SKIP change_column :searches, :query_params, :binary + + # solr_document_sidecars + change_column :solr_document_sidecars, :version, :bigint + + # solr_document_uris + change_column :solr_document_uris, :version, :bigint + + # uri_transitions + change_column :uri_transitions, :solr_document_uri_id, :bigint + + # users + add_column :users, :invitation_token, :string + add_column :users, :invitation_created_at, :datetime + add_column :users, :invitation_sent_at, :datetime + add_column :users, :invitation_accepted_at, :datetime + add_column :users, :invitation_limit, :integer + add_column :users, :invited_by_type, :string + add_column :users, :invited_by_id, :bigint + add_column :users, :invitations_count, :integer, default: 0 + add_column :users, :admin, :boolean, default: true, null: false + add_index :users, :invitation_token, unique: true + add_index :users, :invitations_count + add_index :users, :invited_by_id + add_index :users, [:invited_by_type, :invited_by_id] + + create_table "versions", force: :cascade do |t| + t.string "item_type", null: false + t.uuid "item_id", null: false + t.string "event", null: false + t.string "whodunnit" + t.text "object" + t.datetime "created_at" + t.text "object_changes" + t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" + end + + add_foreign_key "bulk_action_document_transitions", "bulk_action_documents" + add_foreign_key "bulk_action_documents", "bulk_actions" + add_foreign_key "bulk_action_transitions", "bulk_actions" + add_foreign_key "import_document_transitions", "import_documents" + add_foreign_key "import_documents", "imports" + add_foreign_key "import_transitions", "imports" + add_foreign_key "kithe_derivatives", "kithe_models", column: "asset_id" + add_foreign_key "kithe_model_contains", "kithe_models", column: "containee_id" + add_foreign_key "kithe_model_contains", "kithe_models", column: "container_id" + add_foreign_key "kithe_models", "kithe_models", column: "leaf_representative_id" + add_foreign_key "kithe_models", "kithe_models", column: "parent_id" + add_foreign_key "kithe_models", "kithe_models", column: "representative_id" + add_foreign_key "mappings", "imports" + end +end diff --git a/db/schema.rb b/db/schema.rb index 041982168..b6ed8fc02 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,13 +10,58 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_10_06_201348) do +ActiveRecord::Schema.define(version: 2023_10_09_160910) do + + # These are extensions that must be enabled in order to support this database + enable_extension "pgcrypto" + enable_extension "plpgsql" + + create_function :kithe_models_friendlier_id_gen, sql_definition: <<-'SQL' + CREATE OR REPLACE FUNCTION public.kithe_models_friendlier_id_gen(min_value bigint, max_value bigint) + RETURNS text + LANGUAGE plpgsql + AS $function$ + DECLARE + new_id_int bigint; + new_id_str character varying := ''; + done bool; + tries integer; + alphabet char[] := ARRAY['0','1','2','3','4','5','6','7','8','9', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; + alphabet_length integer := array_length(alphabet, 1); + + BEGIN + done := false; + tries := 0; + WHILE (NOT done) LOOP + tries := tries + 1; + IF (tries > 3) THEN + RAISE 'Could not find non-conflicting friendlier_id in 3 tries'; + END IF; + + new_id_int := trunc(random() * (max_value - min_value) + min_value); + + -- convert bigint to a Base-36 alphanumeric string + -- see https://web.archive.org/web/20130420084605/http://www.jamiebegin.com/base36-conversion-in-postgresql/ + -- https://gist.github.com/btbytes/7159902 + WHILE new_id_int != 0 LOOP + new_id_str := alphabet[(new_id_int % alphabet_length)+1] || new_id_str; + new_id_int := new_id_int / alphabet_length; + END LOOP; + + done := NOT exists(SELECT 1 FROM kithe_models WHERE friendlier_id=new_id_str); + END LOOP; + RETURN new_id_str; + END; + $function$ + SQL create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false - t.integer "record_id", null: false - t.integer "blob_id", null: false + t.bigint "record_id", null: false + t.bigint "blob_id", null: false t.datetime "created_at", null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true @@ -27,7 +72,7 @@ t.string "filename", null: false t.string "content_type" t.text "metadata" - t.integer "byte_size", null: false + t.bigint "byte_size", null: false t.string "checksum", null: false t.datetime "created_at", null: false t.string "service_name", null: false @@ -40,6 +85,71 @@ t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end + create_table "blazer_audits", force: :cascade do |t| + t.bigint "user_id" + t.bigint "query_id" + t.text "statement" + t.string "data_source" + t.datetime "created_at" + t.index ["query_id"], name: "index_blazer_audits_on_query_id" + t.index ["user_id"], name: "index_blazer_audits_on_user_id" + end + + create_table "blazer_checks", force: :cascade do |t| + t.bigint "creator_id" + t.bigint "query_id" + t.string "state" + t.string "schedule" + t.text "emails" + t.text "slack_channels" + t.string "check_type" + t.text "message" + t.datetime "last_run_at" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_checks_on_creator_id" + t.index ["query_id"], name: "index_blazer_checks_on_query_id" + end + + create_table "blazer_dashboard_queries", force: :cascade do |t| + t.bigint "dashboard_id" + t.bigint "query_id" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["dashboard_id"], name: "index_blazer_dashboard_queries_on_dashboard_id" + t.index ["query_id"], name: "index_blazer_dashboard_queries_on_query_id" + end + + create_table "blazer_dashboards", force: :cascade do |t| + t.bigint "creator_id" + t.string "name" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_dashboards_on_creator_id" + end + + create_table "blazer_queries", force: :cascade do |t| + t.bigint "creator_id" + t.string "name" + t.text "description" + t.text "statement" + t.string "data_source" + t.string "status" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_queries_on_creator_id" + end + + create_table "blazer_uploads", force: :cascade do |t| + t.bigint "creator_id" + t.string "table" + t.text "description" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["creator_id"], name: "index_blazer_uploads_on_creator_id" + end + create_table "bookmarks", force: :cascade do |t| t.integer "user_id", null: false t.string "user_type" @@ -51,11 +161,122 @@ t.index ["user_id"], name: "index_bookmarks_on_user_id" end + create_table "bulk_action_document_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "bulk_action_document_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["bulk_action_document_id", "most_recent"], name: "index_bulk_action_document_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["bulk_action_document_id", "sort_key"], name: "index_bulk_action_document_transitions_parent_sort", unique: true + end + + create_table "bulk_action_documents", force: :cascade do |t| + t.string "friendlier_id", null: false + t.integer "version", null: false + t.bigint "bulk_action_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.uuid "document_id" + t.index ["bulk_action_id"], name: "index_bulk_action_documents_on_bulk_action_id" + end + + create_table "bulk_action_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "bulk_action_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["bulk_action_id", "most_recent"], name: "index_bulk_action_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["bulk_action_id", "sort_key"], name: "index_bulk_action_transitions_parent_sort", unique: true + end + + create_table "bulk_actions", force: :cascade do |t| + t.string "name" + t.string "request", null: false + t.string "scope", null: false + t.string "field_name", null: false + t.string "field_value", null: false + t.text "notes" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "document_accesses", force: :cascade do |t| + t.string "friendlier_id", null: false + t.string "institution_code", null: false + t.text "access_url", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "document_downloads", force: :cascade do |t| + t.string "friendlier_id" + t.string "label" + t.string "value" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + + create_table "document_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.uuid "kithe_model_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["kithe_model_id", "most_recent"], name: "index_document_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["kithe_model_id", "sort_key"], name: "index_document_transitions_parent_sort", unique: true + end + + create_table "elements", force: :cascade do |t| + t.string "label", null: false + t.string "solr_field", null: false + t.string "field_definition" + t.string "field_type", null: false + t.boolean "required", default: false, null: false + t.boolean "repeatable", default: false, null: false + t.boolean "formable", default: true, null: false + t.string "placeholder_text" + t.string "data_entry_hint" + t.string "test_fixture_example" + t.string "controlled_vocabulary" + t.string "js_behaviors" + t.text "html_attributes" + t.boolean "display_only_on_persisted", default: false, null: false + t.boolean "importable", default: true, null: false + t.boolean "import_deliminated", default: false, null: false + t.string "import_transformation_method" + t.boolean "exportable", default: true, null: false + t.string "export_transformation_method" + t.boolean "indexable", default: true, null: false + t.string "index_transformation_method" + t.string "validation_method" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.integer "position" + end + + create_table "form_elements", force: :cascade do |t| + t.string "type", null: false + t.string "label" + t.string "element_solr_field" + t.integer "position" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + create_table "image_upload_transitions", force: :cascade do |t| t.string "to_state", null: false t.text "metadata" t.integer "sort_key", null: false - t.integer "solr_document_sidecar_id" + t.bigint "solr_document_sidecar_id", null: false t.boolean "most_recent", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -63,6 +284,119 @@ t.index ["solr_document_sidecar_id"], name: "index_image_upload_transitions_on_solr_document_sidecar_id" end + create_table "import_document_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "import_document_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_document_id", "most_recent"], name: "index_import_document_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["import_document_id", "sort_key"], name: "index_import_document_transitions_parent_sort", unique: true + end + + create_table "import_documents", force: :cascade do |t| + t.string "friendlier_id", null: false + t.string "title", null: false + t.json "json_attributes", default: "{}" + t.bigint "import_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_id"], name: "index_import_documents_on_import_id" + end + + create_table "import_transitions", force: :cascade do |t| + t.string "to_state", null: false + t.text "metadata", default: "{}" + t.integer "sort_key", null: false + t.integer "import_id", null: false + t.boolean "most_recent", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_id", "most_recent"], name: "index_import_transitions_parent_most_recent", unique: true, where: "most_recent" + t.index ["import_id", "sort_key"], name: "index_import_transitions_parent_sort", unique: true + end + + create_table "imports", force: :cascade do |t| + t.string "name", null: false + t.string "source" + t.text "description" + t.string "filename" + t.integer "row_count" + t.text "headers", default: [], array: true + t.string "encoding" + t.string "content_type" + t.string "extension" + t.boolean "validity", default: false, null: false + t.text "validation_result" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.string "type" + end + + create_table "kithe_derivatives", force: :cascade do |t| + t.string "key", null: false + t.jsonb "file_data" + t.uuid "asset_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["asset_id", "key"], name: "index_kithe_derivatives_on_asset_id_and_key", unique: true + t.index ["asset_id"], name: "index_kithe_derivatives_on_asset_id" + end + + create_table "kithe_model_contains", id: false, force: :cascade do |t| + t.uuid "containee_id" + t.uuid "container_id" + t.index ["containee_id"], name: "index_kithe_model_contains_on_containee_id" + t.index ["container_id"], name: "index_kithe_model_contains_on_container_id" + end + + create_table "kithe_models", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + t.string "title", null: false + t.string "type", null: false + t.integer "position" + t.jsonb "json_attributes" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.uuid "parent_id" + t.string "friendlier_id", default: -> { "kithe_models_friendlier_id_gen('2821109907456'::bigint, '101559956668415'::bigint)" }, null: false + t.jsonb "file_data" + t.uuid "representative_id" + t.uuid "leaf_representative_id" + t.integer "kithe_model_type", null: false + t.bigint "import_id" + t.string "publication_state", default: "draft" + t.index ["friendlier_id"], name: "index_kithe_models_on_friendlier_id", unique: true + t.index ["import_id"], name: "index_kithe_models_on_import_id" + t.index ["leaf_representative_id"], name: "index_kithe_models_on_leaf_representative_id" + t.index ["parent_id"], name: "index_kithe_models_on_parent_id" + t.index ["representative_id"], name: "index_kithe_models_on_representative_id" + end + + create_table "mappings", force: :cascade do |t| + t.string "source_header" + t.string "destination_field" + t.boolean "delimited" + t.string "transformation_method" + t.bigint "import_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["import_id"], name: "index_mappings_on_import_id" + end + + create_table "notifications", force: :cascade do |t| + t.string "recipient_type", null: false + t.bigint "recipient_id", null: false + t.string "type", null: false + t.jsonb "params" + t.datetime "read_at" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["read_at"], name: "index_notifications_on_read_at" + t.index ["recipient_type", "recipient_id"], name: "index_notifications_on_recipient" + end + create_table "pointless_feedback_messages", force: :cascade do |t| t.string "name" t.string "email_address" @@ -97,7 +431,7 @@ t.string "document_id" t.string "document_type" t.string "cw_image" - t.integer "version", limit: 8 + t.bigint "version" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["document_type", "document_id"], name: "solr_document_sidecars_solr_document" @@ -108,7 +442,7 @@ t.string "document_type" t.string "uri_key" t.string "uri_value" - t.integer "version", limit: 8 + t.bigint "version" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["document_type", "document_id"], name: "solr_document_uris_solr_document" @@ -118,7 +452,7 @@ t.string "to_state", null: false t.text "metadata" t.integer "sort_key", null: false - t.integer "solr_document_uri_id" + t.bigint "solr_document_uri_id" t.boolean "most_recent", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -140,13 +474,50 @@ t.datetime "created_at", null: false t.datetime "updated_at", null: false t.boolean "guest", default: false + t.string "invitation_token" + t.datetime "invitation_created_at" + t.datetime "invitation_sent_at" + t.datetime "invitation_accepted_at" + t.integer "invitation_limit" + t.string "invited_by_type" + t.bigint "invited_by_id" + t.integer "invitations_count", default: 0 + t.boolean "admin", default: true, null: false t.index ["email"], name: "index_users_on_email", unique: true + t.index ["invitation_token"], name: "index_users_on_invitation_token", unique: true + t.index ["invitations_count"], name: "index_users_on_invitations_count" + t.index ["invited_by_id"], name: "index_users_on_invited_by_id" + t.index ["invited_by_type", "invited_by_id"], name: "index_users_on_invited_by_type_and_invited_by_id" t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true end + create_table "versions", force: :cascade do |t| + t.string "item_type", null: false + t.uuid "item_id", null: false + t.string "event", null: false + t.string "whodunnit" + t.text "object" + t.datetime "created_at" + t.text "object_changes" + t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" + end + add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "bulk_action_document_transitions", "bulk_action_documents" + add_foreign_key "bulk_action_documents", "bulk_actions" + add_foreign_key "bulk_action_transitions", "bulk_actions" add_foreign_key "image_upload_transitions", "solr_document_sidecars" + add_foreign_key "import_document_transitions", "import_documents" + add_foreign_key "import_documents", "imports" + add_foreign_key "import_transitions", "imports" + add_foreign_key "kithe_derivatives", "kithe_models", column: "asset_id" + add_foreign_key "kithe_model_contains", "kithe_models", column: "containee_id" + add_foreign_key "kithe_model_contains", "kithe_models", column: "container_id" + add_foreign_key "kithe_models", "kithe_models", column: "leaf_representative_id" + add_foreign_key "kithe_models", "kithe_models", column: "parent_id" + add_foreign_key "kithe_models", "kithe_models", column: "representative_id" + add_foreign_key "mappings", "imports" add_foreign_key "sidecar_image_transitions", "solr_document_sidecars" add_foreign_key "uri_transitions", "solr_document_uris" end diff --git a/db/seeds.rb b/db/seeds.rb index 4edb1e857..53bbc16ca 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -5,3 +5,4 @@ # # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) # Mayor.create(name: 'Emanuel', city: cities.first) +GeoblacklightAdmin::Engine.load_seed \ No newline at end of file diff --git a/package.json b/package.json index e2090a535..de21e7adf 100644 --- a/package.json +++ b/package.json @@ -19,21 +19,35 @@ "devDependencies": { "@babel/cli": "^7.5.5", "@babel/core": "^7.7.2", - "@babel/preset-env": "^7.7.1", "@babel/register": "^7.7.0", - "babel-loader": "^8.0.6", "shx": "^0.3.2", "webpack-dev-server": "^3.9.0" }, "dependencies": { "@babel/cli": "^7.5.5", + "@babel/helpers": "^7.22.15", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@babel/plugin-transform-runtime": "^7.22.15", "@babel/polyfill": "^7.7.0", + "@babel/preset-env": "^7.7.1", "@babel/preset-react": "^7.7.4", "@blueprintjs/core": "^3.26.0", - "@rails/webpacker": "^4.2.0", + "@nathanvda/cocoon": "^1.2.14", + "@rails/actioncable": "^7.0.7-2", + "@rails/activestorage": "^7.0.7-2", + "@rails/ujs": "^7.0.7-2", + "@rails/webpacker": "^5.4.4", + "babel-loader": "^8.0.6", "bloodhound-js": "^1.2.3", - "bootstrap": "^4.3.1", + "bootstrap": "^4.5.0", + "bootstrap-datepicker": "^1.10.0", + "chosen-jquery": "^0.1.1", "core-js": "^3.4.8", + "devbridge-autocomplete": "^1.4.11", + "highcharts": "^11.1.0", + "i18n": "^0.15.1", + "inputmask": "^5.0.8", "jquery": "3.5.1", "js-cookie": "^2.2.1", "linkifyjs": "^2.1.9", @@ -41,11 +55,21 @@ "lodash.template": "^4.5.0", "mirador": "3.0.0-beta.7", "mirador-dl-plugin": "0.11.0", + "moment": "^2.29.4", + "node-forge": "^1.3.1", + "popper.js": "^1.16.1", "react": "^16.12.0", "react-dom": "^16.12.0", - "serialize-javascript": "^2.1.1", + "serialize-javascript": "^6.0.1", + "shave": "^5.0.3", + "stimulus": "^1.1.1", + "stimulus-scroll-to": "^2.0.1", + "turbolinks": "^5.2.0", "typeahead.js": "^0.11.1", "unfetch": "^4.1.0", - "url-polyfill": "^1.1.7" + "url-polyfill": "^1.1.7", + "webpack": "^4.46.0", + "webpack-cli": "^3.3.12", + "yargs-parser": "^21.1.1" } } diff --git a/solr/conf/core.properties b/solr/conf/core.properties new file mode 100644 index 000000000..5ac078400 --- /dev/null +++ b/solr/conf/core.properties @@ -0,0 +1,5 @@ +#Written by CorePropertiesLocator +#name=geoblacklight #Change the name to the appropriate one you would like to use +config=solrconfig.xml +schema=schema.xml +#dataDir=geodata #Change this directory to the appropriate one you would like to use diff --git a/solr/conf/schema.xml b/solr/conf/schema.xml index 5790d8a12..c8f475539 100644 --- a/solr/conf/schema.xml +++ b/solr/conf/schema.xml @@ -18,9 +18,9 @@ - + - + - + diff --git a/solr/snapshots/.keep b/solr/snapshots/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/bug_report.md b/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..4cc2890e8 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + + + +- [ ] I've looked at the [documentation](http://leafletjs.com/reference.html) to make sure the behavior is documented and expected +- [ ] I'm sure this is a Leaflet code issue, not an issue with my own code nor with the framework I'm using (Cordova, Ionic, Angular, React…) +- [ ] I've searched through the issues to make sure it's not yet reported + +**Steps to reproduce** +Steps to reproduce the behavior: +- step 1 +- step 2 +- ... + +**Expected behavior** + + +**Current behavior** + + +**Environment** +- Leaflet version: +- Browser (with version): +- OS/Platform (with version): + +**Additional context** + + +**Minimal example reproducing the issue** + +Please create an example using https://leafletjs.com/edit.html or any other jsfiddle-like site. + +- [ ] this example is as simple as possible +- [ ] this example does not rely on any third party code diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/feature_request.md b/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..066b2d920 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/support.md b/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/support.md new file mode 100644 index 000000000..7fdaa4a7b --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/.github/ISSUE_TEMPLATE/support.md @@ -0,0 +1,17 @@ +--- +name: Support +about: I need support with Leaflet + +--- + +--------------^ Click "Preview" tab for a nicer view! + +We use GitHub as an issue tracker. +For usage and support questions, please check out resources below: + +1. Read Leaflet documentation: https://leafletjs.com +2. For support questions like "How can I do X with Leaflet?" please search or ask questions on StackOverflow or StackExchange using Leaflet tag: + - https://stackoverflow.com/questions/tagged/leaflet + - https://gis.stackexchange.com/questions/tagged/leaflet + +Thanks! diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/.gitignore b/vendor/assets/javascripts/Leaflet-1.4.0/.gitignore new file mode 100644 index 000000000..f3eb61742 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/.gitignore @@ -0,0 +1,22 @@ +node_modules +.DS_Store +tmp/**/* +.idea +.idea/**/* +*.iml +_site +*.sublime-* +_site +dist/*.js +dist/*.map +dist/reference.html +coverage/ +*.js.html +.mailmap +bower.json +component.json +debug/local/ +Gemfile.lock +package-lock.json +yarn.lock +*.log diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/.travis.yml b/vendor/assets/javascripts/Leaflet-1.4.0/.travis.yml new file mode 100644 index 000000000..105e42c4d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/.travis.yml @@ -0,0 +1,32 @@ +sudo: false +language: node_js +node_js: + - node +addons: + artifacts: + paths: + - dist + target_paths: + - content/leaflet/${NAME} + firefox: latest +env: + global: + - ARTIFACTS_BUCKET=leafletjs-cdn + - ARTIFACTS_PERMISSIONS=public-read + - secure: |- + JlC1rD7WryxlUbWmD3NWVX9E60XB/+ss7+j0OaY3WqWziGUWDCuoVkOMGXnp + Ev27O8qhlmRkeyiimUN64UzK0yeZ139DcZMY6r4A5E2kwHYRAO/H/zl5RAGo + Yd9GUPwZfr3xV8WhH2GFy/L/mRjkGwue2o6ZxdsqBOKfYaF9Ryg= + - secure: |- + XW1hzORAtSpTgTKkQwel5gRMDy6SotzeSRsVV2jQCn46VIMx8G/J5nOI+ImL + yeoH12PhCR0h39dM7mq8TYJo5DHwvbotI5nQhpMruSt8eMFbym8nGiqQh806 + fSJXkxmQ4MAjUdNFDIirBHhdZme8q3PueFzJ+5odFMvPGn/aITQ= +script: + - npm test + - xvfb-run --server-args="-screen 0 1280x1024x16" npm run test-nolint -- --browsers Firefox +after_success: + - npm run build + - cd dist && zip -x .DS_Store -r leaflet.zip . && cd .. + - NAME=$TRAVIS_BRANCH + - '[[ $TRAVIS_PULL_REQUEST != ''false'' ]] && NAME=$TRAVIS_PULL_REQUEST' + - '[[ -n $TRAVIS_TAG ]] && NAME=$TRAVIS_TAG' diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/CHANGELOG.md b/vendor/assets/javascripts/Leaflet-1.4.0/CHANGELOG.md new file mode 100644 index 000000000..7509dec77 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/CHANGELOG.md @@ -0,0 +1,1756 @@ +Leaflet Changelog +================= + +(all changes without author notice are by [@mourner](https://github.com/mourner)) + +## 1.3.4 (2018-08-21) + +### Improvements + +* Reset max-width and max-height styles for tiles in custom panes ([#6255](https://github.com/Leaflet/Leaflet/issues/6255) by [jerekshoe](https://github.com/jerekshoe)) +* Add unprefixed `cursor: grab` style ([#6281](https://github.com/Leaflet/Leaflet/issues/6281) by [Malvoz](https://github.com/Malvoz)) +* Remove legacy prefixed styles, add unprefixed styles ([#6282](https://github.com/Leaflet/Leaflet/issues/6282) by [Malvoz](https://github.com/Malvoz)) + +### Bug fixes + +* Move set/getAttribute('src') calls from `GridLayer` into `TileLayer` ([#6264](https://github.com/Leaflet/Leaflet/issues/6264) by [IvanSanchez](https://github.com/IvanSanchez)) +* Support comma- or space-separated strings in `Canvas` `dashArray` option ([#6277](https://github.com/Leaflet/Leaflet/issues/6277) by [IvanSanchez](https://github.com/IvanSanchez)) +* Remove trailing commas to avoid crashes in some IE browsers ([#6279](https://github.com/Leaflet/Leaflet/issues/6279) by [helbling](https://github.com/helbling)) +* Fixed capitalization of `webkitTransform` property, which broke transformations on certain Webkit browsers ([#6290](https://github.com/Leaflet/Leaflet/issues/6290) by [tuckergordon](https://github.com/tuckergordon)) + +### Docs & Web Site + +* Document `zoomControl` map option ([#6254](https://github.com/Leaflet/Leaflet/issues/6254) by [IvanSanchez](https://github.com/IvanSanchez)) +* Explicitly note attribution obligation ([#6261](https://github.com/Leaflet/Leaflet/issues/6261) by [pietervdvn](https://github.com/pietervdvn)) +* Minor fixes of `ImageOverlay` docs ([#6266](https://github.com/Leaflet/Leaflet/issues/6266) by [jgravois](https://github.com/jgravois)) +* Add Edge to the list of supported browsers ([#6270](https://github.com/Leaflet/Leaflet/issues/6270) by [matkoniecz](https://github.com/matkoniecz)) +* Remove references to Leaflet UserVoice page ([#6291](https://github.com/Leaflet/Leaflet/issues/6291) by [zstadler](https://github.com/zstadler)) +* Reword docstrings for draggable markers ([#6296](https://github.com/Leaflet/Leaflet/issues/6296) by [IvanSanchez](https://github.com/IvanSanchez)) + +## 1.3.3 (2018-07-18) + +### Bug fixes + +* Remove `module` field from `package.json` ([#6239](https://github.com/Leaflet/Leaflet/issues/6239)) + +## 1.3.2 (2018-07-17) + +### Improvements + +* Add `use-credentials` CORS option to `ImageOverlay` and `TileLayer` ([#6016](https://github.com/Leaflet/Leaflet/issues/6016) by [caleblogan](https://github.com/caleblogan)) + unit tests ([#6022](https://github.com/Leaflet/Leaflet/issues/6022) and [#6027](https://github.com/Leaflet/Leaflet/issues/6027) by [ghybs](https://github.com/ghybs)) +* Clean up references to global `L` in source code ([#6047](https://github.com/Leaflet/Leaflet/issues/6047) and [#6048](https://github.com/Leaflet/Leaflet/issues/6048) by [ghybs](https://github.com/ghybs)) +* Allow reset of `Canvas` `dashArray` option + support array type ([#6200](https://github.com/Leaflet/Leaflet/issues/6200) by [McBen](https://github.com/McBen)) + +### Bug fixes + +* Respect the `preferCanvas` option in all panes ([#6019](https://github.com/Leaflet/Leaflet/issues/6019) by [mjumbewu](https://github.com/mjumbewu)) +* Do not fire `tileload` event if tile has empty `src` ([#6025](https://github.com/Leaflet/Leaflet/issues/6025) by [cherniavskii](https://github.com/cherniavskii)) +* Fix race condition when removing canvas before it has rendered ([#6033](https://github.com/Leaflet/Leaflet/issues/6033) by [louMoxy](https://github.com/louMoxy)) +* Fix memory leak in canvas renderer ([#6117](https://github.com/Leaflet/Leaflet/issues/6117) by [aj8k](https://github.com/aj8k)) +* Fix dragging for CSS scaled map ([#6055](https://github.com/Leaflet/Leaflet/issues/6055) by [ghybs](https://github.com/ghybs)) +* Handle `Polygon`s with empty array of `LatLng`s ([#6119](https://github.com/Leaflet/Leaflet/issues/6119) by [BakuCity](https://github.com/BakuCity)) +* Fix view bounds calculation in geolocation event handler ([#6140](https://github.com/Leaflet/Leaflet/issues/6140) by [wladich](https://github.com/wladich)) +* Fix error removing map and resizing window at the same time ([#6160](https://github.com/Leaflet/Leaflet/issues/6160) by [danzel](https://github.com/danzel)) +* Stop pan key event when pan animation is in progress ([#6231](https://github.com/Leaflet/Leaflet/issues/6231) by [cherniavskii](https://github.com/cherniavskii)) + +### Docs & Web Site + +* Use more explicit tiles in `Map panes` example ([#6018](https://github.com/Leaflet/Leaflet/issues/6018) by [ghybs](https://github.com/ghybs)) +* Document parameter of `closestLayerPoint` method ([#6060](https://github.com/Leaflet/Leaflet/issues/6060) by [mattdsteele](https://github.com/mattdsteele)) +* Update year ranges ([#6076](https://github.com/Leaflet/Leaflet/issues/6076) by [BakuCity](https://github.com/BakuCity)) +* Use https everywhere for OSM links ([#6082](https://github.com/Leaflet/Leaflet/issues/6082) by [rzoller](https://github.com/rzoller)) +* Fix typo in `VideoOverlay.js` example docs ([#6090](https://github.com/Leaflet/Leaflet/issues/6090) by [zhuang-hao-ming](https://github.com/zhuang-hao-ming)) +* Fix typo in `LatLng` docstring ([#6138](https://github.com/Leaflet/Leaflet/issues/6138) by [jieter](https://github.com/jieter)) +* Use https everywhere and get rid of mixed content warnings ([#6151](https://github.com/Leaflet/Leaflet/issues/6151) by [theel0ja](https://github.com/theel0ja)) +* More accurate `Browser.retina` explanation ([#6203](https://github.com/Leaflet/Leaflet/issues/6203) by [JLuc](https://github.com/JLuc)) +* Use link to official RFC 7946 GeoJSON spec ([#6211](https://github.com/Leaflet/Leaflet/issues/6211) by [ghybs](https://github.com/ghybs)) + +### ES6 / Rollup + +* Add ES module build ([#6021](https://github.com/Leaflet/Leaflet/issues/6021) by [Rich-Harris](https://github.com/Rich-Harris)) + +### Development workflow + +* Move external dependencies to `node_modules` ([#6028](https://github.com/Leaflet/Leaflet/issues/6028) by [cherniavskii](https://github.com/cherniavskii)) +* Remove `jake` dependency and use NPM scripts instead ([#5828](https://github.com/Leaflet/Leaflet/issues/5828) by [cherniavskii](https://github.com/cherniavskii)) +* Update `ssri` dependency to `5.2.2` ([#6086](https://github.com/Leaflet/Leaflet/issues/6086) by [cherniavskii](https://github.com/cherniavskii)) +* Set div width for `getBoundsZoom` parameter `inside` ([#6192](https://github.com/Leaflet/Leaflet/issues/6192) by [ghybs](https://github.com/ghybs)) +* Fix unit tests for graphical browsers ([#6199](https://github.com/Leaflet/Leaflet/issues/6199) and [#6202](https://github.com/Leaflet/Leaflet/issues/6202) by [ghybs](https://github.com/ghybs)) +* Run tests in Firefox graphical browser as part of CI ([#5831](https://github.com/Leaflet/Leaflet/issues/5831) by [cherniavskii](https://github.com/cherniavskii)) + + +## 1.3.1 (2018-01-18) + +### Bug fixes + +* Fix `L.TileLayer`regression, which caused incorrect tile URLs ([#6006](https://github.com/Leaflet/Leaflet/issues/6006) by [ghybs](https://github.com/ghybs)) + + +## 1.3.0 (2018-01-15) + +### API changes + +* Add `tolerance` option to `L.Renderer` instead of hardcoded tolerance for touch devices ([#5922](https://github.com/Leaflet/Leaflet/issues/5922) by [Muscot](https://github.com/Muscot)). + +### Improvements + +* Use more stable form of Haversine formula ([#5935](https://github.com/Leaflet/Leaflet/issues/5935) by [jussimattas](https://github.com/jussimattas)) +* Add `autoPan` option to `L.Marker` ([#5651](https://github.com/Leaflet/Leaflet/issues/5651) by [alenaksu](https://github.com/alenaksu)) +* Cancel http requests for outdated tiles ([#5615](https://github.com/Leaflet/Leaflet/issues/5615) by [jbccollins](https://github.com/jbccollins)) +* Add `closeOnEscapeKey` option to `L.Popup` ([#5730](https://github.com/Leaflet/Leaflet/issues/5730) by [Mickyfen17](https://github.com/Mickyfen17)) +* Add `tileerror` tests to `L.GridLayer` spec ([#5805](https://github.com/Leaflet/Leaflet/issues/5805) by [msiadak](https://github.com/msiadak)) +* Use `eachLayer` method for iterations over layers in `L.LayerGroup` ([#5809](https://github.com/Leaflet/Leaflet/issues/5809) by [cherniavskii](https://github.com/cherniavskii)) +* Change `Util.formatNum` default to 6 decimals ([#5492](https://github.com/Leaflet/Leaflet/issues/5492) by [fminuti](https://github.com/fminuti)) +* Fire `zoomlevelschange` event when calling `setMinZoom` & `setMaxZoom` ([#5230](https://github.com/Leaflet/Leaflet/issues/5230) by [mynameisstephen](https://github.com/mynameisstephen)) +* Use zoom parameter if passed to `L.TileLayer`'s `getTileUrl` method ([#5822](https://github.com/Leaflet/Leaflet/issues/5822) by [broncha](https://github.com/broncha)) +* Round circle radius in renderer instead of layer ([#5859](https://github.com/Leaflet/Leaflet/issues/5859) by [perliedman](https://github.com/perliedman)) +* Make `L.LayerGroup` accept options ([#5792](https://github.com/Leaflet/Leaflet/issues/5792) by [iH8](https://github.com/iH8)) +* Round pan offset towards zero ([#5858](https://github.com/Leaflet/Leaflet/issues/5858) by [perliedman](https://github.com/perliedman)) +* Improve heuristic for what event targets are considered markers ([#5885](https://github.com/Leaflet/Leaflet/issues/5885) by [perliedman](https://github.com/perliedman)) +* Add `typeof` check to `checkDeprecatedMixinEvents` ([#5901](https://github.com/Leaflet/Leaflet/issues/5901) by [murb](https://github.com/murb)) +* Optimize images ([#5936](https://github.com/Leaflet/Leaflet/issues/5936) by [grischard](https://github.com/grischard)) +* Add `addTo` static function to `L.Handler` class ([#5930](https://github.com/Leaflet/Leaflet/issues/5930) by [cherniavskii](https://github.com/cherniavskii)) +* `L.ImageOverlay` accepts `ImageElement` ([#5948](https://github.com/Leaflet/Leaflet/issues/5948) by [ronikar](https://github.com/ronikar)) + +### Bug fixes + +* Fix adding CSS classes in `L.VideoOverlay`, which caused map crash in IE8 ([#5731](https://github.com/Leaflet/Leaflet/issues/5731) by [Dzwiedzminator](https://github.com/Dzwiedzminator) and [#5785](https://github.com/Leaflet/Leaflet/issues/5785) by [cherniavskii](https://github.com/cherniavskii)) +* No inertia if drag is stopped before ending the drag ([#5690](https://github.com/Leaflet/Leaflet/issues/5690) by [perliedman](https://github.com/perliedman)) +* Remove tiles from the `_tiles` cache when they're aborted ([#5634](https://github.com/Leaflet/Leaflet/issues/5634) by [oliverheilig](https://github.com/oliverheilig)) +* Use same condition for adding as well as removing double tap listener ([#5598](https://github.com/Leaflet/Leaflet/issues/5598) by [perliedman](https://github.com/perliedman)) +* Correctly wrap tile coordinate bounds ([#5715](https://github.com/Leaflet/Leaflet/issues/5715) by [perliedman](https://github.com/perliedman)) +* Fix `L.TileLayer` infinite error loop ([#5783](https://github.com/Leaflet/Leaflet/issues/5783) by [cherniavskii](https://github.com/cherniavskii)) +* Fix map not rendering when images have max-height ([#5778](https://github.com/Leaflet/Leaflet/issues/5778) by [idanen](https://github.com/idanen)) +* Add defensive check for `this._map` in `L.Marker`'s `update` method ([#5736](https://github.com/Leaflet/Leaflet/issues/5736) by [dnepromell](https://github.com/dnepromell)) +* Fix zoom when map container is scaled ([#5794](https://github.com/Leaflet/Leaflet/issues/5794) by [cherniavskii](https://github.com/cherniavskii)) +* Update DomPointer.js to revert typo ([#5817](https://github.com/Leaflet/Leaflet/issues/5817) by [daverayment](https://github.com/daverayment)) +* Fix `L.ImageOverlay` `className` option ([#5830](https://github.com/Leaflet/Leaflet/issues/5830) by [cherniavskii](https://github.com/cherniavskii)) +* Fix `L.TileLayer.WMS` when using Polar stereographic ([#5618](https://github.com/Leaflet/Leaflet/issues/5618) by [scaddenp](https://github.com/scaddenp)) +* Stop animation before removing map ([#5876](https://github.com/Leaflet/Leaflet/issues/5876) by [dnepromell](https://github.com/dnepromell) and [#5918](https://github.com/Leaflet/Leaflet/issues/5918) by [aaronplanell](https://github.com/aaronplanell)) +* Stop locate before removing map ([#5893](https://github.com/Leaflet/Leaflet/issues/5893) by [ghybs](https://github.com/ghybs)) +* Reset `GridLayer`'s `_tileZoom` to `undefined` instead of `null` ([#5888](https://github.com/Leaflet/Leaflet/issues/5888) by [iH8](https://github.com/iH8)) +* Fix `L.Map`'s `map.flyTo` method to respect `noMoveStart` option ([#5923](https://github.com/Leaflet/Leaflet/issues/5923) by [iPrytz](https://github.com/iPrytz)) +* Fix map pan when `touchZoom` is disabled ([#5952](https://github.com/Leaflet/Leaflet/issues/5952) by [cherniavskii](https://github.com/cherniavskii)) +* Fix `L.SVG` to reset size on remove from map ([#5966](https://github.com/Leaflet/Leaflet/issues/5966) by [ghybs](https://github.com/ghybs)) +* Fix `L.Marker` to set `alt` attribute for img-based Icons only ([#5979](https://github.com/Leaflet/Leaflet/issues/5979) by [msiadak](https://github.com/msiadak)) + +### Docs & Web Site + +* Add documentation for `PolyLine.closestLayerPoint` ([#5701](https://github.com/Leaflet/Leaflet/issues/5701) by [perliedman](https://github.com/perliedman)) +* Replace urls for samples in wms documentation ([#5712](https://github.com/Leaflet/Leaflet/issues/5712) by [jjimenezshaw](https://github.com/jjimenezshaw)) +* Add `DomEvent.stop` event type to docs ([#5733](https://github.com/Leaflet/Leaflet/issues/5733) by [theashyster](https://github.com/theashyster)) +* Update links to GeoJSON spec in GeoJSON examples ([#5725](https://github.com/Leaflet/Leaflet/issues/5725) by [astridx](https://github.com/astridx)) +* Improve docs for `L.LatLngBounds` `pad` method ([#5748](https://github.com/Leaflet/Leaflet/issues/5748) by [CalvinWilliams1012](https://github.com/CalvinWilliams1012)) +* Improve Zoom-levels documentation to reflect function properly ([#5769](https://github.com/Leaflet/Leaflet/issues/5769) by [CalvinWilliams1012](https://github.com/CalvinWilliams1012)) +* Fix map's height and width in examples to make attributions visible on mobile ([#5772](https://github.com/Leaflet/Leaflet/issues/5772) by [CalvinWilliams1012](https://github.com/CalvinWilliams1012) and [#5819](https://github.com/Leaflet/Leaflet/issues/5819) by [cherniavskii](https://github.com/cherniavskii)) +* Fix `L.FeatureGroup` `bringToBack` method docs ([#5788](https://github.com/Leaflet/Leaflet/issues/5788) by [fpopa](https://github.com/fpopa)) +* Fix `L.LatLng` `distanceTo` method description ([#5791](https://github.com/Leaflet/Leaflet/issues/5791) by [loisgh](https://github.com/loisgh)) +* Fix docs redirects to latest version reference ([#5824](https://github.com/Leaflet/Leaflet/issues/5824) by [cherniavskii](https://github.com/cherniavskii)) +* Add CDN alternatives ([#5837](https://github.com/Leaflet/Leaflet/issues/5837) by [ghybs](https://github.com/ghybs)) +* Update docs for `L.DomEvent.off()` ([#5855](https://github.com/Leaflet/Leaflet/issues/5855) by [77ganesh](https://github.com/77ganesh) and [#5976](https://github.com/Leaflet/Leaflet/issues/5976) by [kring](https://github.com/kring)) +* Move `L.SVG` factory docs to appropriate place ([#5864](https://github.com/Leaflet/Leaflet/issues/5864) by [cherniavskii](https://github.com/cherniavskii)) +* New Leaflet playgrounds on Plunker, Codepen and JSFiddle ([#5868](https://github.com/Leaflet/Leaflet/issues/5868) by [iH8](https://github.com/iH8)) +* Clarify that any option keys can be used ([#5877](https://github.com/Leaflet/Leaflet/issues/5877) by [perliedman](https://github.com/perliedman)) +* Add notes about some classes not inheriting Class ([#5878](https://github.com/Leaflet/Leaflet/issues/5878) by [perliedman](https://github.com/perliedman)) +* Clean up and document event propagation properties ([#5880](https://github.com/Leaflet/Leaflet/issues/5880) by [perliedman](https://github.com/perliedman)) +* Update building instructions ([#5911](https://github.com/Leaflet/Leaflet/issues/5911) by [shadeland](https://github.com/shadeland)) +* Document `mouseup` event for interactive `L.Layer` ([#5941](https://github.com/Leaflet/Leaflet/issues/5941) by [germansokolov13](https://github.com/germansokolov13)) +* Document `L.Icon`'s `tooltipAnchor` option, update `tooltipAnchor` and `popupAnchor` default values docs ([#5989](https://github.com/Leaflet/Leaflet/issues/5989) by [cherniavskii](https://github.com/cherniavskii)) + +### ES6 / Rollup + +* Tweak `legacy` option in rollup config - now Leaflet works in IE again ([#5929](https://github.com/Leaflet/Leaflet/issues/5929) by [IvanSanchez](https://github.com/IvanSanchez)) +* Remove warning alert in watch bundle ([#5714](https://github.com/Leaflet/Leaflet/issues/5714) by [perliedman](https://github.com/perliedman)) +* New rollup config signature ([#5812](https://github.com/Leaflet/Leaflet/issues/5812) by [iH8](https://github.com/iH8)) + + +## 1.2.0 (2017-08-08) + +### API Changes + +* Make `L.LineUtil._flat` public as `L.LineUtil.isFlat` ([#5667](https://github.com/Leaflet/Leaflet/issues/5667) by [yohanboniface](https://github.com/yohanboniface)) +* `L.ImageOverlay`'s `setBounds` method accepts an array of points, not only a `L.LatLngBounds` instance ([#5687](https://github.com/Leaflet/Leaflet/pull/5687) by [ronikar](https://github.com/ronikar) + +### Improvements + +* `VideoOverlay` accepts `VideoElement` ([#5661](https://github.com/Leaflet/Leaflet/issues/5661) by [eavidan-0](https://github.com/eavidan-0)) +* Documentation improvements by [ghybs](https://github.com/ghybs), [thachhoang](https://github.com/thachhoang), [colbin8r](https://github.com/colbin8r), [Timmmm](https://github.com/Timmmm), [cyrilf](https://github.com/cyrilf) and [JonDum](https://github.com/JonDum) +* Filter published files on npm ([#5626](https://github.com/Leaflet/Leaflet/issues/5626) by [TrySound](https://github.com/TrySound)), [e7o-de](https://github.com/e7o-de) +* Throw an error if trying to use `addLayer` with something that is not a `Layer` ([#5689](https://github.com/Leaflet/Leaflet/pull/5689) by [perliedman](https://github.com/perliedman)) +* Ensure copyright banner is kept in the minified `leaflet.js` ([#5682](https://github.com/Leaflet/Leaflet/pull/5682) by [jgravois](https://github.com/jgravois)) + +### Bug fixes + +* Fix non-extendable objects regression of 1.1.0 ([#5658](https://github.com/Leaflet/Leaflet/pull/5658) by [mourner](https://github.com/mourner)) +* `Control.Layers` properly handles adding the same layer multiple times, as well as cleanup ([#5672](https://github.com/Leaflet/Leaflet/issues/5672), [#5684](https://github.com/Leaflet/Leaflet/issues/5684) and [#5673](https://github.com/Leaflet/Leaflet/issues/5673) by [jjimenezshaw](https://github.com/jjimenezshaw)) +* Make `L.Draggable._dragging` public again ([#5659](https://github.com/Leaflet/Leaflet/issues/5659) by [yohanboniface](https://github.com/yohanboniface)) +* `DomEvent.off` returns `this` ([#5601](https://github.com/Leaflet/Leaflet/issues/5601) by [jelhan](https://github.com/jelhan)) +* Don't use functions from the global `L` internally ([#5596](https://github.com/Leaflet/Leaflet/issues/5596) by [atd-schubert](https://github.com/atd-schubert)) +* Return `this` instead of `addOne` in `DomEvent.disableScrollPropagation` ([#5595](https://github.com/Leaflet/Leaflet/issues/5595) by [Eschon](https://github.com/Eschon)) + + +## 1.1.0 (2017-06-27) + +### API changes + +* Add deprecation notice for `L.Mixin.Events`, fixes [#5358](https://github.com/Leaflet/Leaflet/issues/5358) ([#5365](https://github.com/Leaflet/Leaflet/issues/5365)) (by [perliedman](https://github.com/perliedman)) +* Turn `nonBubblingEvents` into a documented boolean option ([#4883](https://github.com/Leaflet/Leaflet/issues/4883) by [IvanSanchez](https://github.com/IvanSanchez)) +* Add `L.transformation` factory, allow creation from array ([#5282](https://github.com/Leaflet/Leaflet/issues/5282) by [anetz89](https://github.com/anetz89)) +* `toGeoJSON` methods now default to a precision of six decimals (as recommended in the [GeoJSON spec](https://tools.ietf.org/html/rfc7946#section-11.2)), precision is settable through a method parameter ([#5544](https://github.com/Leaflet/Leaflet/pull/5544) by [mattgrande](https://github.com/mattgrande)) + +### Docs & Web Site + +* `reference.html` now always points to latest stable docs ([#5490](https://github.com/Leaflet/Leaflet/issues/5490) by [IvanSanchez](https://github.com/IvanSanchez), [#5493](https://github.com/Leaflet/Leaflet/issues/5493) by [alyhegazy](https://github.com/alyhegazy)) +* Subresource integrity information and scripts ([#5468](https://github.com/Leaflet/Leaflet/issues/5468) by [IvanSanchez](https://github.com/IvanSanchez)) +* New tutorial on zooming (by [IvanSanchez](https://github.com/IvanSanchez), [#5007](https://github.com/Leaflet/Leaflet/issues/5007)) +* Minor documentation improvements by [perliedman](https://github.com/perliedman), [veltman](https://github.com/veltman), [FDMS](https://github.com/FDMS), [ghybs](https://github.com/ghybs), [RichardLitt](https://github.com/RichardLitt), [gatsbimantico](https://github.com/gatsbimantico), [daturkel](https://github.com/daturkel), [jgravois](https://github.com/jgravois), [geografa](https://github.com/geografa), [BjoernSchilberg](https://github.com/BjoernSchilberg), [IvanSanchez](https://github.com/IvanSanchez), [bozdoz](https://github.com/bozdoz), [zemadz](https://github.com/zemadz), [danzel](https://github.com/danzel), [jieter](https://github.com/jieter), [massic80](https://github.com/massic80), [jjimenezshaw](https://github.com/jjimenezshaw), [hnrchrdl](https://github.com/hnrchrdl) and [RayBB](https://github.com/RayBB) + +### ES6 / Rollup + +* ES6 modules & Rollup ([#4989](https://github.com/Leaflet/Leaflet/issues/4989)) (by [mourner](https://github.com/mourner) and [IvanSanchez](https://github.com/IvanSanchez)) +* Additional fixes, testing and cleanup of ES6 code by [thachhoang](https://github.com/thachhoang), [danzel](https://github.com/danzel), [jkuebart](https://github.com/jkuebart), [simon04](https://github.com/simon04), [perliedman](https://github.com/perliedman), [luiscamachopt](https://github.com/luiscamachopt) and [Trufi](https://github.com/Trufi) ([#5373](https://github.com/Leaflet/Leaflet/issues/5373), [#5417](https://github.com/Leaflet/Leaflet/issues/5417), [#5351](https://github.com/Leaflet/Leaflet/issues/5351), [#5330](https://github.com/Leaflet/Leaflet/issues/5330), [#5329](https://github.com/Leaflet/Leaflet/issues/5329), [#5489](https://github.com/Leaflet/Leaflet/issues/5489), [#5504](https://github.com/Leaflet/Leaflet/issues/5504), [#5456](https://github.com/Leaflet/Leaflet/issues/5456), [#5463](https://github.com/Leaflet/Leaflet/issues/5463)) + +### Improvements + +* Add new class `L.VideoOverlay` ([#4988](https://github.com/Leaflet/Leaflet/issues/4988) by [IvanSanchez](https://github.com/IvanSanchez)) +* Added z-index support to ImageOverlay ([#5418](https://github.com/Leaflet/Leaflet/issues/5418) by [Saulzi](https://github.com/Saulzi)) +* Added error event to `ImageOverlay` layer and added tests for the new ([#5416](https://github.com/Leaflet/Leaflet/issues/5416) by [Saulzi](https://github.com/Saulzi)) +* Add `className` option for `ImageOverlay` ([#5555](https://github.com/Leaflet/Leaflet/issues/5555) by [perliedman](https://github.com/perliedman)) + +### Bug fixes + +* Handle edge case of empty bounds on `_getBoundsCenterZoom` ([#5157](https://github.com/Leaflet/Leaflet/issues/5157) by [IvanSanchez](https://github.com/IvanSanchez)) +* Add new methods to `L.Bounds` for 2 missing corners, fixes [#5475](https://github.com/Leaflet/Leaflet/issues/5475) ([#5488](https://github.com/Leaflet/Leaflet/issues/5488) by [ghybs](https://github.com/ghybs)) +* Handle `Polyline`s with empty array of `LatLng`s, [#5497](https://github.com/Leaflet/Leaflet/issues/5497) ([#5498](https://github.com/Leaflet/Leaflet/issues/5498), by [perliedman](https://github.com/perliedman)) +* Take `devicePixelRatio` into account for scrollwheel zoom in win10+chrome ([#5480](https://github.com/Leaflet/Leaflet/issues/5480)) (by [IvanSanchez](https://github.com/IvanSanchez)) +* Add hook points to allow for a proper NoGap plugin ([#5476](https://github.com/Leaflet/Leaflet/issues/5476)) (by [IvanSanchez](https://github.com/IvanSanchez)) +* Sanity check to prevent loading tiles when bounds are `Infinity` ([#5478](https://github.com/Leaflet/Leaflet/issues/5478), [#5479](https://github.com/Leaflet/Leaflet/issues/5479) by [IvanSanchez](https://github.com/IvanSanchez)) +* Fix box zoom race condition ([#5452](https://github.com/Leaflet/Leaflet/issues/5452) by [ppaskaris](https://github.com/ppaskaris)) +* On update set current tiles active to avoid pruning ([#5381](https://github.com/Leaflet/Leaflet/issues/5381)) ([#5431](https://github.com/Leaflet/Leaflet/issues/5431) by [oliverheilig](https://github.com/oliverheilig)) +* Make `L.Mixin.Events` a simple object instead of a prototype so it doesn't have a 'constructor' property, fixes [#5451](https://github.com/Leaflet/Leaflet/issues/5451) ([#5453](https://github.com/Leaflet/Leaflet/issues/5453) by [luiscamachopt](https://github.com/luiscamachopt)) +* Canvas: call `ctx.setLineDash` in `_fillStroke` [#5182](https://github.com/Leaflet/Leaflet/issues/5182) ([#5454](https://github.com/Leaflet/Leaflet/issues/5454) by [TeXitoi](https://github.com/TeXitoi)) +* Only rearrange DOM in `toFront`/`toBack` if needed, fixes [#4050](https://github.com/Leaflet/Leaflet/issues/4050) ([#5465](https://github.com/Leaflet/Leaflet/issues/5465) by [perliedman](https://github.com/perliedman)) +* Push back keyboard navigation order of `L.Popup`'s close button ([#5461](https://github.com/Leaflet/Leaflet/issues/5461) by [Mirodil](https://github.com/Mirodil)) +* Remove spurious check in `DomUtil.preventOutline` ([#5435](https://github.com/Leaflet/Leaflet/issues/5435) by [qjas](https://github.com/qjas)) +* Error handler in `ImageOverlay` for 404 links ([#5307](https://github.com/Leaflet/Leaflet/issues/5307)) by [APwhitehat](https://github.com/APwhitehat)) +* Ensure renderer's container is initialized when a path is added to map ([#5404](https://github.com/Leaflet/Leaflet/issues/5404) by [IvanSanchez](https://github.com/IvanSanchez)) +* Layers Control only add layer events to layers when we are on the map. Fixes [#5421](https://github.com/Leaflet/Leaflet/issues/5421) ([#5422](https://github.com/Leaflet/Leaflet/issues/5422) by [danzel](https://github.com/danzel)) +* Layers Control can now become scrollable even if `collapsed: false`, fixes [#5328](https://github.com/Leaflet/Leaflet/issues/5328) ([#5348](https://github.com/Leaflet/Leaflet/issues/5348) by [ghybs](https://github.com/ghybs)) +* Stop map on drag start instead of pointer down, fixes [#5350](https://github.com/Leaflet/Leaflet/issues/5350) ([#5378](https://github.com/Leaflet/Leaflet/issues/5378) by [perliedman](https://github.com/perliedman)) +* fix invalid GeoJSON produced by nested `LayerGroups` ([#5359](https://github.com/Leaflet/Leaflet/issues/5359) by [Resonance1584](https://github.com/Resonance1584)) +* Update toolbar inner border radius ([#5361](https://github.com/Leaflet/Leaflet/issues/5361) by [newmanw](https://github.com/newmanw)) +* Export `lastId` in `Util` ([#5349](https://github.com/Leaflet/Leaflet/issues/5349) by [DenisCarriere](https://github.com/DenisCarriere)) +* Do not stop keypress on escape if no popup is open, plus unit tests ([#5331](https://github.com/Leaflet/Leaflet/issues/5331) (by [IvanSanchez](https://github.com/IvanSanchez)) +* Docs: remove `iframe` borders on examples ([#5327](https://github.com/Leaflet/Leaflet/issues/5327)) (by [tariqksoliman](https://github.com/tariqksoliman)) +* Pull `min`/`maxNativeZoom` from `TileLayer` into `GridLayer`, as per [#5316](https://github.com/Leaflet/Leaflet/issues/5316). ([#5319](https://github.com/Leaflet/Leaflet/issues/5319) by [jkuebart](https://github.com/jkuebart)) +* Disable click propagation on zoom control buttons, fixes [#5308](https://github.com/Leaflet/Leaflet/issues/5308) ([#5318](https://github.com/Leaflet/Leaflet/issues/5318) by [perliedman](https://github.com/perliedman)) +* Add CSS for `-webkit-tap-highlight-color`, fixes [#5302](https://github.com/Leaflet/Leaflet/issues/5302) ([#5303](https://github.com/Leaflet/Leaflet/issues/5303) by [IvanSanchez](https://github.com/IvanSanchez)) +* Removed type attribute in HTML5 files ([#5309](https://github.com/Leaflet/Leaflet/issues/5309) by [uzerus](https://github.com/uzerus)) +* Add margin to `LatLngBounds.equals` method ([#5071](https://github.com/Leaflet/Leaflet/issues/5071) by [miguelcobain](https://github.com/miguelcobain)) +* Add `L.Draggable` options and fix docstring ([#5301](https://github.com/Leaflet/Leaflet/issues/5301) by [IvanSanchez](https://github.com/IvanSanchez)) +* Fix max/min calculation for `getBoundsZoom`, fixes [#5136](https://github.com/Leaflet/Leaflet/issues/5136) ([#5137](https://github.com/Leaflet/Leaflet/issues/5137) by [IvanSanchez](https://github.com/IvanSanchez)) +* Scrubbing of detached DOM elements, prevents memory leaks; fixes [#5263](https://github.com/Leaflet/Leaflet/issues/5263) ([#5265](https://github.com/Leaflet/Leaflet/issues/5265) by [IvanSanchez](https://github.com/IvanSanchez)) +* Remove `marker.dragging` when not on the map, fixes [#5293](https://github.com/Leaflet/Leaflet/issues/5293) ([#5295](https://github.com/Leaflet/Leaflet/issues/5295) by [danzel](https://github.com/danzel)) +* Stop scroll propagation in `L.Layers.Control` in chrome>55 ([#5280](https://github.com/Leaflet/Leaflet/issues/5280) by [IvanSanchez](https://github.com/IvanSanchez)) +* Allow HTML inputs in layer control's labels, fixes [#5116](https://github.com/Leaflet/Leaflet/issues/5116) ([#51165544](https://github.com/Leaflet/Leaflet/issues/5544) by [iZucken](https://github.com/iZucken)) +* Fix possible null reference when auto detecting icon default path, fixes [#5534](https://github.com/Leaflet/Leaflet/issues/5534) ([#5535](https://github.com/Leaflet/Leaflet/issues/5535) by [williamscs](https://github.com/williamscs)) +* Don't turn enter keypress into map clicks, fixes [#5499](https://github.com/Leaflet/Leaflet/issues/5499) ([#5507](https://github.com/Leaflet/Leaflet/issues/5507) by [perliedman](https://github.com/perliedman)) +* Use minus character instead of hyphen in the zoom control ([#5501](https://github.com/Leaflet/Leaflet/issues/5501) by [damianmoore](https://github.com/damianmoore)) + +## 1.0.3 (2017-01-23) + +### Bug fixes + +* Avoid extra `L.Canvas` redraws on several scenarios (by [@perliedman](https://github.com/perliedman), [#5250](https://github.com/Leaflet/Leaflet/pull/5034), also thanks to [@manubb](https://github.com/manubb) for investigation and PR). +* Fix behaviour of `dblclick` events in [Chrome 55 due to `PointerEvent`s](https://developers.google.com/web/updates/2016/11/nic55#pointer-events) (by [@IvanSanchez](https://github.com/IvanSanchez), [#5185](https://github.com/Leaflet/Leaflet/pull/5185), [#5248](https://github.com/Leaflet/Leaflet/pull/5248), [#5268](https://github.com/Leaflet/Leaflet/pull/5268)). +* Fix a dangling comma making IE8 fail to parse the code (by [@batje](https://github.com/batje), [#5270](https://github.com/Leaflet/Leaflet/pull/5270)). +* Backport event handling fixes from [#5054](https://github.com/Leaflet/Leaflet/pull/5054) into `L.SVG.VML` for IE8 (by [@IvanSanchez](https://github.com/IvanSanchez), [#5215](https://github.com/Leaflet/Leaflet/pull/5215)). +* Fix a race condition when closing popups during their `popupopen` event (by [@hagai26](https://github.com/hagai26), [#5202](https://github.com/Leaflet/Leaflet/pull/5202)). +* Fix `getBoundsZoom` return value on CRSs with a flipped axis (by [@computerlove](https://github.com/computerlove), [#5204](https://github.com/Leaflet/Leaflet/pull/5204)). +* Avoid infinite loops when the `errorTileUrl` of a `L.TileLayer` returns 404 (by [@IvanSanchez](https://github.com/IvanSanchez), [#5177](https://github.com/Leaflet/Leaflet/pull/5177)). +* Remove erroneous initialization of unused event listeners (by [@Brikky](https://github.com/Brikky), [#5160](https://github.com/Leaflet/Leaflet/pull/5160)). +* Fix rounding of `L.Canvas` redraw areas to avoid artifacts during partial updates (by [@Ernie23](https://github.com/Ernie23), [#5148](https://github.com/Leaflet/Leaflet/pull/5148)). +* Fix `isPopupOpen()` behaviour of `L.Layer` when no popup is bound to a layer (by [@gvangool](https://github.com/gvangool), [#5106](https://github.com/Leaflet/Leaflet/pull/5106)). +* Add a sanity check in `LatLngBounds.contains()` to allow for non-instantiated `LatLng` objects (by [@IvanSanchez](https://github.com/IvanSanchez), [#5135](https://github.com/Leaflet/Leaflet/pull/5135)). +* Fix collapsing of `L.Control.Layers` when the `collapse` option is `false` (by [@perliedman](https://github.com/perliedman), [#5131](https://github.com/Leaflet/Leaflet/pull/5131)). + +### API changes + +* Added a new `WrapLatLngBounds` method to `L.CRS`, to fix an issue with `maxBounds` of `GridLayer`s (by [@IvanSanchez](https://github.com/IvanSanchez), [#5185](https://github.com/Leaflet/Leaflet/pull/5185), also thanks to [@DiogoMCampos](https://github.com/DiogoMCampos) for investigation). +* `L.Map.getSize()` will now return `0` instead of `NaN` in non-graphical environments (by [@ughitsaaron](https://github.com/ughitsaaron), [#5209](https://github.com/Leaflet/Leaflet/pull/5209)). + +### Improvements + +* Several minor documentation improvements by [@IvanSanchez](https://github.com/IvanSanchez), [@jieter](https://github.com/jieter), [@alonsogarciapablo](https://github.com/alonsogarciapablo), [@jasonoverland](https://github.com/jasonoverland), [@danzel](https://github.com/danzel), [@ghybs](https://github.com/ghybs), [@Ralf8686](https://github.com/Ralf8686), [@geoloep](https://github.com/geoloep) +* Add an `alt` attribute to the ``s of marker shadows (by [@topicus](https://github.com/topicus), [#5259](https://github.com/Leaflet/Leaflet/pull/5259)). + +## 1.0.2 (2016-11-21) + +### Bug fixes + +* Fix CSS for marker shadows when `max-width` is already set (by [@brunob](https://github.com/brunob), [#5046](https://github.com/Leaflet/Leaflet/pull/5046)). +* Fix canvas redraw when style updates fill and/or weight (by [@perliedman](https://github.com/perliedman), [#5034](https://github.com/Leaflet/Leaflet/pull/5034)). +* Prevent canvas from firing multiple `mouseover` events for same layer (by [@perliedman](https://github.com/perliedman), [#5033](https://github.com/Leaflet/Leaflet/pull/5033)). +* Fixed a race condition when removing and adding `L.Canvas` vectors during a zoom animation (by [@ghybs](https://github.com/ghybs)) [#5011](https://github.com/Leaflet/Leaflet/pull/5011). +* Fix zoom animation of ImageOverlay when CRS's Y axis is flipped (by [@perliedman](https://github.com/perliedman)), [#4993](https://github.com/Leaflet/Leaflet/pull/4993). +* Fix encoding/decoding of GeoJSON `FeatureCollection`s (by [@IvanSanchez](https://github.com/IvanSanchez)), [#5045](https://github.com/Leaflet/Leaflet/issues/5045). +* Fix `minZoom`/`maxZoom` late inizialization (by [@IvanSanchez](https://github.com/IvanSanchez)), [#4916](https://github.com/Leaflet/Leaflet/pull/4916). +* Fix styling of custom SVG markers by making stricter CSS selectors (by [@jwoyame](https://github.com/jwoyame)) [#4597](https://github.com/Leaflet/Leaflet/pull/4597). +* Fix order of `mouseover`/`mouseout` events on overlapping `L.Canvas` layers (by [@perliedman](https://github.com/perliedman)), [#5090](https://github.com/Leaflet/Leaflet/pull/5090). +* Fix drag behaviour when a draggable marker is removed in mid-drag (by [@IvanSanchez](https://github.com/IvanSanchez), [#5063](https://github.com/Leaflet/Leaflet/pull/5063). +* Fix `L.Control.Layers.collapse()` on initially uncollapsed layer controls (by [@perliedman](https://github.com/perliedman)), [#5131](https://github.com/Leaflet/Leaflet/pull/5131). +* Fix blurriness of `L.Tooltip` by rounding up pixel coordinates (by [@ashmigelski](https://github.com/ashmigelski)), [#5089](https://github.com/Leaflet/Leaflet/pull/5089). +* Fix click events on overlapping geometries when using `L.Canvas` (by [@perliedman](https://github.com/perliedman)), [#5100](https://github.com/Leaflet/Leaflet/pull/5100). + +### API changes + +* Add a `sortLayers` option to `L.Control.Layers` (by [@IvanSanchez](https://github.com/IvanSanchez), [#4711](https://github.com/Leaflet/Leaflet/pull/4711). +* Implement `bringToFront` and `bringToBack` when using `L.Canvas`, plus preventing other canvas glitches (by [@perliedman](https://github.com/perliedman)), [#5115](https://github.com/Leaflet/Leaflet/pull/5115). +* Add `minNativeZoom` option to `L.TileLayer`s. (by [@bb-juliogarcia](https://github.com/bb-juliogarcia)), [#5088](https://github.com/Leaflet/Leaflet/pull/5088). + +### Improvements + +* Improve performance when adding lots of `L.Path`s by refactoring away event logic (by [@IvanSanchez](https://github.com/IvanSanchez)) [#5054](https://github.com/Leaflet/Leaflet/pull/5054))]. +* Several minor documentation improvements by [@Jmuccigr](https://github.com/Jmuccigr), [@serdarkacka](https://github.com/serdarkacka), [@erickzhao](https://github.com/erickzhao), [@IvanSanchez](https://github.com/IvanSanchez), [@perliedman](https://github.com/perliedman), [@joukewitteveen](https://github.com/joukewitteveen). +* Code reorganization: Extensions for `L.Marker` and `L.Map` no longer have a separate file (by [@mourner](https://github.com/mourner)). +* Removed a duplicated unit test ([@yohanboniface](https://github.com/yohanboniface)). +* Accesibility improvements (ARIA/screenreader related) on map tiles (by [@patrickarlt](https://github.com/patrickarlt)) [#5092](https://github.com/Leaflet/Leaflet/pull/5092). + +## 1.0.1 (2016-09-30) + +### Bug fixes + +* Fixed vector rendering regression in IE8 (by [@perliedman](https://github.com/perliedman)) [#4656](https://github.com/Leaflet/Leaflet/pull/4956). +* Fixed Webpack error when bundling Leaflet's CSS (by [@jefbarn](https://github.com/jefbarn)) [#4679](https://github.com/Leaflet/Leaflet/pull/4979). + +## 1.0.0 (2016-09-26) + +### API changes + +* Remove deprecated `zoomanimated` option for `L.Popup`s (by [@fnicollet](https://github.com/fnicollet)) [#4699](https://github.com/Leaflet/Leaflet/pull/4699) + +### Improvements + +* Several minor fixes to the documentation (by [@IvanSanchez](https://github.com/IvanSanchez), [@alejo90](https://github.com/alejo90), [@ghybs](https://github.com/ghybs), [@JonasDralle](https://github.com/JonasDralle)) +* Add license to `bower.json` (by [@anotherredward](https://github.com/anotherredward)) [#4865](https://github.com/Leaflet/Leaflet/pull/4865) +* Allow creating tooltips without a source layer (by [@yohanboniface](https://github.com/yohanboniface)) [#4836](https://github.com/Leaflet/Leaflet/pull/4836) +* Detect `L.Icon` default path using CSS (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4605](https://github.com/Leaflet/Leaflet/pull/4605) + +### Bug fixes + +* Fix handling of `getScaleZoom` in some custom CRSs (by [@theashyster](https://github.com/theashyster)) [#4919](https://github.com/Leaflet/Leaflet/pull/4919) +* Guard `L.Path` event handlers against race conditions (by [@perliedman](https://github.com/perliedman) and [@IvanSanchez](https://github.com/IvanSanchez)) [#4855](https://github.com/Leaflet/Leaflet/pull/4855) [#4929](https://github.com/Leaflet/Leaflet/pull/4929) [#4838](https://github.com/Leaflet/Leaflet/pull/4838) +* In `L.GridLayer`s, wrap `tileBounds` when `noWrap` is false (by [@fyeah](https://github.com/fyeah)) [#4908](https://github.com/Leaflet/Leaflet/pull/4908) +* Fix `L.Path`'s `bringToFront()` behaviour in the Edge browser (by [@nikolai-b](https://github.com/nikolai-b)) [#4848](https://github.com/Leaflet/Leaflet/pull/4848) +* Remove spurious counting of event handlers (by [@perliedman](https://github.com/perliedman)) [#4842](https://github.com/Leaflet/Leaflet/pull/4842) +* Throw error on `getCenter()` when a `L.Polygon` has no map and thus no CRS (by [@snkashis](https://github.com/snkashis)) [#4820](https://github.com/Leaflet/Leaflet/pull/4820) +* Add a `_leaflet_id` to map containers to prevent error when removing a map twice (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4810](https://github.com/Leaflet/Leaflet/pull/4810) +* Do not fail when closing a tooltip which is not in a map (by [@yohanboniface](https://github.com/yohanboniface)) [#4937](https://github.com/Leaflet/Leaflet/pull/4937) + + +## 1.0-rc3 (2016-08-05) + +### API changes +- `L.Tooltip` `offset` option now defaults to `[0, 0]` (by [@yohanboniface](https://github.com/yohanboniface)) [#4773](https://github.com/Leaflet/Leaflet/pull/4773) +- Event listeners are now always called in the order they have been registered, while until rc2 listeners with a context were all called before listeners without context (even if registered later), and the listeners with context were called in an unpredictable order (by [@yohanboniface](https://github.com/yohanboniface)) [#4769](https://github.com/Leaflet/Leaflet/pull/4769) + +### Improvements +- Added `oldLatLng` in `L.Marker` `drag` event (by [@snkashis](https://github.com/snkashis)) [#4752](https://github.com/Leaflet/Leaflet/pull/4752) + +### Bug fixes +- Fixed regression where event listeners where not always fired in the order of registration (by [@yohanboniface](https://github.com/yohanboniface)) [#4769](https://github.com/Leaflet/Leaflet/pull/4769) +- Fixed `L.Tooltip` zoom animation (by [@yohanboniface](https://github.com/yohanboniface)) [#4744](https://github.com/Leaflet/Leaflet/pull/4744) +- Fixed `layer.bindTooltip` crashing when called before adding the layer to the map (by [@yohanboniface](https://github.com/yohanboniface)) [#4779](https://github.com/Leaflet/Leaflet/pull/4779) +- Fixed regression in `L.Popup` autopaning (by [@yohanboniface](https://github.com/yohanboniface)) [#4768](https://github.com/Leaflet/Leaflet/pull/4768) +- Fixed non permanent `L.Tooltip` not being closed on touch when touching the map (by [@yohanboniface](https://github.com/yohanboniface)) [#4767](https://github.com/Leaflet/Leaflet/pull/4767) +- Fixed `popupopen` and `popupclose` not being fired when clicking on path with an open popup (by [@yohanboniface](https://github.com/yohanboniface)) [#4788](https://github.com/Leaflet/Leaflet/pull/4788) + + +## 1.0-rc2 (2016-07-18) + +### API changes +* Make `L.Handler.enable`/`disable` return `this` (by [@yohanboniface](https://github.com/yohanboniface)) [#4708](https://github.com/Leaflet/Leaflet/pull/4708) +* Icon `size` option can now be initialised with a number (by [@rheh](https://github.com/rheh)) [#4608](https://github.com/Leaflet/Leaflet/pull/4608) +* Add `classname` option to `L.GridLayer` (by [@jayvarner](https://github.com/jayvarner)) [#4553](https://github.com/Leaflet/Leaflet/pull/4553) +* Consistent returns for `Map.addLayer` (by [@nathancahill](https://github.com/nathancahill)) [#4504](https://github.com/Leaflet/Leaflet/pull/4504) +* Create points from objects with `x` and `y` properties (by [@nathancahill](https://github.com/nathancahill)) [#4465](https://github.com/Leaflet/Leaflet/pull/4465) +* Add `updateWhenZooming` option to `L.GridLayer` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4462](https://github.com/Leaflet/Leaflet/pull/4462) + +### Improvements +* Refactoring of events (by [@fab1an](https://github.com/fab1an) and [@perliedman](https://github.com/perliedman)) [#4697](https://github.com/Leaflet/Leaflet/pull/4697) +* Do not alter `popup.options.offset` when computing popup offset (fix #4645) (by [@yohanboniface](https://github.com/yohanboniface)) [#4662](https://github.com/Leaflet/Leaflet/pull/4662) +* Use different `L.Bounds` for "marking as prunable" and loading tiles (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4650](https://github.com/Leaflet/Leaflet/pull/4650) +* Added `L.Tooltip` class to display small tooltips on the map (by [@yohanboniface](https://github.com/yohanboniface)) [#3952](https://github.com/Leaflet/Leaflet/pull/3952) + +### Bug fixes +* Fixed `GridLayer`'s outer edge snapping to vertical center of map (fix #4702) (by [@yohanboniface](https://github.com/yohanboniface)) [#4704](https://github.com/Leaflet/Leaflet/pull/4704) +* Fixed scrollwheel zoom too fast in MS Edge (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4694](https://github.com/Leaflet/Leaflet/pull/4694) +* Use `pointer-events: visiblePainted` as fallback for IE <11 (by [@perliedman](https://github.com/perliedman)) [#4690](https://github.com/Leaflet/Leaflet/pull/4690) +* Avoid double borders on `abbr` in website (by [@brunob](https://github.com/brunob)) [#4663](https://github.com/Leaflet/Leaflet/pull/4663) +* Prevent firing map click when layer has popup (by [@jwoyame](https://github.com/jwoyame)) [#4603](https://github.com/Leaflet/Leaflet/pull/4603) +* Disable pointer events on popup tip (by [@jwoyame](https://github.com/jwoyame)) [#4599](https://github.com/Leaflet/Leaflet/pull/4599) +* Prevent `L.DomUtil.create()` from automatically setting a CSS class name (by [@MuellerMatthew](https://github.com/MuellerMatthew)) [#4563](https://github.com/Leaflet/Leaflet/pull/4563) +* Fix off-by-one bug in `Control.Layers._getLayer` (by [@ValentinH](https://github.com/ValentinH)) [#4561](https://github.com/Leaflet/Leaflet/pull/4561) +* Fix scrollwheel events zomming two levelz in Chrome by scaling down `getWheelDelta()` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4538](https://github.com/Leaflet/Leaflet/pull/4538) +* Prevent event listeners from being called when all listeners are removed (by [@perliedman](https://github.com/perliedman)) [#4555](https://github.com/Leaflet/Leaflet/pull/4555) +* Don't prevent browser's touch scroll and/or zoom unless handlers are enabled (by [@perliedman](https://github.com/perliedman)) [#4552](https://github.com/Leaflet/Leaflet/pull/4552) +* Fixed `getBoundsZoom` with small size and padding (by [@dianjin](https://github.com/dianjin)) [#4532](https://github.com/Leaflet/Leaflet/pull/4532) +* Fixed `L.Control.Layers` in IE8 (by [@jieter](https://github.com/jieter)) [#4509](https://github.com/Leaflet/Leaflet/pull/4509) +* Fixed `TileLayer`'s retina logic when `zoomReverse` is enabled. (by [@perliedman](https://github.com/perliedman)) [#4503](https://github.com/Leaflet/Leaflet/pull/4503) +* Fixed `setMaxBounds` not resetting `maxBounds` when passing `null` argument (by [@yohanboniface](https://github.com/yohanboniface)) [#4494](https://github.com/Leaflet/Leaflet/pull/4494) +* Fixed canvas not filtering click event after drag (by [@yohanboniface](https://github.com/yohanboniface)) [#4493](https://github.com/Leaflet/Leaflet/pull/4493) +* Fixed `L.Control.removeLayer()` raising an error when trying to remove a layer not yet added (by [@jieter](https://github.com/jieter)) [#4487](https://github.com/Leaflet/Leaflet/pull/4487) +* Fixed disabling drag on click in IE11 (by [@perliedman](https://github.com/perliedman)) [#4479](https://github.com/Leaflet/Leaflet/pull/4479) +* Fixed `L.Evented.listens()` on removed event handlers, #4474 (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4476](https://github.com/Leaflet/Leaflet/pull/4476) +* Better handling of `markerZoomAnimation` event hooks (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4460](https://github.com/Leaflet/Leaflet/pull/4460) + + +## 1.0-rc1 (2016-04-18) + +### API changes +* Make `L.Control.Layers.collapse`/`expand` public methods (by [@yohanboniface](https://github.com/yohanboniface)) [#4370](https://github.com/Leaflet/Leaflet/pull/4370) +* Make `L.latLngBounds` factory return an empty bounds with no argument (by [@yohanboniface](https://github.com/yohanboniface)) [#4368](https://github.com/Leaflet/Leaflet/pull/4368) +* `Map.fitBounds` now raises an error if bounds are not valid (by [@theotow](https://github.com/theotow)) [#4353](https://github.com/Leaflet/Leaflet/pull/4353) +* Temporarily support legacy options on `L.Circle` (by [@JrFolk](https://github.com/JrFolk)) [#4290](https://github.com/Leaflet/Leaflet/pull/4290) +* Throw error on `NaN` circle radius (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4237](https://github.com/Leaflet/Leaflet/pull/4237) +* `L.Class.include()` & `mergeOptions()` now return `this` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4246](https://github.com/Leaflet/Leaflet/pull/4246) +* Consistent GeoJSON casing (by [@yohanboniface](https://github.com/yohanboniface)) [#4108](https://github.com/Leaflet/Leaflet/pull/4108) +* Move `L.LatLng.equals` to `L.CRS.equals`. (by [@perliedman](https://github.com/perliedman)) [#4074](https://github.com/Leaflet/Leaflet/pull/4074) +* Make non-interactive markers not firing pointer events (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3937](https://github.com/Leaflet/Leaflet/pull/3937) + + +### Improvements +* Give popups an id (by [@tylercubell](https://github.com/tylercubell)) [#4355](https://github.com/Leaflet/Leaflet/pull/4355) +* Support `{-y}` in tile layer urls (by [@jieter](https://github.com/jieter)) [#4337](https://github.com/Leaflet/Leaflet/pull/4337) +* Support `dashArray` path option in canvas (by [@gommo](https://github.com/gommo)) [#4173](https://github.com/Leaflet/Leaflet/pull/4173) +* Clean up `navigator.pointerEnabled` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4287](https://github.com/Leaflet/Leaflet/pull/4287) +* Use array in `L.Control.Layers` internally (by [@jieter](https://github.com/jieter)) [#4227](https://github.com/Leaflet/Leaflet/pull/4227) +* Implement `L.Browser.edge` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4143](https://github.com/Leaflet/Leaflet/pull/4143) +* Optimized icons (by [@vtduncan](https://github.com/vtduncan)) [#4124](https://github.com/Leaflet/Leaflet/pull/4124) +* Cast `L.DivIcon.bgPos` option to `L.Point` (by [@perliedman](https://github.com/perliedman)) [#4090](https://github.com/Leaflet/Leaflet/pull/4090) +* Switch to wheel event where available (by [@mourner](https://github.com/mourner)) [#3653](https://github.com/Leaflet/Leaflet/pull/3653) +* Fractional zoom controls (by [@IvanSanchez](https://github.com/IvanSanchez) and [@hyperknot](https://github.com/hyperknot)) [#3523](https://github.com/Leaflet/Leaflet/pull/3523) +* Added click tolerance also for non-touch devices (by [DavidUv](https://github.com/DavidUv)) [#4396](https://github.com/Leaflet/Leaflet/pull/4396) + +### Bug fixes +* Fixed an edge case on `Map.fitBounds` (by [@perliedman](https://github.com/perliedman)) [#4377](https://github.com/Leaflet/Leaflet/pull/4377) +* Fixed an edge case bug in `flyTo` (by [@hyperknot](https://github.com/hyperknot)) [#4376](https://github.com/Leaflet/Leaflet/pull/4376) +* Use mean earth radius for distance calculation in `L.CRS.Earth`. (by [@perliedman](https://github.com/perliedman)) [#4369](https://github.com/Leaflet/Leaflet/pull/4369) +* Fixed zoom event fired twice (by [@perliedman](https://github.com/perliedman)) [#4367](https://github.com/Leaflet/Leaflet/pull/4367) +* Initialize canvas dash on init. Check that canvas supports `setLineDash`. (by [@perliedman](https://github.com/perliedman)) [#4364](https://github.com/Leaflet/Leaflet/pull/4364) +* Do not calculate inverted y coords for CRSes with infinite: true (by [@jieter](https://github.com/jieter)) [#4344](https://github.com/Leaflet/Leaflet/pull/4344) +* Fixed zoom handling on `Map.TouchZoom` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4340](https://github.com/Leaflet/Leaflet/pull/4340) +* Fixed `this._times.length` undefined in `Map.Drag.js` (by [@LucasMouraDeOliveira](https://github.com/LucasMouraDeOliveira)) [#4324](https://github.com/Leaflet/Leaflet/pull/4324) +* Fixed simulated click handling in `L.Path` (by [@elkami12](https://github.com/elkami12)) [#4314](https://github.com/Leaflet/Leaflet/pull/4314) +* Fixed attribution text not removed when Layer is removed from map (by [@dr-itz](https://github.com/dr-itz)) [#4293](https://github.com/Leaflet/Leaflet/pull/4293) +* Fixed bug when adding/removing a layer from `L.Control.Layer` that is not on the map (by [@errebenito](https://github.com/errebenito)) [#4280](https://github.com/Leaflet/Leaflet/pull/4280) +* Fixed `Map.attributionControl` only set on `addInitHook` (by [@snkashis](https://github.com/snkashis)) [#4263](https://github.com/Leaflet/Leaflet/pull/4263) +* Check for `e.originalEvent` in `DomUtil._filterclick` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4256](https://github.com/Leaflet/Leaflet/pull/4256) +* Stop drag propagation on `L.Draggable` (by [@turban](https://github.com/turban)) [#4250](https://github.com/Leaflet/Leaflet/pull/4250) +* Fixed error when quickly removing a layer just added (by [@hyperknot](https://github.com/hyperknot)) [#4244](https://github.com/Leaflet/Leaflet/pull/4244) +* Fixed not resetting properly on `Map.stop` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4229](https://github.com/Leaflet/Leaflet/pull/4229) +* Fixed conflict between `Map.fadeAnimation` and `GridLayer.opacity` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4228](https://github.com/Leaflet/Leaflet/pull/4228) +* Fix fractional zoom calculation (by [@hyperknot](https://github.com/hyperknot)) [#4224](https://github.com/Leaflet/Leaflet/pull/4224) +* Better cleanup of L.Control.Layers, fixes [#4213](https://github.com/Leaflet/Leaflet/pull/4213) (plus unit tests) (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4214](https://github.com/Leaflet/Leaflet/pull/4214) +* Fixed transform issue when not `L.Browser.any3d` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4212](https://github.com/Leaflet/Leaflet/pull/4212) +* Fixed fractional zoom controls broken when initial zoom isn't specified (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4209](https://github.com/Leaflet/Leaflet/pull/4209) +* Fix extra tiles usage (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4193](https://github.com/Leaflet/Leaflet/pull/4193) +* Sanity check: test `pxBounds` validity before using it (by [@yohanboniface](https://github.com/yohanboniface)) [#4191](https://github.com/Leaflet/Leaflet/pull/4191) +* Disable event defaults when disabling scroll propagation (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4160](https://github.com/Leaflet/Leaflet/pull/4160) +* Fixed precision issues in `L.Circle` radius (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4133](https://github.com/Leaflet/Leaflet/pull/4133) +* Workarounded some touch-capable browsers firing `dblclick` instead of touch events (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4131](https://github.com/Leaflet/Leaflet/pull/4131) +* Use all projected coords when calculating `L.Polyline`'s pixel bounds. (by [@perliedman](https://github.com/perliedman)) [#4114](https://github.com/Leaflet/Leaflet/pull/4114) +* Fixed removing all events when passing an `undefined` property (by [@robertleeplummerjr](https://github.com/robertleeplummerjr)) [#4113](https://github.com/Leaflet/Leaflet/pull/4113) +* Fixed retina URL computation (by [@hyperknot](https://github.com/hyperknot)) [#4110](https://github.com/Leaflet/Leaflet/pull/4110) +* Fire `tileunload` for all unloading of tiles (by [@tcoats](https://github.com/tcoats)) [#4099](https://github.com/Leaflet/Leaflet/pull/4099) +* Fixed duplicated code in `L.GridLayer.retainParent()` (by [@jblarsen](https://github.com/jblarsen)) [#4094](https://github.com/Leaflet/Leaflet/pull/4094) +* Make sure to always reset `_enforcingBounds`. (by [@perliedman](https://github.com/perliedman)) [#4089](https://github.com/Leaflet/Leaflet/pull/4089) +* Fix bug with max bounds and custom projections (by [@OleLaursen](https://github.com/OleLaursen)) [#4078](https://github.com/Leaflet/Leaflet/pull/4078) +* When limiting center to bounds, ignore offsets less than a pixel. (by [@perliedman](https://github.com/perliedman)) [#4077](https://github.com/Leaflet/Leaflet/pull/4077) +* Fixed bug for hover event between circle overlapping polygon on canvas (by [@fimietta](https://github.com/fimietta)) [#4072](https://github.com/Leaflet/Leaflet/pull/4072) +* Fixed but where `L.Control.Layers` where calling `map._size` instead of `getSize()` (by [@Brobin](https://github.com/Brobin)) [#4063](https://github.com/Leaflet/Leaflet/pull/4063) +* Round new map position before animating pan (by [@RLRR](https://github.com/RLRR)) [#4046](https://github.com/Leaflet/Leaflet/pull/4046) +* Fixed overlayed circles not responding to mouse events in canvas (by [@Deftwun](https://github.com/Deftwun)) [#4033](https://github.com/Leaflet/Leaflet/pull/4033) +* Fixed GeoJSON `resetStyle` (by [@yohanboniface](https://github.com/yohanboniface)) [#4028](https://github.com/Leaflet/Leaflet/pull/4028) +* Fixed popup toggle on marker click (by [@yohanboniface](https://github.com/yohanboniface)) [#4016](https://github.com/Leaflet/Leaflet/pull/4016) +* Fixed event target fallbacking to map after marker drag (fix [#3971](https://github.com/Leaflet/Leaflet/pull/3971)) (by [@yohanboniface](https://github.com/yohanboniface)) [#4010](https://github.com/Leaflet/Leaflet/pull/4010) +* Fixed `maxZoom` not honoring 0 (by [@simsibimsiwimsi](https://github.com/simsibimsiwimsi)) [#4000](https://github.com/Leaflet/Leaflet/pull/4000) +* Skip `L.GridLayer._updateLevels()` when out of min/max zoom (prevents IE8 exceptions) (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3999](https://github.com/Leaflet/Leaflet/pull/3999) +* `L.DomUtil.getPosition()` should return a fallback value (for VML in IE8) (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3998](https://github.com/Leaflet/Leaflet/pull/3998) +* `L.Marker`: init interaction regardless of new icon or not (by [@celadevra](https://github.com/celadevra)) [#3978](https://github.com/Leaflet/Leaflet/pull/3978) +* Fix `interactive=false` not taken into account for canvas (by [@yohanboniface](https://github.com/yohanboniface)) [#3956](https://github.com/Leaflet/Leaflet/pull/3956) +* Fix canvas path disappearing on animation (by [@klaftertief](https://github.com/klaftertief)) [#3950](https://github.com/Leaflet/Leaflet/pull/3950) +* Only check for moving draggable in canvas renderer when map is draggable (by [@klaftertief](https://github.com/klaftertief)) [#3942](https://github.com/Leaflet/Leaflet/pull/3942) +* Fix SVG Dragging issues in IE and Edge (by [@perliedman](https://github.com/perliedman)) [#4382](https://github.com/Leaflet/Leaflet/pull/4382) +* Fix click not working on inputs in controls in IE 11 (by [@perliedman](https://github.com/perliedman)) [#4371](https://github.com/Leaflet/Leaflet/pull/4371) +* Make drag and touch zoom handlers insensitive to order of event handlers (by [@perliedman](https://github.com/perliedman)) [#4387](https://github.com/Leaflet/Leaflet/pull/4387) + +### Other +* Added a Code of Conduct (by [@mourner](https://github.com/mourner)) [#4142](https://github.com/Leaflet/Leaflet/pull/4142) +* Dual 1.0 & 0.7 docs to gh-pages (by [@IvanSanchez](https://github.com/IvanSanchez)) [#4085](https://github.com/Leaflet/Leaflet/pull/4085) +* 🍂doc (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3916](https://github.com/Leaflet/Leaflet/pull/3916) +* A lot of documentation improvements (by [@nathancahill](https://github.com/nathancahill)) [#4418](https://github.com/Leaflet/Leaflet/pull/4418), [#4419](https://github.com/Leaflet/Leaflet/pull/4419), [#4423](https://github.com/Leaflet/Leaflet/pull/4423), [#4425](https://github.com/Leaflet/Leaflet/pull/4425) and [a lot more](https://github.com/Leaflet/Leaflet/pulls?q=is%3Apr+author%3Anathancahill+is%3Aclosed) +* Replace links to google groups with ones to GIS StackExchange (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3886](https://github.com/Leaflet/Leaflet/pull/3886) + + +## 1.0-beta2 (2015-10-14) + +Beta 2 fixes over 50 bugs that were reported by users trying out beta 1. The vast majority of changes are small fixes to problems that are triggered in very specific situations or conditions, a few API consolidation changes, and a few browser workarounds. + +### API changes + +* `L.circle` now accepts `radius` as an option (like `L.circleMarker`) rather than a second argument (by [@IvanSanchez](https://github.com/IvanSanchez)) + +### Improvements + +* Implemented canvas optimizations on mousehover interactions (by [@philippelatulippe](https://github.com/philippelatulippe)) [#3076](https://github.com/Leaflet/Leaflet/issues/3076) +* Improved drag behaviour by preventing a `preclick` event during drag (by [@yohanboniface](https://github.com/yohanboniface)) [#3632](https://github.com/Leaflet/Leaflet/issues/3632) +* Implemented `L.ImageOverlay.setBounds()` and fixed image overlay initialization (by [@fminuti](https://github.com/fminuti)) [#3680](https://github.com/Leaflet/Leaflet/pull/3680) +* Implemented draggable items to fire `mousedown` events (by [@yohanboniface](https://github.com/yohanboniface)) [#3682](https://github.com/Leaflet/Leaflet/pull/3682) +* Changed detection of browsers capable of `msPointer` events (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3684](https://github.com/Leaflet/Leaflet/pull/3684) +* Implemented latitude truncation for spherical mercator projection (by [@perliedman](https://github.com/perliedman)) [#3700](https://github.com/Leaflet/Leaflet/issues/3700) +* Armored against browsers not implementing `Geolocation.clearWatch()` [#3707](https://github.com/Leaflet/Leaflet/issues/3707) +* Implemented generation of sourcemaps when building and minifying source files (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3723](https://github.com/Leaflet/Leaflet/pull/3723) +* Added `bringToFront` and `bringToBack` to popups (by [@danzel](https://github.com/danzel)). [#3908](https://github.com/Leaflet/Leaflet/pull/3908) [#3307](https://github.com/Leaflet/Leaflet/issues/3813) +* Multiply offset by 3 on keyboard pan when shift key is pressed (by [@yohanboniface](https://github.com/yohanboniface)) [#3921](https://github.com/Leaflet/Leaflet/pull/3921) + +### Bug fixes + +* Fixed event propagation on double finger tap (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3532](https://github.com/Leaflet/Leaflet/issues/3532) +* Fixed style changes on re-added layers (by [@wpf500](https://github.com/wpf500)) [#3547](https://github.com/Leaflet/Leaflet/pull/3547) +* Fixed `preventOutline` exceptions [#3625](https://github.com/Leaflet/Leaflet/issues/3625) +* Fixed a box zoom regression bug [#3633](https://github.com/Leaflet/Leaflet/issues/3633) +* Fixed `contextmenu` behaviour when there are no event listeners (by [@yohanboniface](https://github.com/yohanboniface)) [#3638](https://github.com/Leaflet/Leaflet/issues/3638) +* Fixed map controls not showing on top of map layers (by [@patrickarlt](https://github.com/patrickarlt)) [#3644](https://github.com/Leaflet/Leaflet/pull/3644) +* Fixed display of marker images with `max-width` (by [@davidjb](https://github.com/davidjb)) [#3647](https://github.com/Leaflet/Leaflet/pull/3647) +* Fixed `mouseout` and `mouseover` event bubbling (by [@yohanboniface](https://github.com/yohanboniface)) [#3648](https://github.com/Leaflet/Leaflet/issues/3648) [#3797](https://github.com/Leaflet/Leaflet/issues/3797) [#3708](https://github.com/Leaflet/Leaflet/issues/3708) +* Fixed a layer control bug when removing layers (by [@davidlukerice](https://github.com/davidlukerice)) [#3651](https://github.com/Leaflet/Leaflet/pull/3651) +* Fixed pan and zoom animations interacting with each other [#3355](https://github.com/Leaflet/Leaflet/issues/3355) [#3655](https://github.com/Leaflet/Leaflet/issues/3655) +* Fixed a regression bug in canvas renderer when removing layers [#3661](https://github.com/Leaflet/Leaflet/issues/3661) +* Remove a workaround for legacy Android 2 browsers [#2282](https://github.com/Leaflet/Leaflet/issues/2282) +* Fixed VML vector rendering in IE8 when removing and re-adding layers (by [@fminuti](https://github.com/fminuti)) [#2809](https://github.com/Leaflet/Leaflet/issues/2809) +* Fixed `flyTo` animations when the map center doesn't change (by [@fminuti](https://github.com/fminuti)) [#3663](https://github.com/Leaflet/Leaflet/pull/3663) +* Fixed fade animations for semitransparent tile layers (by [@w8r](https://github.com/w8r)) [#3671](https://github.com/Leaflet/Leaflet/pull/3671) +* Fixed behaviour of the `baselayerchange` event (by [@yohanboniface](https://github.com/yohanboniface)) [#3677](https://github.com/Leaflet/Leaflet/issues/3677) +* Fixed marker icon handling during a marker drag (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3687](https://github.com/Leaflet/Leaflet/issues/3687) +* Fixed a IE 11 map container visibility bug (by [@fminuti](https://github.com/fminuti)) [#2788](https://github.com/Leaflet/Leaflet/issues/2788) +* Prevented dragging interactions while a map zoom animation is running (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3692](https://github.com/Leaflet/Leaflet/issues/3692) +* Implement disabling layers in the layer control when they are unavailable at the current zoom level (by [@IvanSanchez](https://github.com/IvanSanchez)) [#252](https://github.com/Leaflet/Leaflet/issues/252) +* Refactored `L.Util.requestAnimFrame` definition (by [@fminuti](https://github.com/fminuti)) [#3703](https://github.com/Leaflet/Leaflet/issues/3703) +* Fixed an edge case of `L.Circle.getBounds()` (by [@knabar](https://github.com/knabar)) [#3776](https://github.com/Leaflet/Leaflet/pull/3776) +* Fixed `Rectangle.setBounds()` return value (by [@IvanSanchez](https://github.com/IvanSanchez)) https://github.com/Leaflet/Leaflet/commit/e698f641afadd4a0b412a6c9e065a6dbfbe16f44 +* Fixed event firing order when opening a popup (by [@yohanboniface](https://github.com/yohanboniface)) [#3745](https://github.com/Leaflet/Leaflet/issues/3745) +* Fixed tile layer loading when dragging then immediately pinch-zooming the map (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3814](https://github.com/Leaflet/Leaflet/issues/3814) +* Work around browser limitations when panning the map too far away (by [@yohanboniface](https://github.com/yohanboniface) and [@IvanSanchez](https://github.com/IvanSanchez)) [#3608](https://github.com/Leaflet/Leaflet/issues/3608) +* Fixed popup text selection and touch events for IE 10 (by [@danzel](https://github.com/danzel)) [#3804](https://github.com/Leaflet/Leaflet/issues/3804) +* Fixed tile layer ordering when `maxZoom` is set (by [@patrickarlt](https://github.com/patrickarlt)) [#3721](https://github.com/Leaflet/Leaflet/issues/3721) +* Fixed scale behaviour on non-standard CRSs (by [@javimolla](https://github.com/patrickarlt), special thanks to [Your First PR](https://yourfirstpr.github.io/)) [#2990](https://github.com/Leaflet/Leaflet/issues/2990) +* Fixed rendering of off-screen vector layers (by [@yohanboniface](https://github.com/yohanboniface)) [#3836](https://github.com/Leaflet/Leaflet/issues/3836) +* Fixed rendering of intersecting vector layers (by [@yohanboniface](https://github.com/yohanboniface)) [#3583](https://github.com/Leaflet/Leaflet/issues/3583) +* Enforced stricter code linting +* Fixed disabled drag handlers not being able to be re-enabled (by [@yohanboniface](https://github.com/yohanboniface)) [#3825](https://github.com/Leaflet/Leaflet/issues/3825) +* Fixed panning outside the map bounds (by [@yohanboniface](https://github.com/yohanboniface)) [#3878](https://github.com/Leaflet/Leaflet/issues/3878) +* Worked around IE 11 not focusing the map using keyboard (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3772](https://github.com/Leaflet/Leaflet/issues/3772) +* Fixed vector layer positioning during a zoom animation in low zoom (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3769](https://github.com/Leaflet/Leaflet/issues/3769) +* Implemented `noWrap` option in `L.GridLayer` (by [@IvanSanchez](https://github.com/IvanSanchez)) [#3691](https://github.com/Leaflet/Leaflet/issues/3691) +* Fixed popups panning the map while running another pan animation (by [@yohanboniface](https://github.com/yohanboniface)) [#3744](https://github.com/Leaflet/Leaflet/issues/3744) +* Fixed uncorrect length of scale control due to CSS styles (by [@yohanboniface](https://github.com/yohanboniface)) [#3668](https://github.com/Leaflet/Leaflet/issues/3668) +* Fixed detection of default image path for icons (by [@ilfa](https://github.com/ilfa)) [#3770](https://github.com/Leaflet/Leaflet/pull/3770) +* Various Canvas events fixes (by [@yohanboniface](https://github.com/yohanboniface)) [#3917](https://github.com/Leaflet/Leaflet/pull/3917) +* Fix touch scroll in layers control (by [@yohanboniface](https://github.com/yohanboniface)) [#2882](https://github.com/Leaflet/Leaflet/issues/2882) +* Fix duration not passed through from setView to panBy (by [@yohanboniface](https://github.com/yohanboniface)) [#3300](https://github.com/Leaflet/Leaflet/issues/3300) + + +## 1.0-beta1 (2015-07-14) + +The first beta of the huge, long-awaited Leaflet 1.0 release. + +This version contains a lot of beneficial but potentially breaking changes (especially if you're a plugin author), so please read through the changes carefully if your code breaks after upgrading. + +### Vectors API improvements + +Leaflet vector layers rendering got a major rewrite, making it possible to switch between rendering backends (Canvas, SVG) dynamically (and even use both for different layers at the same time), have more than one physical pane for vector layers, significantly improving performance, adding Canvas retina support, getting rid of ugly hacks and generally making the code much cleaner. Main PR [#2290](https://github.com/Leaflet/Leaflet/pull/2290). + +* Added `Renderer` layer (inherited by SVG/Canvas implementations) that handles renderer bounds and zoom animation. +* Added `SVG` & `Canvas` classes that now contain all renderer-specific code for vector layers and can be added as layers to the map. +* All vector layer classes (`Path`, `Polyline`, etc.) now don't contain any renderer-specific code and instead can be passed a renderer layer to use as `renderer` in options; +* Removed `MultiPolyline` and `MultiPolygon` classes since multiple rings are now handled by `Polyline` and `Polygon` classes respectively. Layers with multiple rings now perform much better (since each is now physically a single path object instead of being a `FeatureGroup` of layers). +* **Dramatically improved performance of interactive Canvas layers**. Mouse events work much faster (due to improved hit detection algorithms), and layers get updated many times faster (with partial redraws instead of redrawing the whole Canvas). +* **Dramatically improved performance of interactive SVG layers** (e.g. creating a big GeoJSON layer and adding to a map got 3x faster while taking 2.5x less memory). [#2240](https://github.com/Leaflet/Leaflet/issues/2240) [#2315](https://github.com/Leaflet/Leaflet/issues/2315) +* Added retina support for Canvas layers. +* Improved default vector layer styles. +* Added `Polyline` and `Polygon` `getCenter` for getting centroids. +* Respectively, improved `Polyline` and `Polygon` popup positioning when calling `openPopup`. +* Improved `Polyline`/`Polygon` `getBounds` to be cached (so it works much faster). +* Changed `Circle` to inherit from `CircleMarker` and not the other way. +* Fixed `GeoJSON` `resetStyle` to work properly in case `style` option wasn't set. +* Fixed a bug where map fired `moveend` when updating Canvas layers. +* Removed `Polyline` and `Polygon` `spliceLatLngs` method (just use `setLatLngs` instead). +* Changed `Polygon` `getLatLngs` to always return an array of rings (nested array) (by [@yohanboniface](https://github.com/yohanboniface)). [#2618](https://github.com/Leaflet/Leaflet/issues/2618) [#3386](https://github.com/Leaflet/Leaflet/pull/3386) [Leaflet/Leaflet#3279](https://github.com/Leaflet/Leaflet/pull/3279) [#2648](https://github.com/Leaflet/Leaflet/issues/2648) +* Added the ability to specify a custom pane for vector layers (making it possible to easily do stacks like vectors-tiles-vectors with proper z-index order) (by [@Jakobud](https://github.com/Jakobud)). [#3266](https://github.com/Leaflet/Leaflet/pull/3266) [#2786](https://github.com/Leaflet/Leaflet/pull/2786) +* Added vector layers `fillRule` option (by [@bullgare](https://github.com/bullgare)). [#2834](https://github.com/Leaflet/Leaflet/pull/2834) +* Removed `L_PREFER_CANVAS` global switch and added `Map` `preferCanvas` option instead (by [@yohanboniface](https://github.com/yohanboniface)). [#3623](https://github.com/Leaflet/Leaflet/pull/3623) + +### Layers API improvements + +All Leaflet layers (including markers, popups, tile and vector layers) have been refactored to have a common parent, `Layer` class, that shares the basic logic of adding and removing. The leads to the following changes (main PR [#2266](https://github.com/Leaflet/Leaflet/pull/2266)): + +* Added `Layer` class which all layers added to a map should inherit from. +* Added `add` and `remove` events to all layers. +* Added `remove` method to layers and controls (`marker.remove()` is now equivalent to `map.removeLayer(marker)`). +* Improved performance of adding and removing layers. +* Added `pane` option to all layers that can be changed (e.g. you can set `pane: 'overlayPane'` to a tile layer). +* Added `map` `createPane` method for custom panes. [#1742](https://github.com/Leaflet/Leaflet/issues/1742) +* Simplified map panes — removed `objectsPane`, all panes are on the same level now. +* Added `shadowPane` option to markers as well. +* Added `getEvents` method to all layers that returns an `{event: listener, ...}` hash; layers now manage its listeners automatically without having to do this in `onAdd`/`onRemove`. +* Added `togglePopup`, `setPopupContent`, `getPopup`, `isPopupOpen` methods to all layers. [#2279](https://github.com/Leaflet/Leaflet/issues/2279) [#2292](https://github.com/Leaflet/Leaflet/issues/2292) +* Improved performance of adding/removing layers with layers control present (instead of listening to any layer add/remove, the control only listens to layers added in configuration). +* Fixed `FeatureGroup` `getBounds` to work correctly when containing circle markers. +* Removed `Map` `tilelayersload` event. +* Removed `Popup` `open` and `close` events in favor of `add` and `remove` for consistency. +* Moved all layer-related logic in `Map.js` to `Layer.js`. +* Improved `FeatureGroup` `bindPopup` to accept a function for generating popup content, significantly improving memory footprint when adding popups to a huge number of layers (by [@patrickarlt](https://github.com/patrickarlt)). [#3109](https://github.com/Leaflet/Leaflet/pull/3109) [#3059](https://github.com/Leaflet/Leaflet/pull/3059) +* Added `ImageOverlay` interactivity (mouse events, etc.) (by [@snkashis](https://github.com/snkashis)). [#3009](https://github.com/Leaflet/Leaflet/pull/3009) [#1727](https://github.com/Leaflet/Leaflet/issues/1727) +* Added `ImageOverlay` `getBounds` (by [@brunob](https://github.com/brunob)). [#2848](https://github.com/Leaflet/Leaflet/pull/2848) +* Renamed `clickable` option to `interactive` (by [@AndriiHeonia](https://github.com/AndriiHeonia)). [#2838](https://github.com/Leaflet/Leaflet/pull/2838) [#2499](https://github.com/Leaflet/Leaflet/issues/2499) +* Changed the default z-index of panes to be bigger, leaving more room for customization (by [@patrickarlt](https://github.com/patrickarlt)). [#3591](https://github.com/Leaflet/Leaflet/pull/3591) +* Improved DOM event bubbling mechanism for layers (by [@yohanboniface](https://github.com/yohanboniface)). [Leaflet/Leaflet#3307](https://github.com/Leaflet/Leaflet/pull/3307) [#3450](https://github.com/Leaflet/Leaflet/pull/3450) [#3307](https://github.com/Leaflet/Leaflet/pull/3307) +* Added `nonBubblingEvents` option to layers (by [@yohanboniface](https://github.com/yohanboniface)). [#3605](https://github.com/Leaflet/Leaflet/pull/3605) [#3307](https://github.com/Leaflet/Leaflet/pull/3307) [#3604](https://github.com/Leaflet/Leaflet/issues/3604) + +In addition, layer events implementation was rewritten to use **event delegation**, significantly improving add/remove performance and memory footprint. [#3032](https://github.com/Leaflet/Leaflet/pull/3032) [#46](https://github.com/Leaflet/Leaflet/issues/46) + +### TileLayer & Projections API improvements + +TileLayer code and everything projections-related has undergone a major refactoring, documented in PR [#2247](https://github.com/Leaflet/Leaflet/pull/2247). It includes the following changes (in addition to much cleaner and simpler code): + +#### TileLayer API improvements + +These changes make implementing custom grid-like layers for Leaflet much easier. + +* Moved most of the `TileLayer` logic into the new `GridLayer` class (which `TileLayer` now inherits, extending it with logic specific to tile servers). +* Removed `TileLayer.Canvas` in favor of the much more flexible and powerful `GridLayer`. +* Improved tile wrapping and bounding logic in `TileLayer` to work transparently and completely depent on the CRS used; removed the need for `TileLayer` hacks when using custom projections. +* Added non-square tiles support (by [@IvanSanchez](https://github.com/IvanSanchez)). [#3573](https://github.com/Leaflet/Leaflet/pull/3573) [#3570](https://github.com/Leaflet/Leaflet/issues/3570) +* Removed `url` property in `tileload` and `tileloadstart` events (get it through `tile.src`). + +#### Projections API improvements + +These changes were targeted at removing any hardcoded projection-specific logic accross Leaflet classes, making it transparent and driven by the chosen CRS. They make using Leaflet with custom projections (including flat maps) much easier, and remove the need for ugly hacks in the [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin. + +* Added `CRS.Earth` which serves as a base for all Earth-based CRS (`EPSG3857` etc.). [#2345](https://github.com/Leaflet/Leaflet/pull/2345) +* Added `Projection` `bounds` property that defines bounds for different projections (`Mercator`, etc.) in projected coordinates (by [@perliedman](https://github.com/perliedman)). +* Added `CRS` `wrapLat` and `wrapLng` properties which define whether the world wraps on a given axis and in what range. Set as `[-180, 180]` for `EPSG:3857`, `EPSG:4326`, `EPSG:3395` by default. +* Added `CRS` and `Map` `wrapLatLng` (the latter depends on the chosen CRS). +* Added `CRS` `infinite` property that disables boundaries (the world can go on infinitely in any direction), default for `CRS.Simple`. +* Added `CRS` `getProjectedBounds` and `Map` `getPixelWorldBounds` methods that returns world bounds in projected coordinates depending on zoom (derived from `Projection` `bounds`) (by [@perliedman](https://github.com/perliedman)). +* Added `CRS` `unproject` method that converts coordinates in CRS-dependent units into `LatLng` coordinates (by [@sowelie](https://github.com/sowelie)). +* Added `Map` `distance(latlng1, latlng2)` method that takes CRS into account and works with flat projections. [#2345](https://github.com/Leaflet/Leaflet/pull/2345) [#1442](https://github.com/Leaflet/Leaflet/issues/1442) +* Improved `Circle` to be approximated with an ellipse in Earth-based projections. [#2345](https://github.com/Leaflet/Leaflet/pull/2345) +* Fixed `EPSG:4326` to have correct tile pyramid (2x1 tiles at root). +* Fixed `Projection.SphericalMercator` to project to meter units (by [@calvinmetcalf](https://github.com/calvinmetcalf)). +* Fixed `Map` `worldCopyJump` option to work for other projections. +* Fixed `Circle` to work with flat projections. [#2345](https://github.com/Leaflet/Leaflet/pull/2345) [#1465](https://github.com/Leaflet/Leaflet/issues/1465) +* Fixed scale control precision in non-EPSG:3857 projections. [#2345](https://github.com/Leaflet/Leaflet/pull/2345) +* Fixed `ImageOverlay` not working properly in some non-standard projections. [#3011](https://github.com/Leaflet/Leaflet/issues/3011) + + +### Animations improvements and fractional zoom + +Animation code in Leaflet had undergone a major rewrite (main PR: [#2382](https://github.com/Leaflet/Leaflet/pull/2382)), bringing improvements such as: + +- Multi-level tile buffering for more seamless zooming experience with less flickering +- Optimal path animation (`map.flyTo`) for zooming to a particular place in a curve (simultaneously zooming and panning) +- Fractional zoom support — now you can do things like `map.setZoom(12.45)` and it just works. +- Layers now rely on `zoom` event in addition to `viewreset` for frame-by-frame zoom animations. [#3278](https://github.com/Leaflet/Leaflet/pull/3278) + +### UX improvements + +* Improved panning inertia behavior so that there are no tearing during animation when panning around quickly. [#2360](https://github.com/Leaflet/Leaflet/issues/2360) +* Improved inertial scrolling to have a nicer, more natural feel (by [@RickMohr](https://github.com/RickMohr)). [Leaflet/Leaflet#3063](https://github.com/Leaflet/Leaflet/pull/3063) [#3063](https://github.com/Leaflet/Leaflet/pull/3063) [#3062](https://github.com/Leaflet/Leaflet/issues/3062) [#2987](https://github.com/Leaflet/Leaflet/issues/2987) +* Added popup fade out animation. +* Improved keyboard support to ignore keystrokes with modifier keys (Ctrl, Alt, Meta) to not interfere with OS shortcuts. +* Made popup to close when pressing Escape (by [@snkashis](https://github.com/snkashis)). [#951](https://github.com/Leaflet/Leaflet/issues/951) [#3000](https://github.com/Leaflet/Leaflet/pull/3000) +* Improved keyboard zoom to zoom by 3 levels if shift key is pressed (by [@yohanboniface](https://github.com/yohanboniface)). [#3024](https://github.com/Leaflet/Leaflet/pull/3024) +* Improved layers control to become scrollable when there are too many layers (by [@rowanwins](https://github.com/rowanwins)). [#3571](https://github.com/Leaflet/Leaflet/pull/3571) [#3167](https://github.com/Leaflet/Leaflet/issues/3167) + +### Misc. performance improvements + +* Significantly [improved](http://jsperf.com/leaflet-parsefloat-in-latlng/2) `LatLng` creation performance (8x). +* Improved performance of layer objects construction. +* Significantly improved `FeatureGroup` (and correspondingly `GeoJSON`) layer adding and events performance (about 10x) by implementing a much better event propagation mechanism. [#2311](https://github.com/Leaflet/Leaflet/pull/2311) +* Improved Leaflet events and DOM events memory footprint. +* Improved `Evented` `off` performance by about 2 times. + +### Other breaking API changes + +* Changed `DomUtil` `off` to require `context` attribute if you remove a listener that was previously added with a particular context. +* Removed `DomUtil.getViewportOffset` method as it is no longer necessary. +* Removed `DomUtil` `getTranslateString` and `getScaleString` methods. +* Removed `DomUtil` `documentIsLtr` method. +* Removed `LatLng` `RAD_TO_DEG`, `DEG_TO_RAD` and `MAX_MARGIN` constants. +* Renamed `Util.limitExecByInterval` to `Util.throttle`. + +### Other API improvements + +* Added `Evented` class that now many Leaflet classes inherit from (instead of mixing in events methods in each class), while keeping the old `includes: L.Mixin.Events` syntax available. [#2310](https://github.com/Leaflet/Leaflet/pull/2310) +* Improved `Class` `options` to be prototypically inherited instead of copied over in children classes, which leads to more efficient memory use, faster object construction times and ability to change parent options that get propagated to all children automatically (by [@jfirebaugh](https://github.com/jfirebaugh)). [#2300](https://github.com/Leaflet/Leaflet/pull/2300) [#2294](https://github.com/Leaflet/Leaflet/issues/2294) +* Added `{r}` variable to `TileLayer` `url` for adding `"@2x"` prefix on Retina-enabled devices (by [@urbaniak](https://github.com/urbaniak)). [#2296](https://github.com/Leaflet/Leaflet/pull/2296) +* Added `Point` `ceil` method (by [@perliedman](https://github.com/perliedman)). +* Added `Util.wrapNum` method for wrapping a number to lie in a certain range. +* Improved `L.bind` to use native `Function` `bind` on modern browsers and prepend real arguments to bound ones. +* Added `LatLng` `equals` second argument `maxMargin`. +* Added `DomUtil` `setClass` and `getClass` methods. +* Improved `Marker` `move` event to include `oldLatlng` (by [@danzel](https://github.com/danzel)). [#2412](https://github.com/Leaflet/Leaflet/pull/2412) +* Added `Marker` `mousemove` event (by [@bullgare](https://github.com/bullgare)). [#2798](https://github.com/Leaflet/Leaflet/pull/2798) +* Improved `DomEvent` `on`/`off` to accept space-separated events and object literals (`{type: fn}`). +* Added `DomUtil` `toFront` and `toBack` methods. +* Added `Evented` `listens` as a shortcut to `hasEventListeners`. +* Added optional support for center-oriented scroll for `L.map` option `touchZoom` (by [@mtmail](https://github.com/mtmail)). [#2527](https://github.com/Leaflet/Leaflet/pull/2527) +* Added `getElement` method to all layers that returns an associated DOM element. +* Added `LatLng` `clone` method (by [@yohanboniface](https://github.com/yohanboniface)). [#3390](https://github.com/Leaflet/Leaflet/pull/3390) +* Added `Map` `setMinZoom` and `setMaxZoom` methods (by [@nathancahill](https://github.com/nathancahill)). [#3383](https://github.com/Leaflet/Leaflet/pull/3383) [#3380](https://github.com/Leaflet/Leaflet/issues/3380) +* Added `originalEvent` to `Map` and `Marker` `drag` and `move` event data (by [@yohanboniface](https://github.com/yohanboniface)). [#3264](https://github.com/Leaflet/Leaflet/pull/3264) +* Added `Popup` `autoClose` option (by [@jfirebaugh](https://github.com/jfirebaugh)). [#3018](https://github.com/Leaflet/Leaflet/pull/3018) [#2716](https://github.com/Leaflet/Leaflet/issues/2716) [#1853](https://github.com/Leaflet/Leaflet/issues/1853) +* Added `Control.Zoom` `enable` and `disable` methods. [#3172](https://github.com/Leaflet/Leaflet/issues/3172) +* Added an argument to `L.PolyUtil.clipPolygon` that controls rounding (by [@aparshin](https://github.com/aparshin)). [#2926](https://github.com/Leaflet/Leaflet/pull/2926) [#2917](https://github.com/Leaflet/Leaflet/issues/2917) +* Added `Map` `wheelDebounceTime` option (by [@AndriiHeonia](https://github.com/AndriiHeonia)). [#2836](https://github.com/Leaflet/Leaflet/pull/2836) [#2501](https://github.com/Leaflet/Leaflet/issues/2501) +* Added `TileLayer.WMS` `uppercase` option (now `false` by default) (by [@kdeloach](https://github.com/kdeloach)). [#2831](https://github.com/Leaflet/Leaflet/pull/2831) [#1751](https://github.com/Leaflet/Leaflet/issues/1751) +* Added `ImageOverlay` `alt` option (by [@francis-liberty](https://github.com/francis-liberty)). [#2767](https://github.com/Leaflet/Leaflet/pull/2767) [#2564](https://github.com/Leaflet/Leaflet/issues/2564) +* Improved `L.Util.extend` performance (by [@fab1an](https://github.com/fab1an)). [#2746](https://github.com/Leaflet/Leaflet/pull/2746) +* Added `Map` `stop` method for stopping panning or `flyTo` animation. +* Added `Map` `maxBoundsViscosity` option that controls how much the map resits dragging out of max bounds (set to `1` for a hard limit) (by [@IvanSanchez](https://github.com/IvanSanchez)). [#2224](https://github.com/Leaflet/Leaflet/pull/2224) [#3510](https://github.com/Leaflet/Leaflet/pull/3510) [#1673](https://github.com/Leaflet/Leaflet/issues/1673) +* Added `Bounds` and `LatLngBounds` `overlaps` method (by [@IvanSanchez](https://github.com/IvanSanchez)). [#2981](https://github.com/Leaflet/Leaflet/issues/2981) [#3508](https://github.com/Leaflet/Leaflet/pull/3508) +* Added `ImageOverlay` `crossOrigin` option (by [@patrickarlt](https://github.com/patrickarlt)). [#3594](https://github.com/Leaflet/Leaflet/pull/3594) [#2621](https://github.com/Leaflet/Leaflet/pull/2621) + +### Bugfixes + +* Fixed `DomUtil` `on` to make it possible to add the same listener to the same element for multiple contexts. +* Fixed a bug that thowed an error when attempting to reinitialize the map on unload (by [@gamb](https://github.com/gamb)). [#2410](https://github.com/Leaflet/Leaflet/pull/2410) +* Fixed excessively blurry non-retina tiles on retina iOS devices. +* Fixed a bug with popup close button in IE7/8. [#2351](https://github.com/Leaflet/Leaflet/issues/2351) +* Fixed `ImageOverlay` mercator distortion on lower zoom levels. +* Fixed a bug where layers didn't fire `popupopen` and `popupclose` events when manually creating a popup object and passing it to `bindPopup`. [#2354](https://github.com/Leaflet/Leaflet/issues/2354) +* Fixed box-zoom overlay appearing under markers. [#1813](https://github.com/Leaflet/Leaflet/issues/1813) +* Fixed `Map` `panInsideBounds` to accept array-form bounds (by [@RLRR](https://github.com/RLRR)). [#3489](https://github.com/Leaflet/Leaflet/pull/3489) +* Fixed marker draggable state to persist when removing and adding back to the map (by [@IvanSanchez](https://github.com/IvanSanchez)). [#3488](https://github.com/Leaflet/Leaflet/pull/3488) +* Fixed inertia not working when parallel to axis (by [@rikvanmechelen](https://github.com/rikvanmechelen)). [#3432](https://github.com/Leaflet/Leaflet/issues/3432) +* Fixed images and SVG inside popups having max-width property overriden (by [@yohanboniface](https://github.com/yohanboniface)). [#3452](https://github.com/Leaflet/Leaflet/pull/3452) +* Fixed cursors when dragging is disabled (by [@juliensoret](https://github.com/juliensoret)). [#3219](https://github.com/Leaflet/Leaflet/issues/3219) [#3233](https://github.com/Leaflet/Leaflet/pull/3233) +* Fixed `LatLng` `wrap` to not drop altitude (by [@IvanSanchez](https://github.com/IvanSanchez)). [#3420](https://github.com/Leaflet/Leaflet/issues/3420) +* Fixed Firefox for Android not being detected as mobile (by [@IvanSanchez](https://github.com/IvanSanchez)). [#3419](https://github.com/Leaflet/Leaflet/pull/3419) +* Fixed an infinite loop when calling `setMaxBounds` several times in a row (by [@IvanSanchez](https://github.com/IvanSanchez)). [#3410](https://github.com/Leaflet/Leaflet/pull/3410) [#3320](https://github.com/Leaflet/Leaflet/issues/3320) +* Fixed a WTF `Map` `locate` bug that could cause some unexpected effects (by [@sindre](https://github.com/sindre)). [Leaflet/Leaflet#3404](https://github.com/Leaflet/Leaflet/issues/3404) +* Fixed broken zoom in Project Spartan browsers (by [@mitchless](https://github.com/mitchless)). [#3379](https://github.com/Leaflet/Leaflet/pull/3379) +* Fixed broken `Polygon` `getCenter` when all points in the same pixel (by [@yohanboniface](https://github.com/yohanboniface)). [#3372](https://github.com/Leaflet/Leaflet/pull/3372) +* Fixed broken `Polyline` `getCenter` when the line is very small (by [@yohanboniface](https://github.com/yohanboniface)). [#3371](https://github.com/Leaflet/Leaflet/pull/3371) +* Fixed keyboard zoom out not working on `azerty` keyboards. [#3362](https://github.com/Leaflet/Leaflet/issues/3362) +* Fixed a bug where tabbing to an offscreen marker broke control positioning (by [@IvanSanchez](https://github.com/IvanSanchez)). [#3340](https://github.com/Leaflet/Leaflet/pull/3340) [#3333](https://github.com/Leaflet/Leaflet/issues/3333) +* Fixed `Map` `panBy` not always returning `this` (by [@Trufi](https://github.com/Trufi)). [#3303](https://github.com/Leaflet/Leaflet/pull/3303) +* Fixed a bug where pushing a zoom control with a keyboard would switch focus to the map (by [@Jakobud](https://github.com/Jakobud)). [#3275](https://github.com/Leaflet/Leaflet/pull/3275) [#3159](https://github.com/Leaflet/Leaflet/issues/3159) +* Fixed more race conditions leading to map freeze. [#3270](https://github.com/Leaflet/Leaflet/pull/3270) [#3268](https://github.com/Leaflet/Leaflet/issues/3268) [#2693](https://github.com/Leaflet/Leaflet/issues/2693) [#2478](https://github.com/Leaflet/Leaflet/issues/2478) +* Fixed iOS race condition when doing a very small pan. [#2519](https://github.com/Leaflet/Leaflet/issues/2519) +* Fixed `Polygon` `toGeoJSON` exporting a `MultiPolygon` in some cases (by [@yohanboniface](https://github.com/yohanboniface)). [#2977](https://github.com/Leaflet/Leaflet/pull/2977) +* Fixed `TileLayer.WMS` passing all options as WMS params. [#2972](https://github.com/Leaflet/Leaflet/issues/2972) +* Fixed a race condition that made `map.fitBounds(map.getBounds())` zoom out sometimes. [#2957](https://github.com/Leaflet/Leaflet/issues/2957) +* Fixed a bug where a draggable marker stopped being draggable after `setIcon` (by [@jeffsmale90](https://github.com/jeffsmale90)). [#2578](https://github.com/Leaflet/Leaflet/issues/2578) +* Fixed some IE11 touch performance and stability issues (by [@danzel](https://github.com/danzel)). [#3007](https://github.com/Leaflet/Leaflet/pull/3007) [#2820](https://github.com/Leaflet/Leaflet/issues/2820) +* Fixed a race condition with `TileLayer` when `maxNativeZoom = 0`. [#3004](https://github.com/Leaflet/Leaflet/issues/3004) +* Fixed `FeatureGroup` `setStyle` not affecting `ImageOverlay` `opacity` (by [@opie](https://github.com/opie)). [#3008](https://github.com/Leaflet/Leaflet/pull/3008) [#2246](https://github.com/Leaflet/Leaflet/issues/2246) +* Fixed class init hooks not being called for parent classes (by [@jfirebaugh](https://github.com/jfirebaugh)). [#2545](https://github.com/Leaflet/Leaflet/issues/2545) +* Fixed a bug when adding a control that's already added or removing a control that's not present (by [@jfirebaugh](https://github.com/jfirebaugh)). [#3020](https://github.com/Leaflet/Leaflet/issues/3020) [#2877](https://github.com/Leaflet/Leaflet/issues/2877) +* Fixed buggy inertia on low zoom levels when `Map` `worldCopyJump` option is enabled (by [@flemenach](https://github.com/flemenach)). [#3038](https://github.com/Leaflet/Leaflet/pull/3038) [#2624](https://github.com/Leaflet/Leaflet/issues/2624) +* Fixed a bug where `getMaxZoom` sometimes returned wrong result inside a `Control.Layers` `baselayerchange` event (by [@CloudNiner](https://github.com/CloudNiner)). [#3048](https://github.com/Leaflet/Leaflet/pull/3048) [#2318](https://github.com/Leaflet/Leaflet/issues/2318) +* Fixed a bug where during zooming one map, dragging was disabled on all other maps on the page (by [@kdeloach](https://github.com/kdeloach)). [#3050](https://github.com/Leaflet/Leaflet/pull/3050) [#2539](https://github.com/Leaflet/Leaflet/issues/2539) +* Fixed a `Map` `getSize` race condition where it could return a wrong result (by [@kshepard](https://github.com/kshepard)). [#3052](https://github.com/Leaflet/Leaflet/pull/3052) [#3031](https://github.com/Leaflet/Leaflet/issues/3031) +* Fixed `L.latLng` factory to accept `altitude` as a third argument too (by [@lonelyelk](https://github.com/lonelyelk)). [#3070](https://github.com/Leaflet/Leaflet/pull/3070). +* Fixed `L.latLng` factory to not throw error on empty array input (by [@lonelyelk](https://github.com/lonelyelk)). [#3080](https://github.com/Leaflet/Leaflet/pull/3080) [#3079](https://github.com/Leaflet/Leaflet/issues/3079) +* Fixed popups to have a default color (by [@snkashis](https://github.com/snkashis)). [#3115](https://github.com/Leaflet/Leaflet/pull/3115) [#3112](https://github.com/Leaflet/Leaflet/issues/3112) [#333](https://github.com/Leaflet/Leaflet/issues/333) +* Fixed `Map` `locate` not to mutate the given options object (by [@tmcw](https://github.com/tmcw)). [#3173](https://github.com/Leaflet/Leaflet/pull/3173) +* Fixed Canvas polylines not to render if stroke is set to 0 (by [@optical](https://github.com/optical)). [#3203](https://github.com/Leaflet/Leaflet/pull/3203) +* Prevented a Joomla bug that could lead to vector layers disappearing (by [@SniperSister](https://github.com/SniperSister)). [#2886](https://github.com/Leaflet/Leaflet/pull/2886) [#2881](https://github.com/Leaflet/Leaflet/issues/2881) [Leaflet/Leaflet#2881](https://github.com/Leaflet/Leaflet/issues/2881) +* Fixed IE Metro touch events passing through objects on top of a Leaflet map (by [@nikgavalas](https://github.com/nikgavalas)). [#2954](https://github.com/Leaflet/Leaflet/pull/2954) +* Fixed a bug where vector layers wouldn't display on websites with SVG max-width set to 100% (by [@SniperSister](https://github.com/SniperSister)). [#2886](https://github.com/Leaflet/Leaflet/pull/2886) [#2881](https://github.com/Leaflet/Leaflet/issues/2881) +* Fixed `Marker` `setIcon` to not reset popup anchor offset (by [@bullgare](https://github.com/bullgare)). [#2872](https://github.com/Leaflet/Leaflet/pull/2872) +* Fixed a case where you provide `zoom` in `Map` options and then set center (by [@AndriiHeonia](https://github.com/AndriiHeonia)). [#2849](https://github.com/Leaflet/Leaflet/pull/2849) [#1871](https://github.com/Leaflet/Leaflet/issues/1871) +* Fixed a race condition with `TileLayer` `setUrl` where `loading` event didn't fire properly (by [@bennlich](https://github.com/bennlich)). [#2802](https://github.com/Leaflet/Leaflet/pull/2802) [#2675](https://github.com/Leaflet/Leaflet/issues/2675) [#2827](https://github.com/Leaflet/Leaflet/pull/2827) +* Fixed a bug where a tile layer was not cleaned up properly after zooming past its max zoom (by [@francis-liberty](https://github.com/francis-liberty)). [#2764](https://github.com/Leaflet/Leaflet/pull/2764) [#1905](https://github.com/Leaflet/Leaflet/issues/1905) +* Fixed a memory leak with `Marker` `setIcon` (by [@jfgodoy](https://github.com/jfgodoy)). [#2811](https://github.com/Leaflet/Leaflet/pull/2811) +* Fixed `LatLng` `distanceTo` to not return `NaN` on equal locations. [#2705](https://github.com/Leaflet/Leaflet/issues/2705) +* Fixed a bug where `TileLayer` `maxNativeZoom` didn't work properly with `bounds` option set (by [@mlegenhausen](https://github.com/mlegenhausen)). [#2725](https://github.com/Leaflet/Leaflet/pull/2725) [#2704](https://github.com/Leaflet/Leaflet/issues/2704) +* Fixed a bug where tiles touching the edge of the bounds from outside where loaded (by [@IvanSanchez](https://github.com/IvanSanchez)). [#2981](https://github.com/Leaflet/Leaflet/issues/2981) [#3508](https://github.com/Leaflet/Leaflet/pull/3508) +* Fixed a memory leak in `map.remove()` (by [@IvanSanchez](https://github.com/IvanSanchez)). [#3514](https://github.com/Leaflet/Leaflet/pull/3514) [#2718](https://github.com/Leaflet/Leaflet/issues/2718) +* Fixed a bug where layers control collapsed when hovering over a disabled radio button (by [@rowanwins](https://github.com/rowanwins)). [#3564](https://github.com/Leaflet/Leaflet/pull/3564) [#2771](https://github.com/Leaflet/Leaflet/issues/2771) [Leaflet#2771](https://github.com/Leaflet/Leaflet/issues/2771) +* Fixed GeoJSON not accepting null geometry (by [@pglotov](https://github.com/pglotov)). [#3585](https://github.com/Leaflet/Leaflet/pull/3585) +* Fixed occasional popup 1px horizontal offset (by [@patrickarlt](https://github.com/patrickarlt)). [#3587](https://github.com/Leaflet/Leaflet/pull/3587) [#3526](https://github.com/Leaflet/Leaflet/pull/3526) [#3586](https://github.com/Leaflet/Leaflet/issues/3586) [#3525](https://github.com/Leaflet/Leaflet/issues/3525) +* Fixed some inconsistencies in mouse events for Canvas vector layers (by [@wpf500](https://github.com/wpf500)). [#3590](https://github.com/Leaflet/Leaflet/pull/3590) [#3568](https://github.com/Leaflet/Leaflet/issues/3568) [#3618](https://github.com/Leaflet/Leaflet/pull/3618) +* Fixed scale control for non-earth CRS (by [@cmulders](https://github.com/cmulders)). [#3614](https://github.com/Leaflet/Leaflet/pull/3614) + +### Misc improvements + +* Improved the build system (`jake build`) to report gzipped library size. +* Added version name and commit number to Leaflet builds. [#2276](https://github.com/Leaflet/Leaflet/issues/2276) +* Added Leaflet logo in vector format as `src/images/logo.svg`. +* Added reference to Leaflet CSS in `package.json` (by [@bclinkinbeard](https://github.com/bclinkinbeard)). [#2432](https://github.com/Leaflet/Leaflet/pull/2432) +* Switched from JSHint to ESLint for checking code style and made the checks more strict. [#3176](https://github.com/Leaflet/Leaflet/pull/3176) +* Added a plugin guide section on module loaders and publishing plugins (by [@patrickarlt](https://github.com/patrickarlt)). [#2955](https://github.com/Leaflet/Leaflet/pull/2955) [Leaflet/Leaflet#2955](https://github.com/Leaflet/Leaflet/pull/2955) +* Fixed the build system to work in non-git Leaflet folder (by [@cschwarz](https://github.com/cschwarz)). [#2758](https://github.com/Leaflet/Leaflet/pull/2758) + + +## 0.7.7 (2015-10-26) + +* Fixed a regression that could sometimes cause tiles to disappear when pinch-zooming on iOS devices. +* Fixed a regression related to msPointer detection in IE10 (affecting Leaflet.draw and some other plugins) (by @danzel) #3842 #3839 #3804 +* Fixed a bug where a mouseout could fire after a vector element was removed (by @sambernet). #3849 #3829 +* Fixed touch interactions in Edge browser (by @mitchless & @Neorth). #3853 #3379 +* Fixed a bug where removing a layer group from a feature group would throw an error (by @Lambdac0re). #3869 + +Note tha we skipped 0.7.6 version for which we accidentally published a broken build to NPM. + + +## 0.7.5 (2015-09-02) + +* Fixed a regression that broke animation in Leaflet.markercluster. [#3796](https://github.com/Leaflet/Leaflet/issues/3796) + + +## 0.7.4 (2015-09-01) + +* Fixed a bug introduced by a recent Chrome update that caused the map not to react to interactions until all tiles are loaded. [#3689](https://github.com/Leaflet/Leaflet/issues/3689) +* Fixed a bug where tile layers were not respecting their `minZoom` or `maxZoom` options (by [@ivansanchez](https://github.com/ivansanchez)) [#3778](https://github.com/Leaflet/Leaflet/pull/3778) +* Improved detection of touch-capable web browsers, in particular fixing touch interactions in device emulation mode in Chrome and Firefox (by [@ivansanchez](https://github.com/ivansanchez)) [#3520](https://github.com/Leaflet/Leaflet/pull/3520) [#3710](https://github.com/Leaflet/Leaflet/pull/3710) +* Fixed a bug where tile layers with `maxNativeZoom` were not checking bounds properly (by [@jlaxon](https://github.com/jlaxon)) [#3415](https://github.com/Leaflet/Leaflet/pull/3152) +* Fixed a bug where popups were not remembering which layer originated them after calling `bindPopup(popup)` (by [@Eschon](https://github.com/Eschon)) [#3675](https://github.com/Leaflet/Leaflet/pull/3675) +* Fixed a race condition between markers and zoom animation (by [@perliedman](https://github.com/perliedman)) [#3152](https://github.com/Leaflet/Leaflet/pull/3152) +* Fixed a bug with `Map.fitBounds` padding (by [@bsstoner](https://github.com/bsstoner)). [#2489](https://github.com/Leaflet/Leaflet/issues/2489) +* Allow canvas paths to fire `dblclick` and `contextmenu` events (by [@ivansanchez](https://github.com/ivansanchez)) [#3482](https://github.com/Leaflet/Leaflet/pull/3482) +* Allow canvas filled polygons to use the `fillRule` option (by [@w8r](https://github.com/w8r)) [#3477](https://github.com/Leaflet/Leaflet/pull/3477) +* Allow canvas lines to use `lineCap` and `lineJoin` options (by [@northerneyes](https://github.com/northerneyes)) [#3156](https://github.com/Leaflet/Leaflet/pull/3156) +* Updated bower definitions to comply with best practices (by [@guptaso2](https://github.com/guptaso2)) [#2726](https://github.com/Leaflet/Leaflet/pull/2726) [#3448](https://github.com/Leaflet/Leaflet/pull/3448) + + +## 0.7.3 (2014-05-23) + +* Added proper **bower** and **component** support (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#2561](https://github.com/Leaflet/Leaflet/pull/2561) [#1903](https://github.com/Leaflet/Leaflet/issues/1903) +* Fixed a bug where dragging the map outside the window caused an error on FF. [#2610](https://github.com/Leaflet/Leaflet/issues/2610) +* Fixed a bug where some taps on Android where not working, often falsely perceived as drags (by [@axefrog](https://github.com/axefrog)). [#2503](https://github.com/Leaflet/Leaflet/pull/2503) +* Fixed a bug where clicks on Android were skipped when happened too fast. [#2303](https://github.com/Leaflet/Leaflet/issues/2303) +* Fixed a bug where calling `setView` (or similar methods) several times in succession could freeze the map. [#2521](https://github.com/Leaflet/Leaflet/issues/2521) [#2236](https://github.com/Leaflet/Leaflet/issues/2236) [#2485](https://github.com/Leaflet/Leaflet/issues/2485) +* Fixed a bug where `Control.Layers` wasn't properly removed (by [@jack-kerouac](https://github.com/jack-kerouac)). [#2569](https://github.com/Leaflet/Leaflet/pull/2569) +* Fixed a bug that caused `TileLayer` `load` event not to fire properly. [#2510](https://github.com/Leaflet/Leaflet/issues/2510) +* Fixed Canvas-based paths not triggering `remove` event when removed (by @adimitrov). [#2486](https://github.com/Leaflet/Leaflet/pull/2486) +* Fixed a bug where you could end up with fractional zoom after pinch-zooming in some cases (by [@danzel](https://github.com/danzel). [#2400](https://github.com/Leaflet/Leaflet/pull/2400) [#1943](https://github.com/Leaflet/Leaflet/issues/1934) + + +## 0.7.2 (2014-01-17) + +* Fixed a bug that appeared with **Chrome 32 update** that made all **mouse events shifted on scrolled pages**. [#2352](https://github.com/Leaflet/Leaflet/issues/2352) +* Fixed a bug that could break tile loading when using non-standard tile sizes. [#2288](https://github.com/Leaflet/Leaflet/issues/2288) +* Fixed a bug where `maxNativeZoom` option didn't work with TMS tile layers (by [@perliedman](https://github.com/perliedman)). [#2321](https://github.com/Leaflet/Leaflet/issues/2321) [#2314](https://github.com/Leaflet/Leaflet/issues/2314) + + +## 0.7.1 (2013-12-06) + +* Fixed a bug where pinch-zooming quickly could occasionally leave the map at a fractional zoom thus breaking tile loading (by [@danzel](https://github.com/danzel)). [#2269](https://github.com/Leaflet/Leaflet/pull/2269) [#2255](https://github.com/Leaflet/Leaflet/issues/2255) [#1934](https://github.com/Leaflet/Leaflet/issues/1934) +* Fixed tile flickering issues on some old Android 2/3 devices by disabling buggy hardware accelerated CSS there (by [@danzel](https://github.com/danzel)). [#2216](https://github.com/Leaflet/Leaflet/pull/2216) [#2198](https://github.com/Leaflet/Leaflet/issues/2198) +* Fixed a regression that sometimes led to an error when you started pinch-zoom as the first action on the map (by [@danzel](https://github.com/danzel)). [#2259](https://github.com/Leaflet/Leaflet/pull/2259) [#2256](https://github.com/Leaflet/Leaflet/issues/2256) +* Reverted `L.Util.template` optimizations to allow Leaflet to be used in eval-banning environments like browser extensions (performance gain was insignificant anyway) (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#2217](https://github.com/Leaflet/Leaflet/issues/2217) [#2209](https://github.com/Leaflet/Leaflet/issues/2209) [#1968](https://github.com/Leaflet/Leaflet/issues/1968) +* Fixed a regression where `Map` `invalidateSize` could lead to unexpected results when called before map initialization (by [@Zverik](https://github.com/Zverik)). [#2250](https://github.com/Leaflet/Leaflet/issues/2250) [#2249](https://github.com/Leaflet/Leaflet/issues/2249) +* Fixed a regression where `FeatureGroup` containing other group overwrote original `e.layer` value in mouse events (by [@gumballhead](https://github.com/gumballhead)). [#2253](https://github.com/Leaflet/Leaflet/pull/2253) [#2252](https://github.com/Leaflet/Leaflet/issues/2252) +* Fixed a regression where `CircleMarker` `setLatLngs` didn't return `this` (by [@radicalbiscuit](https://github.com/radicalbiscuit)). [#2206](https://github.com/Leaflet/Leaflet/pull/2206) + +## 0.7 (2013-11-18) + +### Improvements + +#### Usability improvements + +* Added **support for IE11 touch devices** (by [@danzel](https://github.com/danzel), [@DanielX2](https://github.com/DanielX2) and [@fnicollet](https://github.com/fnicollet)). [#2039](https://github.com/Leaflet/Leaflet/pull/2039) [#2066](https://github.com/Leaflet/Leaflet/pull/2066) [#2037](https://github.com/Leaflet/Leaflet/issues/2037) [#2102](https://github.com/Leaflet/Leaflet/issues/2102) +* Added shift-double-click to zoom out shortcut. [#2185](https://github.com/Leaflet/Leaflet/issues/2185) +* Significantly improved **controls design on mobile** devices. [#1868](https://github.com/Leaflet/Leaflet/issues/1868) [#2012](https://github.com/Leaflet/Leaflet/issues/2012) +* Fixed and improved IE7-8 control and popup styles. +* Made subtle improvements to control styles on desktop browsers. +* Improved keyboard nav support so that map doesn't loose focus when you click on a control (by [@jacobtoye](https://github.com/jacobtoye)). [#2150](https://github.com/Leaflet/Leaflet/issues/2150) [#2148](https://github.com/Leaflet/Leaflet/issues/2148) +* Improved `maxBounds` behavior: now it doesn't force higher minimal zoom, and anchors to max bounds edges properly when zooming (by [@kapouer](https://github.com/kapouer) and [@mourner](https://github.com/mourner)). [#2187](https://github.com/Leaflet/Leaflet/pull/2187) [#1946](https://github.com/Leaflet/Leaflet/pull/1946) [#2081](https://github.com/Leaflet/Leaflet/issues/2081) [#2168](https://github.com/Leaflet/Leaflet/issues/2168) [#1908](https://github.com/Leaflet/Leaflet/issues/1908) + +#### Map API improvements + +* Made `Map` `setView` `zoom` argument optional. [#2056](https://github.com/Leaflet/Leaflet/issues/2056) +* Added `maxZoom` option to `Map` `fitBounds`. [#2101](https://github.com/Leaflet/Leaflet/issues/2101) +* Added `Map` `bounceAtZoomLimits` option that makes the map bounce when you pinch-zoom past limits (it worked like this before, but now you can disable this) (by [@trevorpowell](https://github.com/trevorpowell)). [#1864](https://github.com/Leaflet/Leaflet/issues/1864) [#2072](https://github.com/Leaflet/Leaflet/pull/2072) +* Added `distance` property to `Map` and `Marker` `dragend` events. [#2158](https://github.com/Leaflet/Leaflet/issues/2158) [#872](https://github.com/Leaflet/Leaflet/issues/872) +* Added optional support for center-oriented scroll and double-click zoom (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1939](https://github.com/Leaflet/Leaflet/issues/1939) +* Added `timestamp` to `Map` `locationfound` event. [#584](https://github.com/Leaflet/Leaflet/pull/584) +* Improved `Map` `invalidateSize` to call `moveend` immediately unless given `debounceMoveend: true` option (by [@jfirebaugh](https://github.com/jfirebaugh)). [#2181](https://github.com/Leaflet/Leaflet/issues/2181) + +#### TileLayer API improvements + +* Added `TileLayer` `maxNativeZoom` option that allows displaying tile layers on zoom levels above their maximum by **upscaling tiles**. [#1802](https://github.com/Leaflet/Leaflet/issues/1802) [#1798](https://github.com/Leaflet/Leaflet/issues/1798) +* Added `TileLayer` `tileloadstart` event (by [@tmcw](https://github.com/tmcw)). [#2142](https://github.com/Leaflet/Leaflet/pull/2142) [#2140](https://github.com/Leaflet/Leaflet/issues/2140) +* Improved `TileLayer` world size (used for wrapping and limiting tiles) to be derived from CRS instead of hardcoded, making it easier to use with custom projections (by [@perliedman](https://github.com/perliedman)). [#2160](https://github.com/Leaflet/Leaflet/pull/2160) + +#### Marker API improvements + +* Added CSS classes to draggable markers for easier customization (by [@snkashis](https://github.com/snkashis)). [#1902](https://github.com/Leaflet/Leaflet/issues/1902) [#1916](https://github.com/Leaflet/Leaflet/issues/1916) +* Added `Marker` `add` event (by [@tohaocean](https://github.com/tohaocean)). [#1942](https://github.com/Leaflet/Leaflet/issues/1942) +* Added `Marker` `getPopup` method (by [@scottharvey](https://github.com/scottharvey)). [#618](https://github.com/Leaflet/Leaflet/issues/618) [#1197](https://github.com/Leaflet/Leaflet/pull/1197) +* Added `Marker` `alt` option for adding `alt` text to markers (by [@jimmytidey](https://github.com/jimmytidey)). [#2112](https://github.com/Leaflet/Leaflet/pull/2112) + +#### Vector layers API improvements + +* Added `Path` `className` option for adding custom class names to vector layers. +* Added `Path` `lineCap` and `lineJoin` options (by [@palewire](https://github.com/palewire)). [#1843](https://github.com/Leaflet/Leaflet/issues/1843) [#1863](https://github.com/Leaflet/Leaflet/issues/1863) [#1881](https://github.com/Leaflet/Leaflet/issues/1881) +* Added ability to pass vector options to `GeoJSON` (by [@kapouer](https://github.com/kapouer)). [#2075](https://github.com/Leaflet/Leaflet/pull/2075) +* Improved `Polygon` `setLatLngs` to also accept holes (by [@aparshin](https://github.com/aparshin)). [#2095](https://github.com/Leaflet/Leaflet/pull/2095) [#1518](https://github.com/Leaflet/Leaflet/issues/1518) +* Added `GeoJSON` 3D format support and optional `altitude` argument to `LatLng` constructor (by [@Starefossen](https://github.com/Starefossen)). [#1822](https://github.com/Leaflet/Leaflet/pull/1822) +* Added `MultiPolygon` and `MultiPolyline` `openPopup` method. [#2046](https://github.com/Leaflet/Leaflet/issues/2046) + +#### Popup API improvements + +* Added `Popup` `update` method. [#1959](https://github.com/Leaflet/Leaflet/issues/1959) +* Added `Popup` `autoPanPaddingTopLeft` and `autoPanPaddingBottomRight` options (by [@albburtsev](https://github.com/albburtsev)). [#1972](https://github.com/Leaflet/Leaflet/issues/1972) [#1588](https://github.com/Leaflet/Leaflet/issues/1588) +* Added `Popup` `getContent` method. [#2100](https://github.com/Leaflet/Leaflet/issues/2100) +* Added `Popup` `getLatLng` method (by [@AndreyGeonya](https://github.com/AndreyGeonya)). [#2097](https://github.com/Leaflet/Leaflet/pull/2097) + +#### Misc API improvements + +* Added `ImageOverlay` `setUrl` and `getAttribution` methods and `attribution` option (by [@stsydow](https://github.com/stsydow)). [#1957](https://github.com/Leaflet/Leaflet/issues/1957) [#1958](https://github.com/Leaflet/Leaflet/issues/1958) +* Added localization support for the zoom control (by [@Danielku15](https://github.com/Danielku15)). [#1953](https://github.com/Leaflet/Leaflet/issues/1953) [#1643](https://github.com/Leaflet/Leaflet/issues/1643) [#1953](https://github.com/Leaflet/Leaflet/pull/1953) +* Significantly improved `L.Util.template` performance (affects `L.TileLayer`) by introducing cached template compilation (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#1969](https://github.com/Leaflet/Leaflet/issues/1969) [#1968](https://github.com/Leaflet/Leaflet/issues/1968) [#1554](https://github.com/Leaflet/Leaflet/issues/1554) +* Added `CRS` `getSize` for getting the world size in pixels (by [@perliedman](https://github.com/perliedman)). [#2160](https://github.com/Leaflet/Leaflet/pull/2160) +* Added `leaflet-drag-target` CSS class to an element under cursor when dragging for more flexible customization. [#2164](https://github.com/Leaflet/Leaflet/issues/2164) [#1902](https://github.com/Leaflet/Leaflet/issues/1902) +* Improved `L.DomUtil` `addClass`, `removeClass`, `hasClass` methods performance and fixed it to work with SVG elements. [#2164](https://github.com/Leaflet/Leaflet/issues/2164) + +#### Dev workflow improvements + +* Added an [official FAQ](https://github.com/Leaflet/Leaflet/blob/master/FAQ.md). +* Cleaned up and moved old IE styles to `leaflet.css` and removed `leaflet.ie.css`, so **no need for IE conditional comment** when including Leaflet now. [#2159](https://github.com/Leaflet/Leaflet/issues/2159) +* Added `leaflet-oldie` CSS class to map container in IE7-8 for easier styling. [#2159](https://github.com/Leaflet/Leaflet/issues/2159) +* Officially **dropped support for IE6**. Nobody cares anyway, and Leaflet should still be accessible on it. [#2159](https://github.com/Leaflet/Leaflet/issues/2159) +* Improved the build system to check JS errors in spec files. [#2151](https://github.com/Leaflet/Leaflet/issues/2151) +* Fixed `jake` command to run tests before building the source. [#2151](https://github.com/Leaflet/Leaflet/issues/2151) +* Switched the main file in `package.json` to unminified version for NPM/Browserify (by [@icetan](https://github.com/icetan)). [#2109](https://github.com/Leaflet/Leaflet/pull/2109) + +### Bugfixes + +#### 0.6 regression fixes + +* Fixed a **memory leak in iOS7** that could crash Safari when handling lots of objects (e.g. 1000 markers) (by [@danzel](https://github.com/danzel)). [#2149](https://github.com/Leaflet/Leaflet/pull/2149) [#2122](https://github.com/Leaflet/Leaflet/issues/2122) +* Fixed a bug that caused lag at the beginning of panning in Chrome (by [@jfirebaugh](https://github.com/jfirebaugh)). [#2163](https://github.com/Leaflet/Leaflet/issues/2163) +* Fixed a regression that made the layers control unscrollable in Firefox. [#2029](https://github.com/Leaflet/Leaflet/issues/2029) +* Fixed a regression that broke `worldCopyJump: true` option (by [@fastrde](https://github.com/fastrde)). [#1904](https://github.com/Leaflet/Leaflet/issues/1904) [#1831](https://github.com/Leaflet/Leaflet/issues/1831) [#1982](https://github.com/Leaflet/Leaflet/issues/1982) +* Fixed a regression where a first map click after popup close button click was ignored (by [@fastrde](https://github.com/fastrde)). [#1537](https://github.com/Leaflet/Leaflet/issues/1537) [#1963](https://github.com/Leaflet/Leaflet/issues/1963) [#1925](https://github.com/Leaflet/Leaflet/issues/1925) +* Fixed a regression where `L.DomUtil.getMousePosition` would throw an error if container argument not provided (by [@scooterw](https://github.com/scooterw)). [#1826](https://github.com/Leaflet/Leaflet/issues/1826) [#1928](https://github.com/Leaflet/Leaflet/issues/1928) [#1926](https://github.com/Leaflet/Leaflet/issues/1926) +* Fixed a regression with vector layers positioning when zooming on IE10+ touch devices (by [@danzel](https://github.com/danzel)). [#2002](https://github.com/Leaflet/Leaflet/issues/2002) [#2000](https://github.com/Leaflet/Leaflet/issues/2000) +* Fixed a regression with `maxBounds` behaving weirdly on panning inertia out of bounds. [#2168](https://github.com/Leaflet/Leaflet/issues/2168) + +#### General bugfixes + +* Fixed a bug where the map could freeze if centered and immediately recentered on initialization. [#2071](https://github.com/Leaflet/Leaflet/issues/2071) +* Fixed a bug where all maps except the first one on a page didn't track window resize. [#1980](https://github.com/Leaflet/Leaflet/issues/1980) +* Fixed a bug where tiles in `EPSG:3395` projection were shifted (by [@aparshin](https://github.com/aparshin)). [#2020](https://github.com/Leaflet/Leaflet/issues/2020) +* Fixed a bug where scale control displayed wrong scale when on pages with `box-sizing: border-box`. +* Fixed a bug where zoom control button didn't appear as disabled if map was initialized at the zoom limit. [#2083](https://github.com/Leaflet/Leaflet/issues/2083) +* Fixed a bug where box zoom also triggered a map click event (by [@fastrde](https://github.com/fastrde)). [#1951](https://github.com/Leaflet/Leaflet/issues/1951) [#1884](https://github.com/Leaflet/Leaflet/issues/1884) +* Fixed a bug where shift-clicking on a map immediately after a drag didn't trigger a click event (by [@fastrde](https://github.com/fastrde)). [#1952](https://github.com/Leaflet/Leaflet/issues/1952) [#1950](https://github.com/Leaflet/Leaflet/issues/1950) +* Fixed a bug where content was updated twice when opening a popup. [#2137](https://github.com/Leaflet/Leaflet/issues/2137) +* Fixed a bug that could sometimes cause infinite panning loop when using `maxBounds` (by [@kapouer](https://github.com/kapouer) and [@mourner](https://github.com/mourner)). [#2187](https://github.com/Leaflet/Leaflet/pull/2187) [#1946](https://github.com/Leaflet/Leaflet/pull/1946) [#2081](https://github.com/Leaflet/Leaflet/issues/2081) [#2168](https://github.com/Leaflet/Leaflet/issues/2168) [#1908](https://github.com/Leaflet/Leaflet/issues/1908) + +#### Browser bugfixes + +* Fixed a bug where keyboard `+` no longer zoomed the map on FF 22+ (by [@fastrde](https://github.com/fastrde)). [#1943](https://github.com/Leaflet/Leaflet/issues/1943) [#1981](https://github.com/Leaflet/Leaflet/issues/1981) +* Fixed a bug where calling `Map` `remove` throwed an error in IE6-8. [#2015](https://github.com/Leaflet/Leaflet/issues/2015) +* Fixed a bug where `isArray` didn't work in rare cases in IE9. [#2077](https://github.com/Leaflet/Leaflet/issues/2077) +* Fixed a bug where FF sometimes produced console warnings when animating markers. [#2090](https://github.com/Leaflet/Leaflet/issues/2090) +* Fixed a bug where mouse wasn't handled correctly on RTL pages in some cases (by [@danzel](https://github.com/danzel)). [#1986](https://github.com/Leaflet/Leaflet/issues/1986) [#2136](https://github.com/Leaflet/Leaflet/pull/2136) + +#### Mobile bugfixes + +* Fixed a bug where tiles could **disappear after zooming on Chrome 30+ for Android** (by [@danzel](https://github.com/danzel)). [#2152](https://github.com/Leaflet/Leaflet/pull/2152) [#2078](https://github.com/Leaflet/Leaflet/issues/2078) +* Fixed a bug on IE10+ touch where pinch-zoom also caused click (by [@danzel](https://github.com/danzel)). [#2117](https://github.com/Leaflet/Leaflet/pull/2117) [#2094](https://github.com/Leaflet/Leaflet/issues/2094) +* Fixed a bug on IE10+ touch where controls didn't loose the pressed state after tapping (by [@danzel](https://github.com/danzel)). [#2111](https://github.com/Leaflet/Leaflet/pull/2111) [#2103](https://github.com/Leaflet/Leaflet/issues/2103) +* Fixed a bug where clicking on layers control labels on iOS throwed an error (by [@olemarkus](https://github.com/olemarkus) and [@dagjomar](https://github.com/dagjomar)). [#1984](https://github.com/Leaflet/Leaflet/issues/1984) [#1989](https://github.com/Leaflet/Leaflet/issues/1989) + +#### Map API bugfixes + +* Fixed a bug where `Map` `getCenter` returned old result after map container size changed (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1940](https://github.com/Leaflet/Leaflet/issues/1940) [#1919](https://github.com/Leaflet/Leaflet/issues/1919) +* Fixed `Map` `invalidateSize` rounding issues when changing map size by an odd pixel amount (by [@russelldavis](https://github.com/russelldavis)). [#1931](https://github.com/Leaflet/Leaflet/issues/1931) +* Fixed a bug where `Map` `removeLayer` didn't return `this` in a corner case (by [@jfirebaugh](https://github.com/jfirebaugh)). +* Fixed a bug where calling `Map` `setZoom` before `setView` would throw an error. [#1449](https://github.com/Leaflet/Leaflet/issues/1449) + +#### Layers API bugfixes + +* Fixed a bug where `Popup` `setLatLng` unnecessarily reset content and updated layout; works much faster now. [#2167](https://github.com/Leaflet/Leaflet/issues/2167) +* Fixed a bug where `toGeoJSON` of layers originated from GeoJSON GeometryCollection and MultiPoint didn't work properly (wasn't round-tripped). [#1956](https://github.com/Leaflet/Leaflet/issues/1956) +* Fixed `GeoJSON` dependencies in build configuration that could lead to a broken custom build in some situations (by [@alubchuk](https://github.com/alubchuk)). [#1909](https://github.com/Leaflet/Leaflet/issues/1909) +* Fixed a bug where `CircleMarker` popup placement wasn't updated after calling `setLatLng` (by [@snkashis](https://github.com/snkashis)). [#1921](https://github.com/Leaflet/Leaflet/issues/1921) [#1927](https://github.com/Leaflet/Leaflet/issues/1927) +* Fixed a bug where popup anchor wasn't updated on `Marker` `setIcon` (by [@snkashis](https://github.com/snkashis)). [#1874](https://github.com/Leaflet/Leaflet/issues/1874) [#1891](https://github.com/Leaflet/Leaflet/issues/1891) +* Fixed a bug with GeoJSON not throwing a descriptive error if a polygon has zero length inner ring (by [@snkashis](https://github.com/snkashis)). [#1917](https://github.com/Leaflet/Leaflet/issues/1917) [#1918](https://github.com/Leaflet/Leaflet/issues/1918) +* Fixed a bug where `FeatureGroup` would break when using non-evented children layers (by [@tmcw](https://github.com/tmcw)). [#2032](https://github.com/Leaflet/Leaflet/pull/2032) [#1962](https://github.com/Leaflet/Leaflet/issues/1962) +* Fixed a bug where `CircleMarker` `getRadius` would always return `null`. [#2016](https://github.com/Leaflet/Leaflet/issues/2016) [#2017](https://github.com/Leaflet/Leaflet/pull/2017) +* Fixed a bug where `TileLayer.WMS` didn't work with WMS 1.3 & EPSG4326 projection (by [@Bobboya](https://github.com/Bobboya)). [#1897](https://github.com/Leaflet/Leaflet/pull/1897) +* Fixed a bug where `FeatureGroup` events `e.layer` was sometimes empty in old IE. [#1938](https://github.com/Leaflet/Leaflet/issues/1938) + +#### Misc API bugfixes + +* Fixed a bug where `L.latLngBounds` didn't accept simple object `LatLng` form (by [@Gnurfos](https://github.com/Gnurfos)). [#2025](https://github.com/Leaflet/Leaflet/issues/2025) [#1915](https://github.com/Leaflet/Leaflet/issues/1915) +* Fixed a bug where `L.Util.tempalate` wouldn't work with double quotes in the string (by [@jieter](https://github.com/jieter)). [#1968](https://github.com/Leaflet/Leaflet/issues/1968) [#2121](https://github.com/Leaflet/Leaflet/pull/2121) [#2120](https://github.com/Leaflet/Leaflet/issues/2120) +* Fixed a bug where attribution control that was added to a map after attributed layers didn't have the corresponding attributions (by [@snkashis](https://github.com/snkashis)). [#2177](https://github.com/Leaflet/Leaflet/issues/2177) [#2178](https://github.com/Leaflet/Leaflet/pull/2178) + + +## 0.6.4 (2013-07-25) + +* Fixed a regression where `fitBounds` and `setMaxBounds` could freeze the browser in some situations. [#1895](https://github.com/Leaflet/Leaflet/issues/1895) [1866](https://github.com/Leaflet/Leaflet/issues/1866) +* Fixed a bug where click on a map on a page with horizontal scroll caused the page to scroll right (by [@mstrelan](https://github.com/mstrelan)). [#1901](https://github.com/Leaflet/Leaflet/issues/1901) + +## 0.6.3 (2013-07-17) + +### Regression fixes + +* Fixed a regression where mouse interaction had incorrect coordinates in some map positioning cases (by [@scooterw](https://github.com/scooterw)). [#1826](https://github.com/Leaflet/Leaflet/issues/1826) [#1684](https://github.com/Leaflet/Leaflet/issues/1684) [#1745](https://github.com/Leaflet/Leaflet/issues/1745) [#1](https://github.com/Leaflet/Leaflet/issues/1) +* Fixed a regression that prevented the map from responding to drag on areas covered with `ImageOverlay` (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1821](https://github.com/Leaflet/Leaflet/issues/1821) +* Fixed a regression where `layerremove` and `layeradd` were fired before the corresponding action finishes (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1846](https://github.com/Leaflet/Leaflet/issues/1846) +* Fixed a regression with `worldCopyJump: true` breaking the map on small zoom levels (by [@danzel](https://github.com/danzel)). [#1831](https://github.com/Leaflet/Leaflet/issues/1831) +* Fixed a regression where `Marker` shadow didn't animate on zoom after using `setIcon`. [#1768](https://github.com/Leaflet/Leaflet/issues/1768) +* Fixed a regression where the map would stuck when trying to animate zoom before any tile layers are added to the map. [#1484](https://github.com/Leaflet/Leaflet/issues/1484) [#1845](https://github.com/Leaflet/Leaflet/issues/1845) +* Fixed a regression with the layers control and popups closing on inside click in IE < 9. [#1850](https://github.com/Leaflet/Leaflet/issues/1850) +* Fixed a regression where scrolled popup content woudln't scroll in FF (by [@jfirebaugh](https://github.com/jfirebaugh)). + +### Bug fixes + +* Fixed vector feature flickering on Safari Mac for screen < 2000px. [#902](https://github.com/Leaflet/Leaflet/issues/902) +* Fixed a bug where `GeoJSON` ignored non-feature geometries passed in an array. [#1840](https://github.com/Leaflet/Leaflet/issues/1840) +* Fixed a bug where `Map` `minZoom` and `maxZoom` didn't always override values derived from the added tile layers. [1848](https://github.com/Leaflet/Leaflet/issues/1848) +* Fixed a bug where `TileLayer.Canvas` wasn't immediately redrawn when `redraw` is called (by [@tofferrosen](https://github.com/tofferrosen)). [#1797](https://github.com/Leaflet/Leaflet/issues/1797) [#1817](https://github.com/Leaflet/Leaflet/issues/1817) +* Fixed a bug where `FeatureGroup` still fired `layerremove` event on `removeLayer` even if the given layer wan't present in the group (by (by [@danzel](https://github.com/danzel))). [#1847](https://github.com/Leaflet/Leaflet/issues/1847) [#1858](https://github.com/Leaflet/Leaflet/issues/1858) +* Fixed a bug where `Marker` `setOpacity` wasn't returning the marker (by [@freepius44](https://github.com/freepius44)). [#1851](https://github.com/Leaflet/Leaflet/issues/1851) +* Fixed a bug where removing the map element from the DOM before panning transition has finished could keep a setInterval loop running forever (by [@rutkovsky](https://github.com/rutkovsky)). [#1825](https://github.com/Leaflet/Leaflet/issues/1825) [#1856](https://github.com/Leaflet/Leaflet/issues/1856) +* Fixed mobile styles to apply to `leaflet-bar` elements. + +### Improvements + +* Added ability to pass zoom/pan animation options to `setMaxBounds` (by [@davidjb](http://git.io/djb)). [#1834](https://github.com/Leaflet/Leaflet/pull/1834) +* Added `MultiPolyline` and `MultiPolygon` `getLatLngs` method. [#1839](https://github.com/Leaflet/Leaflet/issues/1839) + +### Dev Workflow improvements + +* Leaflet builds (*.js files in the `dist` folder) were removed from the repo and are now done automatically on each commit for `master` and `stable` branches by [Travis CI](travis-ci.org/Leaflet/Leaflet). The download links are on the [Leafet download page](http://leafletjs.com/download.html). + +## 0.6.2 (2013-06-28) + + * Fixed a bug that caused wrong tile layers stacking order when using opacity < 1 (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1804](https://github.com/Leaflet/Leaflet/issues/1804) [#1790](https://github.com/Leaflet/Leaflet/issues/1790) [#1667](https://github.com/Leaflet/Leaflet/issues/1667) + * Fixed a regression that caused tiles selection when double-clicking absolutely positioned maps with vector layers in it in Firefox (WTF!) (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1807](https://github.com/Leaflet/Leaflet/issues/1807) + * Fixed a regression with a wrong cursor when dragging a map with vector layers, and tiles becoming selected on double click (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1800](https://github.com/Leaflet/Leaflet/issues/1800) + * Fixed a regression that caused flickering of tiles near map border on zoom animation in Chrome. + +## 0.6.1 (2013-06-27) + + * Fixed a regression with mouse wheel zooming too fast on Firefox (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1788](https://github.com/Leaflet/Leaflet/issues/1788) + * Fixed a regression with broken zooming on maps with EPSG3395 projection. [#1796](https://github.com/Leaflet/Leaflet/issues/1796) + * Fixed a bug where zoom buttons inherited Bootstrap link hover styles. [#1791](https://github.com/Leaflet/Leaflet/issues/1791) + +## 0.6 (2013-06-26) + +### Breaking changes + + * Moved polyline editing code into [Leaflet.draw](https://github.com/Leaflet/Leaflet.draw) plugin (where it fits much better along with all other editing and drawing handlers). The API remains the same. + * Dropped support for environments that augment `Object.prototype` (luckily it's a thing of the past nowadays). + * `Map` `invalidateSize` no longer fires `move` and `moveend` events if the map size didn't change. [#1819](https://github.com/Leaflet/Leaflet/issues/1819) + +### Improvements + +#### Usability and performance improvements + + * **Improved zoom control design** - cleaner, simpler, more accessible (mostly by [@jacobtoye](https://github.com/jacobtoye)). [#1313](https://github.com/Leaflet/Leaflet/issues/1313) + * Updated `Control.Layers` icon (designed by Volker Kinkelin), added retina version and SVG source. [#1739](https://github.com/Leaflet/Leaflet/issues/1739) + * Added keyboard accessibility to markers (you can now tab to them and press enter for click behavior). [#1355](https://github.com/Leaflet/Leaflet/issues/1355) + * Improved `TileLayer` zoom animation to eliminate flickering in case one tile layer on top of another or when zooming several times quickly (by [@mourner](https://github.com/mourner) with lots of fixes from [@danzel](https://github.com/danzel)). [#1140](https://github.com/Leaflet/Leaflet/issues/1140) [#1437](https://github.com/Leaflet/Leaflet/issues/1437) [#52](https://github.com/Leaflet/Leaflet/issues/52) + * Subtly improved default popup styles + * Improved attribution control to be much less obtrusive (no "powered by", just a Leaflet link). You can still remove the prefix with `map.attributionControl.setPrefix('')` if you need. + * Improved zoom behavior so that there's no drift of coordinates when you change zoom back and forth without panning. [#426](https://github.com/Leaflet/Leaflet/issues/426) + * Improved double click behavior to zoom while keeping the clicked point fixed (by [@ansis](https://github.com/ansis)). [#1582](https://github.com/Leaflet/Leaflet/issues/1582) + * Improved dragging behavior to not get stuck if mouse moved outside of an iframe containing the map (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1277](https://github.com/Leaflet/Leaflet/issues/1277) [#1782](https://github.com/Leaflet/Leaflet/issues/1782) [#1786](https://github.com/Leaflet/Leaflet/issues/1786) + * Improved box zoom to be cancelable by pressing Escape (by [@yohanboniface](https://github.com/yohanboniface)). [#1438](https://github.com/Leaflet/Leaflet/issues/1438) + * Improved `Marker` popups to close on marker click if opened (by [@popox](https://github.com/popox)). [#1761](https://github.com/Leaflet/Leaflet/issues/1761) + * Significantly improved mass layer removal performance (by [@jfgirard](https://github.com/jfgirard) with fixes from [@danzel](https://github.com/danzel)). [#1141](https://github.com/Leaflet/Leaflet/pull/1141) [#1514](https://github.com/Leaflet/Leaflet/pull/1514) + +#### API improvements + +##### Layers API improvements + + * Added `toGeoJSON` method to various layer types, allowing you to **save your Leaflet layers as GeoJSON**. (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1462](https://github.com/Leaflet/Leaflet/issues/1462) [#712](https://github.com/Leaflet/Leaflet/issues/712) [#1779](https://github.com/Leaflet/Leaflet/issues/1779) + * Added `GeoJSON` `coordsToLatLng` option for dealing with GeoJSON that has non-WGS84 coords (thanks to [@moonlite](https://github.com/moonlite)). [#888](https://github.com/Leaflet/Leaflet/issues/888) [#886](https://github.com/Leaflet/Leaflet/issues/886) + * Improved `Marker` to reuse icon DOM elements when changing icons on the fly (e.g. fixes problems when changing icon on mouse hover) (by [@robpvn](https://github.com/robpvn) & [@danzel](https://github.com/danzel)). [#1726](https://github.com/Leaflet/Leaflet/issues/1726) [#561](https://github.com/Leaflet/Leaflet/issues/561) [#1753](https://github.com/Leaflet/Leaflet/issues/1753) [#1754](https://github.com/Leaflet/Leaflet/pull/1754) + * Added `latlng` property to `Marker` mouse event data. [#1613](https://github.com/Leaflet/Leaflet/issues/1613) + * Added `LayerGroup` `hasLayer` method (by [@rvlasveld](https://github.com/rvlasveld)). [#1282](https://github.com/Leaflet/Leaflet/issues/1282) [#1300](https://github.com/Leaflet/Leaflet/pull/1300) + * Added `LayerGroup` `getLayers` method (by [@tmcw](https://github.com/tmcw)). [#1469](https://github.com/Leaflet/Leaflet/pull/1469) + * Added `LayerGroup` `getLayer` method (by [@gumballhead](https://github.com/gumballhead)). [#1650](https://github.com/Leaflet/Leaflet/pull/1650) + * Improved `LayerGroup` `removeLayer` method to also accept layer `id` (by [@gumballhead](https://github.com/gumballhead)). [#1642](https://github.com/Leaflet/Leaflet/pull/1642) + * Added `Path` `pointerEvents` option for setting pointer-events on SVG-powered vector layers (by [@inpursuit](https://github.com/inpursuit)). [#1053](https://github.com/Leaflet/Leaflet/pull/1053) + * Improved `Polygon` to filter out last point if it's equal to the first one (to fix GeoJSON polygon issues) (by [@snkashis](https://github.com/snkashis)). [#1153](https://github.com/Leaflet/Leaflet/pull/1153) [#1135](https://github.com/Leaflet/Leaflet/issues/1135) + * Improved paths with `clickable: false` to allow mouse events to pass through to objects underneath (by [@snkashis](https://github.com/snkashis)). [#1384](https://github.com/Leaflet/Leaflet/pull/1384) [#1281](https://github.com/Leaflet/Leaflet/issues/1281) + * Improved `L.Util.template` (and correspondingly url-related `TileLayer` options) to support functions for data values (by [@olegsmith](https://github.com/olegsmith)). [#1554](https://github.com/Leaflet/Leaflet/pull/1554) + * Added `TileLayer` `getContainer` method (by [@tmcw](https://github.com/tmcw)). [#1433](https://github.com/Leaflet/Leaflet/pull/1433) + * Fixed `TileLayer.Canvas` `redraw` method chaining (by [@jieter](https://github.com/jieter)). [#1287](https://github.com/Leaflet/Leaflet/pull/1287) + * Added `TileLayer.WMS` `crs` option to be able to use WMS of CRS other than the map CRS (by [@kengu](https://github.com/kengu)). [#942](https://github.com/Leaflet/Leaflet/issues/942) [#945](https://github.com/Leaflet/Leaflet/issues/945) + * Added `popupopen` and `popupclose` events to various layers (by [@Koc](https://github.com/Koc)). [#738](https://github.com/Leaflet/Leaflet/pull/738) + * Added `Popup` `keepInView` option (thanks to [@lapo-luchini](https://github.com/lapo-luchini)) that prevents the popup from going off-screen while it's opened. [#1308](https://github.com/Leaflet/Leaflet/pull/1308) [#1052](https://github.com/Leaflet/Leaflet/issues/1052) + * Added `Marker` `togglePopup` method (by [@popox](https://github.com/popox)). [#1761](https://github.com/Leaflet/Leaflet/issues/1761) + * Added `Popup` `closeOnClick` option that overrides the same `Map` option for specific popups (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1669](https://github.com/Leaflet/Leaflet/issues/1669) + * Improved `Marker` and `Path` `bindPopup` method to also accept `Popup` objects (by [@snkashis](https://github.com/snkashis)). [#1385](https://github.com/Leaflet/Leaflet/pull/1385) [#1208](https://github.com/Leaflet/Leaflet/issues/1208) [#1402](https://github.com/Leaflet/Leaflet/pull/1402) + * Added `Marker` `setPopupContent` method (by [@snkashis](https://github.com/snkashis)). [#1373](https://github.com/Leaflet/Leaflet/pull/1373) + +##### Map API improvements + + * Improved all view changing methods of `Map` (`setView`, `panTo`, `setZoom`, `fitBounds`, etc.) to accept an options object, including the ability to precisely control zoom/pan animations they cause (force disable/enable, etc.). [#1617](https://github.com/Leaflet/Leaflet/pull/1617) [#1616](https://github.com/Leaflet/Leaflet/issues/1616) [#340](https://github.com/Leaflet/Leaflet/issues/340) [#483](https://github.com/Leaflet/Leaflet/issues/483) [#1164](https://github.com/Leaflet/Leaflet/issues/1164) [#1420](https://github.com/Leaflet/Leaflet/issues/1420) + * Improved `Map` `fitBounds` method to accept `padding` (or `paddingTopLeft` and `paddingBottomRight`) options, allowing you to zoom to an area with a certain padding in pixels (usually left for controls). [#859](https://github.com/Leaflet/Leaflet/issues/859) + * Improved `Map` `invalidateSize` to accept options object (`animate` and `pan`, the latter controls if it pans the map on size change). (by [@jacobtoye](https://github.com/jacobtoye) and [@mourner](https://github.com/mourner)). [#1766](https://github.com/Leaflet/Leaflet/issues/1766) [#1767](https://github.com/Leaflet/Leaflet/issues/1767) + * Added `Map` `setZoomAround` method for zooming while keeping a certain point fixed (used by scroll and double-click zooming). [#1157](https://github.com/Leaflet/Leaflet/issues/1157) + * Added `Map` `remove` method to properly destroy the map and clean up all events, and added corresponding `unload` event (by [@jfirebaugh](https://github.com/jfirebaugh) and [@mourner](https://github.com/mourner)). [#1434](https://github.com/Leaflet/Leaflet/issues/1434) [#1101](https://github.com/Leaflet/Leaflet/issues/1101) [#1621](https://github.com/Leaflet/Leaflet/issues/1621) + * Added `Map` `tap` handler that now contains all mobile hacks for enabling quick taps and long holds and `tapTolerance` option specifying the number of pixels you can shift your finger for click to still fire. + * Added `Map` `zoomAnimationThreshold` for setting the max zoom difference with which zoom animation can occur. [#1377](https://github.com/Leaflet/Leaflet/issues/1377) + * Improved `Map` `openPopup` method to also accept `(content, latlng)` signature as a shortcut. + * Improved `Map` `closePopup` method to optionally accept a popup object to close. [#1641](https://github.com/Leaflet/Leaflet/issues/1641) + * Improved `Map` `stopLocate` method to abort resetting map view if calling `locate` with `setView` option. [#747](https://github.com/Leaflet/Leaflet/issues/747) + * Improved `Map` to throw exception if the specified container id is not found (by [@tmcw](htts://github.com/tmcw)). [#1574](https://github.com/Leaflet/Leaflet/pull/1574) + * Improved `Map` `locationfound` event to pass all location data (heading, speed, etc.). [#984](https://github.com/Leaflet/Leaflet/issues/984) [#584](https://github.com/Leaflet/Leaflet/issues/584) [#987](https://github.com/Leaflet/Leaflet/issues/987) [#1028](https://github.com/Leaflet/Leaflet/issues/1028) + * Added `Map` `resize` event. [#1564](https://github.com/Leaflet/Leaflet/issues/1564) + * Added `Map` `zoomlevelschange` event that triggers when the current zoom range (min/max) changes (by [@moonlite](https://github.com/moonlite)). [#1376](https://github.com/Leaflet/Leaflet/pull/1376) + +##### Controls API improvements + + * Added **generic toolbar classes** for reuse by plugin developers (used by zoom control). + * Added `Map` `baselayerchange`, `overlayadd` and `overlayremove` events fired by `Control.Layers` (by [@calvinmetcalf](https://github.com/calvinmetcalf) and [@Xelio](https://github.com/Xelio)). [#1286](https://github.com/Leaflet/Leaflet/issues/1286) [#1634](https://github.com/Leaflet/Leaflet/issues/1634) + * Added `Control` `getContainer` method. [#1409](https://github.com/Leaflet/Leaflet/issues/1409) + +##### Misc API improvements + + * Made Leaflet classes compatible with **CoffeeScript class inheritance** syntax (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#1345](https://github.com/Leaflet/Leaflet/pull/1345) [#1314](https://github.com/Leaflet/Leaflet/issues/1314) + * Added `cleanAllEventListeners` method (aliased to `off` without arguments) to all events-enabled objects (by [@iirvine](https://github.com/iirvine)). [#1599](https://github.com/Leaflet/Leaflet/issues/1599) + * Added `addOneTimeEventListener` method (aliased to `once`) to all events-enabled objects (by [@iirvine](https://github.com/iirvine)). [#473](https://github.com/Leaflet/Leaflet/issues/473) [#1596](https://github.com/Leaflet/Leaflet/issues/1596) + * Added ability to pass coordinates as simple objects (`{lat: 50, lon: 30}` or `{lat: 50, lng: 30}`). [#1412](https://github.com/Leaflet/Leaflet/issues/1412) + * Added `LatLngBounds` `getNorth`, `getEast`, `getSouth`, `getWest` methods (by [@yohanboniface](https://github.com/yohanboniface)). [#1318](https://github.com/Leaflet/Leaflet/issues/1318) + * Added `AMD` support (Leaflet now registers itself as a `leaflet` AMD module) (with fixes from [@sheppard](https://github.com/sheppard)). [#1364](https://github.com/Leaflet/Leaflet/issues/1364) [#1778](https://github.com/Leaflet/Leaflet/issues/1778) + * Added `L.Util.trim` function (by [@kristerkari](https://github.com/kristerkari)). [#1607](https://github.com/Leaflet/Leaflet/pull/1607) + +#### Development workflow improvements + + * Switched from Jasmine to [Mocha](http://visionmedia.github.io/mocha/) with Expect.js (matchers) and Sinon (spies) for tests (by [@tmcw](https://github.com/tmcw) & [@jfirebaugh](https://github.com/jfirebaugh)). [#1479](https://github.com/Leaflet/Leaflet/issues/1479) + * Added [Karma](http://karma-runner.github.io) integration for running tests in a headless PhantomJS instance and code coverage reporting (by [@edjafarov](https://github.com/edjafarov)). [#1326](https://github.com/Leaflet/Leaflet/issues/1326) [#1340](https://github.com/Leaflet/Leaflet/pull/1340) + * Added [Travis CI integration](https://travis-ci.org/Leaflet/Leaflet) for linting and running tests for each commit and pull request automatically (by [@edjafarov](https://github.com/edjafarov)). [#1336](https://github.com/Leaflet/Leaflet/issues/1336) + * Significantly improved test coverage + * Added compatibility with lazy evaluation scripts (by [@kristerkari](https://github.com/kristerkari)). [#1288](https://github.com/Leaflet/Leaflet/issues/1288) [#1607](https://github.com/Leaflet/Leaflet/issues/1607) [#1288](https://github.com/Leaflet/Leaflet/issues/1288) + +### Bugfixes + +#### General bugfixes + + * Fixed lots of issues with extent restriction by `Map` `maxBounds`. [#1491](https://github.com/Leaflet/Leaflet/issues/1491) [#1475](https://github.com/Leaflet/Leaflet/issues/1475) [#1194](https://github.com/Leaflet/Leaflet/issues/1194) [#900](https://github.com/Leaflet/Leaflet/issues/900) [#1333](https://github.com/Leaflet/Leaflet/issues/1333) + * Fixed occasional crashes by disabling zoom animation if changing zoom level by more than 4 levels. [#1377](https://github.com/Leaflet/Leaflet/issues/1377) + * Fixed a bug with that caused stuttery keyboard panning in some cases (by [@tmcw](https://github.com/tmcw)). [#1710](https://github.com/Leaflet/Leaflet/issues/1710) + * Fixed a bug that caused unwanted scrolling of the page to the top of the map on focus. [#1228](https://github.com/Leaflet/Leaflet/issues/1228) [#1540](https://github.com/Leaflet/Leaflet/issues/1540) + * Fixed a bug where clicking on a marker with an open popup caused the popup to faded in again (by [@snkashis](https://github.com/snkashis)). [#506](https://github.com/Leaflet/Leaflet/issues/560) [#1386](https://github.com/Leaflet/Leaflet/pull/1386) + * Fixed a bug where zoom buttons disabled state didn't update on min/max zoom change (by [@snkashis](https://github.com/snkashis)). [#1372](https://github.com/Leaflet/Leaflet/pull/1372) [#1328](https://github.com/Leaflet/Leaflet/issues/1328) + * Fixed a bug where scrolling slightly wouldn't always zoom out the map (by [@cschwarz](https://github.com/cschwarz)). [#1575](https://github.com/Leaflet/Leaflet/pull/1575) + * Fixed popup close button to not leave an outline after clicking on it and reopening the popup (by [@dotCypress](https://github.com/dotCypress)). [#1537](https://github.com/Leaflet/Leaflet/pull/1537) + * Fixed a bug that prevented tiles from loading during pan animation. + * Fixed a bug with `contextmenu` events on popups falling through to map (by [@snkashis](https://github.com/snkashis)). [#1730](https://github.com/Leaflet/Leaflet/issues/1730) [#1732](https://github.com/Leaflet/Leaflet/issues/1732) + * Fixed `404` tile loading errors when browsing the map off the world bounds. + * Fixed shifted mouse events in some cases with map inside a relatively positioned parent (by [@scooterw](https://github.com/scooterw) and [@jec006](https://github.com/jec006)). [#1670](https://github.com/Leaflet/Leaflet/issues/1670) [#1684](https://github.com/Leaflet/Leaflet/issues/1684) [#1745](https://github.com/Leaflet/Leaflet/issues/1745) [#1744](https://github.com/Leaflet/Leaflet/issues/1744) + * Fixed a bug where tile layer z-index order sometimes broke after view reset. [#1422](https://github.com/Leaflet/Leaflet/issues/1422) + +#### Browser bugfixes + + * Fixed a bug with undesirable page scrolling in Firefox 17+ when you zoom the map by scrolling (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1789](https://github.com/Leaflet/Leaflet/issues/1789) [#1788](https://github.com/Leaflet/Leaflet/issues/1788) + * Fixed a bug where mouse coordinates where shifted in Firefox if the map was inside a positioned block on a scrolled page (by [@joschka](https://github.com/joschka)). [#1365](https://github.com/Leaflet/Leaflet/pull/1365) [#1322](https://github.com/Leaflet/Leaflet/issues/1322) + * Fixed a bug where box zoom didn't work in some cases in Firefox 18+ (by [@fabriceds](https://github.com/fabriceds)). [#1405](https://github.com/Leaflet/Leaflet/pull/1405) + * Fixed a bug where `TileLayer` opacity didn't work in IE 7-8 (by [@javisantana](https://github.com/javisantana) & [@danzel](https://gi +.com/danzel)). [#1084](https://github.com/Leaflet/Leaflet/issues/1084) [#1396](https://github.com/Leaflet/Leaflet/pull/1396) [#1371](https://github.com/Leaflet/Leaflet/issues/1371) + * Fixed Leaflet not working correctly in PhantomJS (by [@rassie](https://github.com/rassie)). [#1501](https://github.com/Leaflet/Leaflet/pull/1501) + +#### Mobile bugfixes + + * Fixed a bug with layers control on WinPhone8/IE10 Touch (by [@danzel](https://github.com/danzel)). [#1635](https://github.com/Leaflet/Leaflet/pull/1635) [#1539](https://github.com/Leaflet/Leaflet/issues/1539) + * Fixed a bug with click sometimes firing twice on WinPhone8/IE10 Touch (by [@danzel](https://github.com/danzel)). [#1694](https://github.com/Leaflet/Leaflet/issues/1694) + * Fixed a bug in Android where click was triggered twice on one tap (by [@jerel](https://github.com/jerel) & [@mourner](https://github.com/mourner)). [#1227](https://github.com/Leaflet/Leaflet/pull/1227) [#1263](https://github.com/Leaflet/Leaflet/issues/1263) [#1785](https://github.com/Leaflet/Leaflet/issues/1785) [#1694](https://github.com/Leaflet/Leaflet/issues/1694) + * Fixed a bug in Android where click on a collapsed layers control would immediately select one of the layers (by [@danzel](https://github.com/danzel)). [#1784](https://github.com/Leaflet/Leaflet/issues/1784) [#1694](https://github.com/Leaflet/Leaflet/issues/1694) + +#### API bugfixes + +##### General API bugfixes + + * Fixed click mouse event inside popups **not propagating outside the map** (fixes issues with jQuery.live and some mobile frameworks that rely on document click listeners). [#301](https://github.com/Leaflet/Leaflet/issues/301) + * Fixed a bug where event listener still fired even if it was removed on the same event in other listener (by [@spamdaemon](https://github.com/spamdaemon)). [#1661](https://github.com/Leaflet/Leaflet/issues/1661) [#1654](https://github.com/Leaflet/Leaflet/issues/1654) + * Fixed a bug where `L.point` and `L.latLng` factories weren't passing `null` and `undefined` values through. + * Fixed `DomEvent` `removeListener` function chaining (by [@pagameba](https://github.com/pagameba)). + * Fixed a bug where `removeEventListener` would throw an error if no events are registered on the object (by [@tjoekbezoer](https://github.com/tjoekbezoer)). [#1632](https://github.com/Leaflet/Leaflet/pull/1632) [#1631](https://github.com/Leaflet/Leaflet/issues/1631) + * Fixed a bug where `Point` `equals` and `contains` methods didn't accept points in array form. + * Fixed a bug where `LatLngBounds` `extend` of an undefined object would cause an error (by [@korzhyk](https://github.com/korzhyk)). [#1688](https://github.com/Leaflet/Leaflet/issues/1688) + * Fixed a bug where `Control.Attribution` `removeAttribution` of inexistant attribution corrupted the attribution text. [#1410](https://github.com/Leaflet/Leaflet/issues/1410) + * Fixed a bug where `setView` on an invisible map caused an error (by [@jfire](https://github.com/jfire)). [#1707](https://github.com/Leaflet/Leaflet/issues/1707) + * Fixed compatibility with Browserify (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1572](https://github.com/Leaflet/Leaflet/pull/1572) + +##### Layers API bugfixes + + * Fixed a bug where default marker icon path wasn't properly detected in some cases in IE6-7 (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#1294](https://github.com/Leaflet/Leaflet/pull/1294) + * Fixed a bug where `TileLayer.WMS` param values weren't escaped in URLs (by [@yohanboniface](https://github.com/yohanboniface)). [#1317](https://github.com/Leaflet/Leaflet/issues/1317) + * Fixed a bug where layers that belong to multiple feature groups didn't propagate events correctly (by [@danzel](https://github.com/danzel)). [#1359](https://github.com/Leaflet/Leaflet/pull/1359) + * Fixed a bug where `TileLayer.WMS` `tileSize` option was ignored (by [@brianhatchl](https://github.com/brianhatchl)). [#1080](https://github.com/brianhatchl) + * Fixed a bug where `Polyline` constructor could overwrite the source array (by [@snkashis](https://github.com/snkashis) and [@danzel](https://github.com/danzel)). [#1439](https://github.com/Leaflet/Leaflet/pull/1439) [#1092](https://github.com/Leaflet/Leaflet/issues/1092) [#1246](https://github.com/Leaflet/Leaflet/issues/1246) [#1426](https://github.com/Leaflet/Leaflet/issues/1426) + * Fixed a bug where marker dragging disabling/enabling wouldn't always work correctly (by [@snkashis](https://github.com/snkashis) and [@escaped](https://github.com/escaped)). [#1471](https://github.com/Leaflet/Leaflet/pull/1471) [#1551](https://github.com/Leaflet/Leaflet/pull/1551) + * Fixed `TileLayer` to prevent incorrect subdomain in case of negative tile coordinates (by [@malexeev](https://github.com/malexeev)). [#1532](https://github.com/Leaflet/Leaflet/pull/1532) + * Fixed polygons to normalize holes (remove last point if it's equal to the first one) (by [@jfirebaugh](https://github.com/jfirebaugh)). [#](https://github.com/Leaflet/Leaflet/pull/1467) [#1459](https://github.com/Leaflet/Leaflet/issues/1459) + * Fixed `DivIcon` `html` option to accept `0` as a value (by [@stuporglue](https://github.com/stuporglue)). [#1633](https://github.com/Leaflet/Leaflet/pull/1633) + * Fixed a bug with Canvas-based paths throwing an error on `mousemove` in certain conditions. [#1615](https://github.com/Leaflet/Leaflet/issues/1615) + * Fixed a bug where copies of the world wouldn't load if you set `TileLayer` `bounds` (by [@ansis](https://github.com/ansis)). [#1618](https://github.com/Leaflet/Leaflet/issues/1618) + * Fixed a bug where `TileLayer` `load` event wouldn't always fire correctly. [#1565](https://github.com/Leaflet/Leaflet/issues/1565) + * Fixed `TileLayer.WMS` compatibility with some old servers that only accepted request parameters in uppercase. [#1751](https://github.com/Leaflet/Leaflet/issues/1751) + * Fixed a bug with incorrect `L.Icon.Default.imagePath` detection in some cases. [#1657](https://github.com/Leaflet/Leaflet/issues/1657) + * Fixed a bug where layer `onRemove` was still called even if it was never added (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1729](https://github.com/Leaflet/Leaflet/issues/1729) + * Fixed a bug where calling `setRadius` on a Canvas-powered `CircleMarker` would cause an infinite loop (by [@snkashis](https://github.com/snkashis)). [#1712](https://github.com/Leaflet/Leaflet/issues/1712) [#1713](https://github.com/Leaflet/Leaflet/issues/1713) [#1728](https://github.com/Leaflet/Leaflet/issues/1728) + * Renamed `marker-icon@2x.png` to `marker-icon-2x.png` to fix compatibility with Google AppEngine. [#1552](https://github.com/Leaflet/Leaflet/issues/1552) [#1553](https://github.com/Leaflet/Leaflet/issues/1553) + * Fixed a bug where `popupclose` and `popupopen` events weren't fired for multipolygons and multipolylines (by [@tmcw](https://github.com/tmcw)). [#1681](https://github.com/Leaflet/Leaflet/issues/1681) + +##### Map API bugfixes + + * Fixed a bug where `Map` `fitBounds` wouldn't work correctly with large bounds (thanks to [@MaZderMind](https://github.com/MaZderMind)). [#1069](https://github.com/Leaflet/Leaflet/issues/1069) + * Fixed a bug where `Map` `hasLayer` wasn't handling `null` objects (by [@rvlasveld](https://github.com/rvlasveld)). [#1282](https://github.com/Leaflet/Leaflet/issues/1282) [#1302](https://github.com/Leaflet/Leaflet/pull/1302) + * Fixed a bug where `Map` `moveend` fired before `dragend` on drag (by [@oslek](https://github.com/oslek)). [#1374](https://github.com/Leaflet/Leaflet/pull/1374) + * Fixed a bug where panning with inertia produced an excessive `Map` `movestart` event on inertia start (by [@oslek](https://github.com/oslek)). [#1374](https://github.com/Leaflet/Leaflet/pull/1374) + * Fixed a bug where `Map` `moveend` fired repeatedly on window resize even if the actual map size didn't change (by [@oslek](https://github.com/oslek)). [#1374](https://github.com/Leaflet/Leaflet/pull/1374) + * Fixed a bug where `Map` `moveend` sometimes wasn't fired after drag (particularly often when dragging with a trackpad). + * Fixed a bug that would cause an error when trying to get the state of the map in a `Map` `load` event listener. [#962](https://github.com/Leaflet/Leaflet/issues/962) + * Added `Map` `autopanstart` event back (it was removed occasionally in previous version). [#1375](https://github.com/Leaflet/Leaflet/issues/1375) + * Fixed a bug with removing previously set `Map` `maxBounds` (by [@jec006](https://github.com/jec006)). [#1749](https://github.com/Leaflet/Leaflet/issues/1749) [#1750](https://github.com/Leaflet/Leaflet/issues/1750) + + +## 0.5.1 (2013-02-06) + + * Fixed a regression with `GeoJSON` not accepting arrays of `FeatureCollection` (by [@snkashis](https://github.com/snkashis)). [#1299](https://github.com/Leaflet/Leaflet/pull/1299) [#1298](https://github.com/Leaflet/Leaflet/issues/1298) + * Fixed a regression with `CirleMarker` `setRadius` not working if called before adding the layer to the map (by [@danzel](https://github.com/danzel)). [#1342](https://github.com/Leaflet/Leaflet/issues/1342) [#1297](https://github.com/Leaflet/Leaflet/issues/1297) + +## 0.5 (2013-01-17) + +### Breaking changes + +Be sure to read through these changes to avoid any issues when upgrading from older versions: + + * Removed default `LatLng` wrapping/clamping of coordinates (`-180, -90` to `180, 90`), wrapping moved to an explicit method (`LatLng` `wrap`). + * Disabled `Map` `worldCopyJump` option by default (jumping back to the original world copy when panning out of it). Enable it explicitly if you need it. + * Changed styles for the zoom control (you may need to update your custom styles for it). + +### Improvements + +#### Usability improvements + +##### Interaction + + * Added touch zoom, pan and double tap support for **IE10 touch devices and Metro apps** (by [@danzel](https://github.com/danzel) and [@veproza](https://github.com/veproza) with help from [@oliverheilig](https://github.com/oliverheilig)). [#1076](https://github.com/Leaflet/Leaflet/pull/1076) [#871](https://github.com/Leaflet/Leaflet/issues/871) + * **Improved panning inertia** to be much more natural and smooth. + * **Improved dragging cursors** in Chrome, Safari and Firefox (now grabbing hand cursors are used). + * Improved zoom animation curve for a better feel overall. + * Improved scroll wheel zoom to be more responsive. + * Improved panning animation performance in IE6-8. + +##### Controls + + * **Improved zoom control design** to look better, more neutral and in line with other controls, making it easier to customize and fit different website designs. Replaced +/- images with text. + * Improved zoom control to zoom by 3 levels if you hold shift while clicking on a button. + * Improved zoom control buttons to become visually disabled when min/max zoom is reached. [#917](https://github.com/Leaflet/Leaflet/issues/917) + * Improved scale control styles. + * Improved fallback control styles for IE6-8. + +##### Other + + * Added **retina support for markers** (through `Icon` `iconRetinaUrl` and `shadowRetinaUrl` options) (by [@danzel](https://github.com/danzel)). [#1048](https://github.com/Leaflet/Leaflet/issues/1048) [#1174](https://github.com/Leaflet/Leaflet/pull/1174) + * Added retina-sized default marker icon in addition to standard one (along with its SVG source and with some subtle design improvements) (by [@danzel](https://github.com/danzel)). [#1048](https://github.com/Leaflet/Leaflet/issues/1048) [#1174](https://github.com/Leaflet/Leaflet/pull/1174) + * Improved vectors updating/removing performance on Canvas backend (by [@danzel](https://github.com/danzel)). [#961](https://github.com/Leaflet/Leaflet/pull/961) + * Cut total images size from 10KB to 3.2KB with [Yahoo Smush.it](http://www.smushit.com/ysmush.it/). Thanks to Peter Rounce for suggestion. + +#### API improvements + + * Replaced `L.Transition` with a much better and simpler `L.PosAnimation`. + * Added `Class` `addInitHook` method for **adding constructor hooks to any classes** (great extension point for plugin authors). [#1123](https://github.com/Leaflet/Leaflet/issues/1123) + * Added `Map` `whenReady` method (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1063](https://github.com/Leaflet/Leaflet/pull/1063) + * Added optional `delta` argument to `Map` `zoomIn` and `zoomOut` (1 by default). + * Added `isValid` method to `LatLngBounds` and `Bounds` (by [@domoritz](https://github.com/domoritz)). [#972](https://github.com/Leaflet/Leaflet/pull/972) + * Added `Point` `equals` method. + * Added `Bounds` `getSize` method. + * Improved markers and vectors click event so that it propagates to map if no one is listening to it (by [@danzel](https://github.com/danzel)). [#834](https://github.com/Leaflet/Leaflet/issues/834) [#1033](https://github.com/Leaflet/Leaflet/pull/1033) + * Added `Path` `unbindPopup` and `closePopup` methods. + * Added `Path` `add` and `remove` event. + * Added `Marker` `riseOnHover` and `riseOffset` options (for bringing markers to front on hover, disabled by default) (by [jacobtoye](https://github.com/jacobtoye)). [#914](https://github.com/Leaflet/Leaflet/pull/914) [#920](https://github.com/Leaflet/Leaflet/issues/920) + * Added `Marker` `move` and `remove` events. + * Added `Marker` `contextmenu` event. [#223](https://github.com/Leaflet/Leaflet/issues/223) + * Added `Popup` `zoomAnimation` option (useful to disable when displaying flash content inside popups [#999](https://github.com/Leaflet/Leaflet/issues/999)). + * Added `FeatureGroup` `layeradd` and `layerremove` events (by [@jacobtoye](https://github.com/jacobtoye)). [#1122](https://github.com/Leaflet/Leaflet/issues/1122) + * Added `Control.Layers` `baselayerchange` event (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1064](https://github.com/Leaflet/Leaflet/pull/1064) + * Improved `Control.Layers` to support HTML in layer names (by [@aparshin](https://github.com/aparshin)). [#1055](https://github.com/Leaflet/Leaflet/pull/1055) [#1099](https://github.com/Leaflet/Leaflet/issues/1099) + * Added `CRS.Simple` to the list of built-in CRS and improved it to be more usable out of the box (it has different default scaling and transformation now), see `debug/map/simple-proj.html` for an example. + * Removed `Browser` `ua`, `gecko`, `opera` properties (no longer needed). + * Added `L.extend`, `L.bind`, `L.stamp`, `L.setOptions` shortcuts for corresponding `L.Util` methods. + * Disabled clearing of map container contents on map initialization (as a result of fixing [#278](https://github.com/Leaflet/Leaflet/issues/278)). + * Added `L.Util.isArray` function (by [@oslek](https://github.com/oslek)). [#1279](https://github.com/Leaflet/Leaflet/pull/1279) + * Added `mouseover` and `mouseout` events to canvas-based vector layers (by [@snkashis](https://github.com/snkashis)). [#1403](https://github.com/Leaflet/Leaflet/pull/1403) + * Added `Map` `eachLayer` to iterate over all layers added to the map (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1457](https://github.com/Leaflet/Leaflet/pull/1457) + * Added `TileLayer` `bounds` option to limit tile loading to a specific region (by [@adimitrov](https://github.com/adimitrov)). [#991](https://github.com/Leaflet/Leaflet/pull/991) + +### Bugfixes + +#### General bugfixes + + * Fixed broken tiles and zooming in RTL layouts (by [@danzel](https://github.com/danzel)). [#1099](https://github.com/Leaflet/Leaflet/pull/1099) [#1095](https://github.com/Leaflet/Leaflet/issues/1095) + * Fixed a bug with pan animation where it jumped to its end position if you tried to drag the map. + * Fixed a bug where shift-clicking on a map would zoom it to the max zoom level. + * Fixed a glitch with zooming in while panning animation is running. + * Fixed a glitch with dragging the map while zoom animation is running. + * Fixed a bug where slight touchpad scrolling or one-wheel scrolling wouln't always perform zooming. [#1039](https://github.com/Leaflet/Leaflet/issues/1039) + * Fixed a bug where `panBy` wouldn't round the offset values (so it was possible to make the map blurry with it). [#1085](https://github.com/Leaflet/Leaflet/issues/1085) + * Fixed a bug where you couldn't scroll the layers control with a mouse wheel. + * Fixed a regression where WMS tiles wouldn't wrap on date lines. [#970](https://github.com/Leaflet/Leaflet/issues/970) + * Fixed a bug where mouse interaction was affected by map container border width (by [@mohlendo](https://github.com/mohlendo)). [#1204](https://github.com/Leaflet/Leaflet/issues/1205) [#1205](https://github.com/Leaflet/Leaflet/pull/1205) + * Fixed a bug with weird vector zoom animation when using Canvas for rendering (by [@danzel](https://github.com/danzel)). [#1187](https://github.com/Leaflet/Leaflet/issues/1187) [#1188](https://github.com/Leaflet/Leaflet/pull/1188) + * Fixed a bug where max bounds limitation didn't work when navigating the map with a keyboard (by [@snkashis](https://github.com/snkashis)). [#989](https://github.com/Leaflet/Leaflet/issues/989) [#1221](https://github.com/Leaflet/Leaflet/pull/1221) + +#### API bugfixes + + * Fixed a bug where `TileLayer` `bringToBack` didn't work properly in some cases (by [@danzel](https://github.com/danzel)). [#963](https://github.com/Leaflet/Leaflet/pull/963) [#959](https://github.com/Leaflet/Leaflet/issues/959) + * Fixed a bug where removing a tile layer while dragging would throw an error (by [@danzel](https://github.com/danzel)). [#965](https://github.com/Leaflet/Leaflet/issues/965) [#968](https://github.com/Leaflet/Leaflet/pull/968) + * Fixed a bug where middle marker wasn't removed after deleting 2 end nodes from a polyline (by [@Svad](https://github.com/Svad)). [#1022](https://github.com/Leaflet/Leaflet/issues/1022) [#1023](https://github.com/Leaflet/Leaflet/pull/1023) + * Fixed a bug where `Map` `load` event happened too late (after `moveend`, etc.) (by [@jfirebaugh](https://github.com/jfirebaugh)). [#1027](https://github.com/Leaflet/Leaflet/pull/1027) + * Fixed `Circle` `getBounds` to return correct bounds and work without adding the circle to a map. [#1068](https://github.com/Leaflet/Leaflet/issues/1068) + * Fixed a bug where removing `Popup` on `viewreset` throwed an error (by [fnicollet](https://github.com/fnicollet) and [@danzel](https://github.com/danzel)). [#1098](https://github.com/Leaflet/Leaflet/pull/1098) [#1094](https://github.com/Leaflet/Leaflet/issues/1094) + * Fixed a bug where `TileLayer.Canvas` `drawTile` didn't receive tile zoom level in arguments. + * Fixed a bug where `GeoJSON` `resetStyle` would not fully reset a layer to its default style. [#1112](https://github.com/Leaflet/Leaflet/issues/1112) + * Fixed a bug that caused infinite recursion when using `latLngBounds` factory with coordinates as string values. [#933](https://github.com/Leaflet/Leaflet/issues/933) + * Fixed chaining on `Marker` `setIcon`, `setZIndexOffset`, `update` methods. [#1176](https://github.com/Leaflet/Leaflet/issues/1176) + * Fixed a bug with mouse interaction when the map container contained children with position other than absolute. [#278](https://github.com/Leaflet/Leaflet/issues/278) + * Fixed a bug with fill/stroke opacity conflicts when using Canvas for rendering (by [@danzel](https://github.com/danzel)). [#1186](https://github.com/Leaflet/Leaflet/issues/1186) [#1889](https://github.com/Leaflet/Leaflet/pull/1189) + * Fixed a bug where `FeatureGroup` `bindPopup` didn't take options into account. + * Fixed a bug where Canvas-based vector layers didn't cleanup click event on removal properly (by [@snkashis](https://github.com/snkashis)). [#1006](https://github.com/Leaflet/Leaflet/issues/1006) [#1273](https://github.com/Leaflet/Leaflet/pull/1273) + * Fixed a bug where `CircleMarker` `setStyle` didn't take `radius` into account (by [@fdlk](https://github.com/fdlk)). [#1012](https://github.com/Leaflet/Leaflet/issues/1012) [#1013](https://github.com/Leaflet/Leaflet/pull/1013) + * Fixed a bug where null GeoJSON geometries would throw an error instead of skipping (by [@brianherbert](https://github.com/brianherbert)). [#1240](https://github.com/Leaflet/Leaflet/pull/1240) + * Fixed a bug where Canvas-based vector layers passed incorrect `layer` event property on click (by [@snkashis](https://github.com/snkashis)). [#1215](https://github.com/Leaflet/Leaflet/issues/1215) [#1243](https://github.com/Leaflet/Leaflet/pull/1243) + * Fixed a bug where `TileLayer.WMS` didn't work correctly if the base URL contained query parameters (by [@snkashis](https://github.com/snkashis)). [#973](https://github.com/Leaflet/Leaflet/issues/973) [#1231](https://github.com/Leaflet/Leaflet/pull/1231) + * Fixed a bug where removing a polyline in editing state wouldn't clean up the editing handles (by [@mehmeta](https://github.com/mehmeta)). [#1233](https://github.com/Leaflet/Leaflet/pull/1233) + * Fixed a bug where removing a vector layer with a bound popup wouldn't clean up its click event properly (by [@yohanboniface](https://github.com/yohanboniface)). [#1229](https://github.com/Leaflet/Leaflet/pull/1229) + * Fixed a bug where `GeoJSON` features with `GeometryCollection` didn't pass properties to `pointToLayer` function (by [@calvinmetcalf](https://github.com/calvinmetcalf)). [#1097](https://github.com/Leaflet/Leaflet/pull/1097) + * Fixed `FeatureGroup` `eachLayer` chaining. [#1452](https://github.com/Leaflet/Leaflet/issues/1452) + +#### Browser bugfixes + + * Fixed a bug with map **freezing after zoom on Android 4.1**. [#1182](https://github.com/Leaflet/Leaflet/issues/1182) + * Fixed a bug where "Not implemented" error sometimes appeared in IE6-8 (by [@bryguy](https://github.com/bryguy) and [@lookfirst](https://github.com/lookfirst)). [#892](https://github.com/Leaflet/Leaflet/issues/892) [#893](https://github.com/Leaflet/Leaflet/pull/893) + * Fixed compatibility with SmoothWheel extension for Firefox (by [@waldir](https://github.com/waldir)). [#1011](https://github.com/Leaflet/Leaflet/pull/1011) + * Fixed a bug with popup layout in IE6-7 (by [@danzel](https://github.com/danzel)). [#1117](https://github.com/Leaflet/Leaflet/issues/1117) + * Fixed a bug with incorrect box zoom opacity in IE6-7 (by [@jacobtoye](https://github.com/jacobtoye)). [#1072](https://githubcom/Leaflet/Leaflet/pull/1072) + * Fixed a bug with box zoom throwing a JS error in IE6-7 (by [@danzel](https://github.com/danzel)). [#1071](https://github.com/Leaflet/Leaflet/pull/1071) + * Fixed a bug where `TileLayer` `bringToFront/Back()` throwed an error in IE6-8. [#1168](https://github.com/Leaflet/Leaflet/issues/1168) + * Fixed array type checking in the code to be more consistent in a cross-frame environment (by [@oslek](https://github.com/oslek)). [#1279](https://github.com/Leaflet/Leaflet/pull/1279) + * Fixed a bug with `-` key not working in Firefox 15+ (thanks to [@mattesCZ](https://github.com/mattesCZ)). [#869](https://github.com/Leaflet/Leaflet/issues/869) + +## 0.4.5 (2012-10-25) + + * Fixed a bug with **wonky zoom animation in IE10** (by [@danzel](https://github.com/danzel)). [#1007](https://github.com/Leaflet/Leaflet/pull/1007) + * Fixed a bug with **wonky zoom animation in Chrome 23+** (by [@danzel](https://github.com/danzel)). [#1060](https://github.com/Leaflet/Leaflet/pull/1060) [#1056](https://github.com/Leaflet/Leaflet/issues/1056) + +## 0.4.4 (2012-08-07) + +### Improvements + + * Improved `GeoJSON` `setStyle` to also accept function (like the corresponding option). + * Added `GeoJSON` `resetStyle(layer)`, useful for resetting hover state. + * Added `feature` property to layers created with `GeoJSON` (containing the GeoJSON feature data). + * Added `FeatureGroup` `bringToFront` and `bringToBack` methods (so that they would work for multipolys). + * Added optional `animate` argument to `Map` `invalidateSize` (by [@ajbeaven](https://github.com/ajbeaven)). [#857](https://github.com/Leaflet/Leaflet/pull/857) + +### Bugfixes + + * Fixed a bug where tiles sometimes disappeared on initial map load on Android 2/3 (by [@danzel](https://github.com/danzel)). [#868](https://github.com/Leaflet/Leaflet/pull/868) + * Fixed a bug where map would occasionally flicker near the border on zoom or pan on Chrome. + * Fixed a bug where `Path` `bringToFront` and `bringToBack` didn't return `this`. + * Removed zoom out on Win/Meta key binding (since it interferes with global keyboard shortcuts). [#869](https://github.com/Leaflet/Leaflet/issues/869) + +## 0.4.2 (2012-08-01) + + * Fixed a bug where layers control radio buttons would not work correctly in IE7 (by [@danzel](https://github.com/danzel)). [#862](https://github.com/Leaflet/Leaflet/pull/862) + * Fixed a bug where `FeatureGroup` `removeLayer` would unbind popups of removed layers even if the popups were not put by the group (affected [Leaflet.markercluster](https://github.com/danzel/Leaflet.markercluster) plugin) (by [@danzel](https://github.com/danzel)). [#861](https://github.com/Leaflet/Leaflet/pull/861) + +## 0.4.1 (2012-07-31) + + * Fixed a bug that caused marker shadows appear as opaque black in IE6-8. [#850](https://github.com/Leaflet/Leaflet/issues/850) + * Fixed a bug with incorrect calculation of scale by the scale control. [#852](https://github.com/Leaflet/Leaflet/issues/852) + * Fixed broken L.tileLayer.wms class factory (by [@mattcurrie](https://github.com/mattcurrie)). [#856](https://github.com/Leaflet/Leaflet/issues/856) + * Improved retina detection for `TileLayer` `detectRetina` option (by [@sxua](https://github.com/sxua)). [#854](https://github.com/Leaflet/Leaflet/issues/854) + +## 0.4 (2012-07-30) + +### API simplification + +Leaflet 0.4 contains several API improvements that allow simpler, jQuery-like syntax ([example](https://gist.github.com/3038879)) while being backwards compatible with the previous approach (so you can use both styles): + + * Improved most methods and options to accept `LatLng`, `LatLngBounds`, `Point` and `Bounds` values in an array form (e.g. `map.panTo([lat, lng])` will be the same as `map.panTo(new L.LatLng(lat, lng))`) + * Added `addTo` method to all layer classes, e.g. `marker.addTo(map)` is equivalent to `map.addLayer(marker)` + * Added factory methods to most classes to be able to write code without `new` keyword, named the same as classes but starting with a lowercase letter, e.g. `L.map('map')` is the same as `new L.Map('map')` + +### Notable new features + + * Added configurable **panning inertia** - after a quick pan, the map slows down in the same direction. + * Added **keyboard navigation** for panning/zooming with keyboard arrows and +/- keys (by [@ericmmartinez](https://github.com/ericmmartinez)). [#663](https://github.com/Leaflet/Leaflet/pull/663) [#646](https://github.com/Leaflet/Leaflet/issues/646) + * Added smooth **zoom animation of markers, vector layers, image overlays and popups** (by [@danzel](https://github.com/danzel)). [#740](https://github.com/Leaflet/Leaflet/pull/740) [#758](https://github.com/Leaflet/Leaflet/issues/758) + * Added **Android 4+ pinch-zoom** support (by [@danzel](https://github.com/danzel)). [#774](https://github.com/Leaflet/Leaflet/pull/774) + * Added **polyline and polygon editing**. [#174](https://github.com/Leaflet/Leaflet/issues/174) + * Added an unobtrusive **scale control**. + * Added **DivIcon** class that easily allows you to create lightweight div-based markers. + * Added **Rectangle** vector layer (by [@JasonSanford](https://github.com/JasonSanford)). [#504](https://github.com/Leaflet/Leaflet/pull/504) + +### Improvements + +#### Usability improvements + + * Improved zooming so that you don't get a blank map when you zoom in or out twice quickly (by [@danzel](https://github.com/danzel)). [#7](https://github.com/Leaflet/Leaflet/issues/7) [#729](https://github.com/Leaflet/Leaflet/pull/729) + * Drag-panning now works even when there are markers in the starting point (helps on maps with lots of markers). [#506](https://github.com/Leaflet/Leaflet/issues/506) + * Improved panning performance even more (there are no wasted frames now). + * Improved pinch-zoom performance in mobile Chrome and Firefox. + * Improved map performance on window resize. + * Replaced box-shadow with border on controls for mobile devices to improve performance. + * Slightly improved default popup styling. + * Added `TileLayer` `detectRetina` option (`false` by default) that makes tiles show in a higher resolution on iOS retina displays (by [@Mithgol](https://github.com/Mithgol)). [#586](https://github.com/Leaflet/Leaflet/pull/586) + +#### GeoJSON API changes + +GeoJSON API was improved to be simpler and more flexible ([example](https://gist.github.com/3062900)). The changes are not backwards-compatible, so be sure to update your old code. + + * Added `style` option for styling vector layers, passed either as an object or as a function (to style vector layers according to GeoJSON properties). + * Added `filter` option to leave out features that don't correspond to a certain criteria (e.g. based on properties). + * Added `onEachFeature` option to execute certain code on each feature layer based on its properties (binding popups, etc). + * Changed `pointToLayer` function signature to provide `geojson` in addition to `latlng` when creating point features for more flexibility. + +#### Icon API changes + +Icon API was improved to be more flexible, but one of the changes is backwards-incompatible: you now need to pass different icon properties (like `iconUrl`) inside an options object ([example](https://gist.github.com/3076084)). + + * Converted `Icon` properties to options, changed constructor signature to `Icon(options)`. + * Moved default marker icon options to `L.Icon.Default` class (which extends from `L.Icon`). + * Added `Icon` `className` option to assign a custom class to an icon. + * Added `Icon` `shadowAnchor` option to set the anchor of the shadow. + * Made all `Icon` options except `iconUrl` optional (if not specified, they'll be chosen automatically or implemented using CSS). Anchor is centered by default (if size is specified), and otherwise can be set through CSS using negative margins. + +#### Control API changes + + * Added `setPosition` and `getPosition` to all controls, as well as ability to pass certain position as an option when creating a control. + * Made controls implementation easier (now more magic happens under the hood). + * Replaced ugly control position constants (e.g. `L.Control.Position.TOP_LEFT`) with light strings (`'topleft'`, `'bottomright'`, etc.) + +#### Other breaking API changes + + * Improved `TileLayer` constructor to interpolate URL template values from options (removed third `urlParams` argument). + * Changed `TileLayer` `scheme: 'tms'` option to `tms: true`. + * Removed `Map` `locateAndSetView` method (use `locate` with `setView: true` option) + * Changed popup `minWidth` and `maxWidth` options to be applied to content element, not the whole popup. + * Moved `prefix` argument to `options` in `Control.Attribution` constructor. + * Renamed `L.VERSION` to `L.version`. + +#### Other API improvements + + * Improved `on` and `off` methods to also accept `(eventHash[, context])`, as well as multiple space-separated events (by [@Guiswa](https://github.com/Guiswa)). [#770](https://github.com/Leaflet/Leaflet/pull/770) + * Improved `off` to remove all listeners of the event if no function was specified (by [@Guiswa](https://github.com/Guiswa)). [#770](https://github.com/Leaflet/Leaflet/pull/770) [#691](https://github.com/Leaflet/Leaflet/issues/691) + * Added `TileLayer` `setZIndex` method for controlling the order of tile layers (thanks to [@mattcurrie](https://github.com/mattcurrie)). [#837](https://github.com/Leaflet/Leaflet/pull/837) + * Added `Control.Layers` `autoZIndex` option (on by default) to preserve the order of tile layers when switching. + * Added `TileLayer` `redraw` method for re-requesting tiles (by [@greeninfo](https://github.com/greeninfo)). [#719](https://github.com/Leaflet/Leaflet/issues/719) + * Added `TileLayer` `setUrl` method for dynamically changing the tile URL template. + * Added `bringToFront` and `bringToBack` methods to `TileLayer`, `ImageOverlay` and vector layers. [#185](https://github.com/Leaflet/Leaflet/issues/185) [#505](https://github.com/Leaflet/Leaflet/issues/505) + * Added `TileLayer` `loading` event that fires when its tiles start to load (thanks to [@lapinos03](https://github.com/lapinos03)). [#177](https://github.com/Leaflet/Leaflet/issues/177) + * Added `TileLayer.WMS` `setParams` method for setting WMS parameters at runtime (by [@greeninfo](https://github.com/greeninfo)). [#719](https://github.com/Leaflet/Leaflet/issues/719) + * Added `TileLayer.WMS` subdomain support (`{s}` in the url) (by [@greeninfo](https://github.com/greeninfo)). [#735](https://github.com/Leaflet/Leaflet/issues/735) + * Added `originalEvent` property to `MouseEvent` (by [@k4](https://github.com/k4)). [#521](https://github.com/Leaflet/Leaflet/pull/521) + * Added `containerPoint` property to `MouseEvent`. [#413](https://github.com/Leaflet/Leaflet/issues/413) + * Added `contextmenu` event to vector layers (by [@ErrorProne](https://github.com/ErrorProne)). [#500](https://github.com/Leaflet/Leaflet/pull/500) + * Added `LayerGroup` `eachLayer` method for iterating over its members. + * Added `FeatureGroup` `mousemove` and `contextmenu` events (by [@jacobtoye](https://github.com/jacobtoye)). [#816](https://github.com/Leaflet/Leaflet/pull/816) + * Added chaining to `DomEvent` methods. + * Added `on` and `off` aliases for `DomEvent` `addListener` and `removeListener` methods. + * Added `L_NO_TOUCH` global variable switch (set it before Leaflet inclusion) which disables touch detection, helpful for desktop apps built using QT. [#572](https://github.com/Leaflet/Leaflet/issues/572) + * Added `dashArray` option to vector layers for making dashed strokes (by [jacobtoye](https://github.com/jacobtoye)). [#821](https://github.com/Leaflet/Leaflet/pull/821) [#165](https://github.com/Leaflet/Leaflet/issues/165) + * Added `Circle` `getBounds` method. [#440](https://github.com/Leaflet/Leaflet/issues/440) + * Added `Circle` `getLatLng` and `getRadius` methods (by [@Guiswa](https://github.com/Guiswa)). [#655](https://github.com/Leaflet/Leaflet/pull/655) + * Added `openPopup` method to all vector layers. [#246](https://github.com/Leaflet/Leaflet/issues/246) + * Added public `redraw` method to vector layers (useful if you manipulate their `LatLng` points directly). + * Added `Marker` `opacity` option and `setOpacity` method. + * Added `Marker` `update` method. [#392](https://github.com/Leaflet/Leaflet/issues/392) + * Improved `Marker` `openPopup` not to raise an error if it doesn't have a popup. [#507](https://github.com/Leaflet/Leaflet/issues/507) + * Added `ImageOverlay` `opacity` option and `setOpacity` method. [#438](https://github.com/Leaflet/Leaflet/issues/438) + * Added `Popup` `maxHeight` option that makes content inside the popup scrolled if it doesn't fit the specified max height. + * Added `Popup` `openOn(map)` method (similar to `Map` `openPopup`). + * Added `Map` `getContainer` method (by [@Guiswa](https://github.com/Guiswa)). [#654](https://github.com/Leaflet/Leaflet/pull/654) + * Added `Map` `containerPointToLatLng` and `latLngToContainerPoint` methods. [#474](https://github.com/Leaflet/Leaflet/issues/474) + * Added `Map` `addHandler` method. + * Added `Map` `mouseup` and `autopanstart` events. + * Added `LatLngBounds` `pad` method that returns bounds extended by a percentage (by [@jacobtoye](https://github.com/jacobtoye)). [#492](https://github.com/Leaflet/Leaflet/pull/492) + * Moved dragging cursor styles from JS code to CSS. + +### Bug fixes + +#### General bugfixes + + * Fixed a bug where the map was zooming incorrectly inside a `position: fixed` container (by [@chx007](https://github.com/chx007)). [#602](https://github.com/Leaflet/Leaflet/pull/602) + * Fixed a bug where scaled tiles weren't cleared up after zoom in some cases (by [@cfis](https://github.com/cfis)) [#683](https://github.com/Leaflet/Leaflet/pull/683) + * Fixed a bug where map wouldn't drag over a polygon with a `mousedown` listener. [#834](https://github.com/Leaflet/Leaflet/issues/834) + +#### API bugfixes + + * Fixed a regression where removeLayer would not remove corresponding attribution. [#488](https://github.com/Leaflet/Leaflet/issues/488) + * Fixed a bug where popup close button wouldn't work on manually added popups. [#423](https://github.com/Leaflet/Leaflet/issues/423) + * Fixed a bug where marker click event would stop working if you dragged it and then disabled dragging. [#434](https://github.com/Leaflet/Leaflet/issues/434) + * Fixed a bug where `TileLayer` `setOpacity` wouldn't work when setting it back to 1. + * Fixed a bug where vector layer `setStyle({stroke: false})` wouldn't remove stroke and the same for fill. [#441](https://github.com/Leaflet/Leaflet/issues/441) + * Fixed a bug where `Marker` `bindPopup` method wouldn't take `offset` option into account. + * Fixed a bug where `TileLayer` `load` event wasn't fired if some tile didn't load (by [@lapinos03](https://github.com/lapinos03) and [@cfis](https://github.com/cfis)) [#682](https://github.com/Leaflet/Leaflet/pull/682) + * Fixed error when removing `GeoJSON` layer. [#685](https://github.com/Leaflet/Leaflet/issues/685) + * Fixed error when calling `GeoJSON` `clearLayer` (by [@runderwood](https://github.com/runderwood)). [#617](https://github.com/Leaflet/Leaflet/pull/617) + * Fixed a bug where `Control` `setPosition` wasn't always working correctly (by [@ericmmartinez](https://github.com/ericmmartinez)). [#657](https://github.com/Leaflet/Leaflet/pull/657) + * Fixed a bug with `Util.bind` sometimes losing arguments (by [@johtso](https://github.com/johtso)). [#588](https://github.com/Leaflet/Leaflet/pull/588) + * Fixed a bug where `drag` event was sometimes fired after `dragend`. [#555](https://github.com/Leaflet/Leaflet/issues/555) + * Fixed a bug where `TileLayer` `load` event was firing only once (by [@lapinos03](https://github.com/lapinos03) and [shintonik](https://github.com/shintonik)). [#742](https://github.com/Leaflet/Leaflet/pull/742) [#177](https://github.com/Leaflet/Leaflet/issues/177) + * Fixed a bug where `FeatureGroup` popup events where not cleaned up after removing a layer from it (by [@danzel](https://github.com/danzel)). [#775](https://github.com/Leaflet/Leaflet/pull/775) + * Fixed a bug where `DomUtil.removeClass` didn't remove trailing spaces (by [@jieter](https://github.com/jieter)). [#784](https://github.com/Leaflet/Leaflet/pull/784) + * Fixed a bug where marker popup didn't take popup offset into account. + * Fixed a bug that led to an error when polyline was removed inside a `moveend` listener. + * Fixed a bug where `LayerGroup` `addLayer` wouldn't check if a layer has already been added (by [@danzel](https://github.com/danzel)). [798](https://github.com/Leaflet/Leaflet/pull/798) + +#### Browser bugfixes + + * Fixed broken zooming on IE10 beta (by [@danzel](https://github.com/danzel)). [#650](https://github.com/Leaflet/Leaflet/issues/650) [#751](https://github.com/Leaflet/Leaflet/pull/751) + * Fixed a bug that broke Leaflet for websites that had XHTML content-type header set (by [lars-sh](https://github.com/lars-sh)). [#801](https://github.com/Leaflet/Leaflet/pull/801) + * Fixed a bug that caused popups to be empty in IE when passing a DOM node as the content (by [@nrenner](https://github.com/nrenner)). [#472](https://github.com/Leaflet/Leaflet/pull/472) + * Fixed inability to use scrolled content inside popup due to mouse wheel propagation. + * Fixed a bug that caused jumping/stuttering of panning animation in some cases. + * Fixed a bug where popup size was calculated incorrectly in IE. + * Fixed a bug where cursor would flicker when dragging a marker. + * Fixed a bug where clickable paths on IE9 didn't have a hand cursor (by [naehrstoff](https://github.com/naehrstoff)). [#671](https://github.com/Leaflet/Leaflet/pull/671) + * Fixed a bug in IE with disappearing icons when changing opacity (by [@tagliala](https://github.com/tagliala) and [DamonOehlman](https://github.com/DamonOehlman)). [#667](https://github.com/Leaflet/Leaflet/pull/667) [#600](https://github.com/Leaflet/Leaflet/pull/600) + * Fixed a bug with setting opacity on IE10 (by [@danzel](https://github.com/danzel)). [796](https://github.com/Leaflet/Leaflet/pull/796) + * Fixed a bug where `Control.Layers` didn't work on IE7. [#652](https://github.com/Leaflet/Leaflet/issues/652) + * Fixed a bug that could cause false `mousemove` events on click in Chrome (by [@stsydow](https://github.com/stsydow)). [#757](https://github.com/Leaflet/Leaflet/pull/757) + * Fixed a bug in IE6-8 where adding fill or stroke on vector layers after initialization with `setStyle` would break the map. [#641](https://github.com/Leaflet/Leaflet/issues/641) + * Fixed a bug with setOpacity in IE where it would not work correctly if used more than once on the same element (by [@ajbeaven](https://github.com/ajbeaven)). [#827](https://github.com/Leaflet/Leaflet/pull/827) + * Fixed a bug in Chrome where transparent control corners sometimes couldn't be clicked through (by [@danzel](https://github.com/danzel)). [#836](https://github.com/Leaflet/Leaflet/pull/836) [#575](https://github.com/Leaflet/Leaflet/issues/575) + +#### Mobile browser bugfixes + + * Fixed a bug that sometimes caused map to disappear completely after zoom on iOS (by [@fr1n63](https://github.com/fr1n63)). [#580](https://github.com/Leaflet/Leaflet/issues/580) [#777](https://github.com/Leaflet/Leaflet/pull/777) + * Fixed a bug that often caused vector layers to flicker on drag end on iOS (by [@krawaller](https://github.com/krawaller)). [#18](https://github.com/Leaflet/Leaflet/issues/18) + * Fixed a bug with false map click events on pinch-zoom and zoom/layers controls click. [#485](https://github.com/Leaflet/Leaflet/issues/485) + * Fixed a bug where touching the map with two or more fingers simultaneously would raise an error. + * Fixed a bug where zoom control wasn't always visible on Android 3. [#335](https://github.com/Leaflet/Leaflet/issues/335) + * Fixed a bug where opening the layers control would propagate a click to the map (by [@jacobtoye](https://github.com/jacobtoye)). [#638](https://github.com/Leaflet/Leaflet/pull/638) + * Fixed a bug where `ImageOverlay` wouldn't stretch properly on zoom on Android 2. [#651](https://github.com/Leaflet/Leaflet/issues/651) + * Fixed a bug where `clearLayers` for vector layers on a Canvas backend (e.g. on Android 2) would take unreasonable amount of time. [#785](https://github.com/Leaflet/Leaflet/issues/785) + * Fixed a bug where `setLatLngs` and similar methods on vector layers on a Canvas backend would not update the layers immediately. [#732](https://github.com/Leaflet/Leaflet/issues/732) + +## 0.3.1 (2012-02-14) + + * Fixed a regression where default marker icons wouldn't work if Leaflet include url contained a query string. + * Fixed a regression where tiles sometimes flickered with black on panning in iOS. + +## 0.3 (2012-02-13) + +### Major features + + * Added **Canvas backend** for vector layers (polylines, polygons, circles). This enables vector support on Android < 3, and it can also be optionally preferred over SVG for a performance gain in some cases. Thanks to [@florianf](https://github.com/florianf) for a big part of this work. + * Added **layers control** (`Control.Layers`) for convenient layer switching. + * Added ability to set **max bounds** within which users can pan/zoom. [#93](https://github.com/Leaflet/Leaflet/issues/93) + +### Improvements + +#### Usability improvements + + * Map now preserves its center after resize. + * When panning to another copy of the world (that's infinite horizontally), map overlays now jump to corresponding positions. [#273](https://github.com/Leaflet/Leaflet/issues/273) + * Limited maximum zoom change on a single mouse wheel movement (so you won't zoom across the whole zoom range in one scroll). [#149](https://github.com/Leaflet/Leaflet/issues/149) + * Significantly improved line simplification performance (noticeable when rendering polylines/polygons with tens of thousands of points) + * Improved circles performance by not drawing them if they're off the clip region. + * Improved stability of zoom animation (less flickering of tiles). + +#### API improvements + + * Added ability to add a tile layer below all others (`map.addLayer(layer, true)`) (useful for switching base tile layers). + * Added `Map` `zoomstart` event (thanks to [@Fabiz](https://github.com/Fabiz)). [#377](https://github.com/Leaflet/Leaflet/pull/377) + * Improved `Map` `locate` method, added ability to watch location continuously and more options. [#212](https://github.com/Leaflet/Leaflet/issues/212) + * Added second argument `inside` to `Map` `getBoundsZoom` method that allows you to get appropriate zoom for the view to fit *inside* the given bounds. + * Added `hasLayer` method to `Map`. + * Added `Marker` `zIndexOffset` option to be able to set certain markers below/above others. [#65](https://github.com/Leaflet/Leaflet/issues/65) + * Added `urlParams` third optional argument to `TileLayer` constructor for convenience: an object with properties that will be evaluated in the URL template. + * Added `TileLayer` `continuousWorld` option to disable tile coordinates checking/wrapping. + * Added `TileLayer` `tileunload` event fired when tile gets removed after panning (by [@CodeJosch](https://github.com/CodeJosch)). [#256](https://github.com/Leaflet/Leaflet/pull/256) + * Added `TileLayer` `zoomOffset` option useful for non-256px tiles (by [@msaspence](https://github.com/msaspence)). + * Added `TileLayer` `zoomReverse` option to reverse zoom numbering (by [@Majiir](https://github.com/Majiir)). [#406](https://github.com/Leaflet/Leaflet/pull/406) + * Added `TileLayer.Canvas` `redraw` method (by [@mortenbekditlevsen](https://github.com/mortenbekditlevsen)). [#459](https://github.com/Leaflet/Leaflet/pull/459) + * Added `Polyline` `closestLayerPoint` method that's can be useful for interaction features (by [@anru](https://github.com/anru)). [#186](https://github.com/Leaflet/Leaflet/pull/186) + * Added `setLatLngs` method to `MultiPolyline` and `MultiPolygon` (by [@anru](https://github.com/anru)). [#194](https://github.com/Leaflet/Leaflet/pull/194) + * Added `getBounds` method to `Polyline` and `Polygon` (by [@JasonSanford](https://github.com/JasonSanford)). [#253](https://github.com/Leaflet/Leaflet/pull/253) + * Added `getBounds` method to `FeatureGroup` (by [@JasonSanford](https://github.com/JasonSanford)). [#557](https://github.com/Leaflet/Leaflet/pull/557) + * Added `FeatureGroup` `setStyle` method (also inherited by `MultiPolyline` and `MultiPolygon`). [#353](https://github.com/Leaflet/Leaflet/issues/353) + * Added `FeatureGroup` `invoke` method to call a particular method on all layers of the group with the given arguments. + * Added `ImageOverlay` `load` event. [#213](https://github.com/Leaflet/Leaflet/issues/213) + * Added `minWidth` option to `Popup` (by [@marphi](https://github.com/marphi)). [#214](https://github.com/Leaflet/Leaflet/pull/214) + * Improved `LatLng` constructor to be more tolerant (and throw descriptive error if latitude or longitude can't be interpreted as a number). [#136](https://github.com/Leaflet/Leaflet/issues/136) + * Added `LatLng` `distanceTo` method (great circle distance) (by [@mortenbekditlevsen](https://github.com/mortenbekditlevsen)). [#462](https://github.com/Leaflet/Leaflet/pull/462) + * Added `LatLngBounds` `toBBoxString` method for convenience (by [@JasonSanford](https://github.com/JasonSanford)). [#263](https://github.com/Leaflet/Leaflet/pull/263) + * Added `LatLngBounds` `intersects(otherBounds)` method (thanks to [@pagameba](https://github.com/pagameba)). [#350](https://github.com/Leaflet/Leaflet/pull/350) + * Made `LatLngBounds` `extend` method to accept other `LatLngBounds` in addition to `LatLng` (by [@JasonSanford](https://github.com/JasonSanford)). [#553](https://github.com/Leaflet/Leaflet/pull/553) + * Added `Bounds` `intersects(otherBounds)` method. [#461](https://github.com/Leaflet/Leaflet/issues/461) + * Added `L.Util.template` method for simple string template evaluation. + * Added `DomUtil.removeClass` method (by [@anru](https://github.com/anru)). + * Improved browser-specific code to rely more on feature detection rather than user agent string. + * Improved superclass access mechanism to work with inheritance chains of 3 or more classes; now you should use `Klass.superclass` instead of `this.superclass` (by [@anru](https://github.com/anru)). [#179](https://github.com/Leaflet/Leaflet/pull/179) + * Added `Map` `boxzoomstart` and `boxzoomend` events (by [@zedd45](https://github.com/zedd45)). [#554](https://github.com/Leaflet/Leaflet/pull/554) + * Added `Popup` `contentupdate` event (by [@mehmeta](https://github.com/mehmeta)). [#548](https://github.com/Leaflet/Leaflet/pull/548) + +#### Breaking API changes + + * `shiftDragZoom` map option/property renamed to `boxZoom`. + * Removed `mouseEventToLatLng` method (bringed back in 0.4). + +#### Development workflow improvements + + * Build system completely overhauled to be based on Node.js, Jake, JSHint and UglifyJS. + * All code is now linted for errors and conformity with a strict code style (with JSHint), and wont build unless the check passes. + +### Bugfixes + +#### General bugfixes + + * Fixed a bug where `Circle` was rendered with incorrect radius (didn't take projection exagerration into account). [#331](https://github.com/Leaflet/Leaflet/issues/331) + * Fixed a bug where `Map` `getBounds` would work incorrectly on a date line cross. [#295](https://github.com/Leaflet/Leaflet/issues/295) + * Fixed a bug where polygons and polylines sometimes rendered incorrectly on some zoom levels. [#381](https://github.com/Leaflet/Leaflet/issues/381) + * Fixed a bug where fast mouse wheel zoom worked incorrectly when approaching min/max zoom values. + * Fixed a bug where `GeoJSON` `pointToLayer` option wouldn't work in a `GeometryCollection`. [#391](https://github.com/Leaflet/Leaflet/issues/391) + * Fixed a bug with incorrect rendering of GeoJSON on a date line cross. [#354](https://github.com/Leaflet/Leaflet/issues/354) + * Fixed a bug where map panning would stuck forever after releasing the mouse over an iframe or a flash object (thanks to [@sten82](https://github.com/sten82)). [#297](https://github.com/Leaflet/Leaflet/pull/297) [#64](https://github.com/Leaflet/Leaflet/issues/64) + * Fixed a bug where mouse wheel zoom worked incorrectly if map is inside scrolled container (partially by [@chrillo](https://github.com/chrillo)). [#206](https://github.com/Leaflet/Leaflet/issues/206) + * Fixed a bug where it was possible to add the same listener twice. [#281](https://github.com/Leaflet/Leaflet/issues/281) + * Fixed a bug where `Circle` was rendered with incorrect radius (didn't take projection exaggeration into account). [#331](https://github.com/Leaflet/Leaflet/issues/331) + * Fixed a bug where `Marker` `setIcon` was not working properly (by [@marphi](https://github.com/marphi)). [#218](https://github.com/Leaflet/Leaflet/pull/218) [#311](https://github.com/Leaflet/Leaflet/issues/311) + * Fixed a bug where `Marker` `setLatLng` was not working if it's set before adding the marker to a map. [#222](https://github.com/Leaflet/Leaflet/issues/222) + * Fixed a bug where marker popup would not move on `Marker` `setLatLng` (by [@tjarratt](https://github.com/tjarratt)). [#272](https://github.com/Leaflet/Leaflet/pull/272) + * Fixed a bug where static properties of a child class would not override the parent ones. + * Fixed broken popup `closePopup` option (by [@jgerigmeyer](https://github.com/jgerigmeyer)). + * Fixed a bug that caused en error when dragging marker with icon without shadow (by [@anru](https://github.com/anru)). [#178](https://github.com/Leaflet/Leaflet/issues/178) + * Fixed a typo in `Bounds` `contains` method (by [@anru](https://github.com/anru)). [#180](https://github.com/Leaflet/Leaflet/pull/180) + * Fixed a bug where creating an empty `Polygon` with `new L.Polygon()` would raise an error. + * Fixed a bug where drag event fired before the actual movement of layer (by [@anru](https://github.com/anru)). [#197](https://github.com/Leaflet/Leaflet/pull/197) + * Fixed a bug where map click caused an error if dragging is initially disabled. [#196](https://github.com/Leaflet/Leaflet/issues/196) + * Fixed a bug where map `movestart` event would fire after zoom animation. + * Fixed a bug where attribution prefix would not update on `setPrefix`. [#195](https://github.com/Leaflet/Leaflet/issues/195) + * Fixed a bug where `TileLayer` `load` event wouldn't fire in some edge cases (by [@dravnic](https://github.com/dravnic)). + * Fixed a bug related to clearing background tiles after zooming (by [@neno-giscloud](https://github.com/neno-giscloud) & [@dravnic](https://github.com/dravnic)). + * Fixed a bug that sometimes caused map flickering after zoom animation. + * Fixed a bug related to cleaning up after removing tile layers (by [@dravnic](https://github.com/dravnic)). [#276](https://github.com/Leaflet/Leaflet/pull/276) + * Fixed a bug that made selecting text in the attribution control impossible. [#279](https://github.com/Leaflet/Leaflet/issues/279) + * Fixed a bug when initializing a map in a non-empty div. [#278](https://github.com/Leaflet/Leaflet/issues/278) + * Fixed a bug where `movestart` didn't fire on panning animation. + * Fixed a bug in Elliptical Mercator formula that affeted `EPSG:3395` CRS (by [@Savvkin](https://github.com/Savvkin)). [#358](https://github.com/Leaflet/Leaflet/pull/358) + +#### Browser bugfixes + + * Fixed occasional crashes on Mac Safari (thanks to [@lapinos03](https://github.com/lapinos03)). [#191](https://github.com/Leaflet/Leaflet/issues/191) + * Fixed a bug where resizing the map would sometimes make it blurry on WebKit (by [@mortenbekditlevsen](https://github.com/mortenbekditlevsen)). [#453](https://github.com/Leaflet/Leaflet/pull/453) + * Fixed a bug that raised error in IE6-8 when clicking on popup close button. [#235](https://github.com/Leaflet/Leaflet/issues/235) + * Fixed a bug with Safari not redrawing UI immediately after closing a popup. [#296](https://github.com/Leaflet/Leaflet/issues/296) + * Fixed a bug that caused performance drop and high CPU usage when calling `setView` or `panTo` to the current center. [#231](https://github.com/Leaflet/Leaflet/issues/231) + * Fixed a bug that caused map overlays to appear blurry in some cases under WebKit browsers. + * Fixed a bug that was causing errors in some Webkit/Linux builds (requestAnimationFrame-related), thanks to Chris Martens. + +#### Mobile browser bugfixes + + * Fixed a bug that caused an error when clicking vector layers under iOS. [#204](https://github.com/Leaflet/Leaflet/issues/204) + * Fixed crash on Android 3+ when panning or zooming (by [@florian](https://github.com/florianf)). [#137](https://github.com/Leaflet/Leaflet/issues/137) + * Fixed a bug on Android 2/3 that sometimes caused the map to disappear after zooming. [#69](https://github.com/Leaflet/Leaflet/issues/69) + * Fixed a bug on Android 3 that caused tiles to shift position on a big map. + * Fixed a bug that caused the map to pan when touch-panning inside a popup. [#452](https://github.com/Leaflet/Leaflet/issues/452) + * Fixed a bug that caused click delays on zoom control. + + +## 0.2.1 (2011-06-18) + + * Fixed regression that caused error in `TileLayer.Canvas`. + +## 0.2 (2011-06-17) + +### Major features + + * Added **WMS** support (`TileLayer.WMS` layer). + * Added different **projections** support, having `EPSG:3857`, `EPSG:4326` and `EPSG:3395` out of the box (through `crs` option in `Map`). Thanks to [@Miroff](https://github.com/Miroff) & [@Komzpa](https://github.com/Komzpa) for great advice and explanation regarding this. + * Added **GeoJSON** layer support. + +### Improvements + +#### Usability improvements + + * Improved panning performance in Chrome and FF considerably with the help of `requestAnimationFrame`. [#130](https://github.com/Leaflet/Leaflet/issues/130) + * Improved click responsiveness in mobile WebKit (now it happens without delay). [#26](https://github.com/Leaflet/Leaflet/issues/26) + * Added tap tolerance (so click happens even if you moved your finger slighly when tapping). + * Improved geolocation error handling: better error messages, explicit timeout, set world view on locateAndSetView failure. [#61](https://github.com/Leaflet/Leaflet/issues/61) + +#### API improvements + + * Added **MultiPolyline** and **MultiPolygon** layers. [#77](https://github.com/Leaflet/Leaflet/issues/77) + * Added **LayerGroup** and **FeatureGroup** layers for grouping other layers. + * Added **TileLayer.Canvas** for easy creation of canvas-based tile layers. + * Changed `Circle` to be zoom-dependent (with radius in meters); circle of a permanent size is now called `CircleMarker`. + * Added `mouseover` and `mouseout` events to map, markers and paths; added map `mousemove` event. + * Added `setLatLngs`, `spliceLatLngs`, `addLatLng`, `getLatLngs` methods to polylines and polygons. + * Added `setLatLng` and `setRadius` methods to `Circle` and `CircleMarker`. + * Improved `LatLngBounds contains` method to accept `LatLng` in addition to `LatLngBounds`, the same for `Bounds contains` and `Point` + * Improved `LatLngBounds` & `Bounds` to allow their instantiation without arguments (by [@snc](https://github.com/snc)). + * Added TMS tile numbering support through `TileLayer` `scheme: 'tms'` option (by [@tmcw](https://github.com/tmcw)). + * Added `TileLayer` `noWrap` option to disable wrapping `x` tile coordinate (by [@jasondavies](https://github.com/jasondavies)). + * Added `opacity` option and `setOpacity` method to `TileLayer`. + * Added `setLatLng` and `setIcon` methods to `Marker`. + * Added `title` option to `Marker`. + * Added `maxZoom` argument to `map.locateAndSetView` method. + * Added ability to pass Geolocation options to map `locate` and `locateAndSetView` methods (by [@JasonSanford](https://github.com/JasonSanford)). + * Improved `Popup` to accept HTML elements in addition to strings as its content. + +#### Development workflow improvements + + * Added `Makefile` for building `leaflet.js` on non-Windows machines (by [@tmcw](https://github.com/tmcw)). + * Improved `debug/leaflet-include.js` script to allow using it outside of `debug` folder (by [@antonj](https://github.com/antonj)). + * Improved `L` definition to be compatible with CommonJS. [#122](https://github.com/Leaflet/Leaflet/issues/122) + +### Bug fixes + +#### General bugfixes + + * Fixed a bug where zooming is broken if the map contains a polygon and you zoom to an area where it's not visible. [#47](https://github.com/Leaflet/Leaflet/issues/47) + * Fixed a bug where closed polylines would not appear on the map. + * Fixed a bug where marker that was added, removed and then added again would not appear on the map. [#66](https://github.com/Leaflet/Leaflet/issues/66) + * Fixed a bug where tile layer that was added, removed and then added again would not appear on the map. + * Fixed a bug where some tiles would not load when panning across the date line. [#97](https://github.com/Leaflet/Leaflet/issues/97) + * Fixed a bug where map div with `position: absolute` is reset to `relative`. [#100](https://github.com/Leaflet/Leaflet/issues/100) + * Fixed a bug that caused an error when trying to add a marker without shadow in its icon. + * Fixed a bug where popup content would not update on `setContent` call. [#94](https://github.com/Leaflet/Leaflet/issues/94) + * Fixed a bug where double click zoom wouldn't work if popup is opened on map click + * Fixed a bug with click propagation on popup close button. [#99](https://github.com/Leaflet/Leaflet/issues/99) + * Fixed inability to remove ImageOverlay layer. + +#### Browser bugfixes + + * Fixed a bug where paths would not appear in IE8. + * Fixed a bug where there were occasional slowdowns before zoom animation in WebKit. [#123](https://github.com/Leaflet/Leaflet/issues/123) + * Fixed incorrect zoom animation & popup styling in Opera 11.11. + * Fixed popup fade animation in Firefox and Opera. + * Fixed a bug where map isn't displayed in Firefox when there's an `img { max-width: 100% }` rule. + +#### Mobile browsers bugfixes + + * Fixed a bug that prevented panning on some Android 2.1 (and possibly older) devices. [#84](https://github.com/Leaflet/Leaflet/issues/84) + * Disabled zoom animation on Android by default because it's buggy on some devices (will be enabled back when it's stable enough). [#32](https://github.com/Leaflet/Leaflet/issues/32) + * Fixed a bug where map would occasionally break while multi-touch-zooming on iOS. [#32](https://github.com/Leaflet/Leaflet/issues/32) + * Fixed a bug that prevented panning/clicking on Android 3 tablets. [#121](https://github.com/Leaflet/Leaflet/issues/121) + * Fixed a bug that prevented panning/clicking on Opera Mobile. [#138](https://github.com/Leaflet/Leaflet/issues/138) + * Fixed potentional memory leak on WebKit when removing tiles, thanks to [@Scalar4eg](https://github.com/Scalar4eg). [#107](https://github.com/Leaflet/Leaflet/issues/107) + +## 0.1 (2011-05-13) + +Initial Leaflet release. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/CONTRIBUTING.md b/vendor/assets/javascripts/Leaflet-1.4.0/CONTRIBUTING.md new file mode 100644 index 000000000..bd2f1ed0f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/CONTRIBUTING.md @@ -0,0 +1,210 @@ +Contributing to Leaflet +======================= + + 1. [Getting Involved](#getting-involved) + 2. [Reporting Bugs](#reporting-bugs) + 3. [Contributing Code](#contributing-code) + 4. [Running the Tests](#running-the-tests) + 5. [Code Coverage](#code-coverage) + 6. [Improving Documentation](#improving-documentation) + 7. [Code of Conduct](#code-of-conduct) + 8. [Thank You](#thank-you) + +## Getting Involved + +Third-party patches are absolutely essential on our quest to create the best mapping library that will ever exist. +However, they're not the only way to get involved with Leaflet development. +You can help the project tremendously by discovering and [reporting bugs](#reporting-bugs); +[improving documentation](#improving-documentation); +helping others on [Stack Overflow](https://stackoverflow.com/questions/tagged/leaflet), +[GIS Stack Exchange](https://gis.stackexchange.com/questions/tagged/leaflet) +and [GitHub issues](https://github.com/Leaflet/Leaflet/issues); +tweeting to [@LeafletJS](http://twitter.com/LeafletJS); +and spreading the word about Leaflet among your colleagues and friends. + +## Reporting Bugs + +Before reporting a bug on the project's [issues page](https://github.com/Leaflet/Leaflet/issues), +first make sure that your issue is caused by Leaflet, not your application code +(e.g. passing incorrect arguments to methods, etc.). +Second, search the already reported issues for similar cases, +and if it's already reported, just add any additional details in the comments. + +After you've made sure that you've found a new Leaflet bug, +here are some tips for creating a helpful report that will make fixing it much easier and quicker: + + * Write a **descriptive, specific title**. Bad: *Problem with polylines*. Good: *Doing X in IE9 causes Z*. + * Include **browser, OS and Leaflet version** info in the description. + * Create a **simple test case** that demonstrates the bug (e.g. using [Leaflet plunker](http://leafletjs.com/edit.html)). + * Check whether the bug can be reproduced in **other browsers**. + * Check if the bug occurs in the stable version, master, or both. + * *Bonus tip:* if the bug only appears in the master version but the stable version is fine, + use `git bisect` to find the exact commit that introduced the bug. + +If you just want some help with your project, +try asking on [Stack Overflow](https://stackoverflow.com/questions/tagged/leaflet) +or [GIS Stack Exchange](https://gis.stackexchange.com/questions/tagged/leaflet) instead. + +## Contributing Code + +### Considerations for Accepting Patches + +While we happily accept patches, we're also committed to keeping Leaflet simple, lightweight and blazingly fast. +So bugfixes, performance optimizations and small improvements that don't add a lot of code +are much more likely to get accepted quickly. + +Before sending a pull request with a new feature, check if it's been discussed before already +on [GitHub issues](https://github.com/Leaflet/Leaflet/issues) +and ask yourself two questions: + + 1. Are you sure that this new feature is important enough to justify its presence in the Leaflet core? + Or will it look better as a plugin in a separate repository? + 2. Is it written in a simple, concise way that doesn't add bulk to the codebase? + +If your feature or API improvement did get merged into master, +please consider submitting another pull request with the corresponding [documentation update](#improving-documentation). + +### Setting up the Build System + +The Leaflet build system uses [NodeJS](http://nodejs.org/). +To set up the Leaflet build system, install [NodeJS](https://nodejs.org/). +Then run the following commands in the project root to install dependencies: + +``` +npm install +``` +or, if you prefer [`yarn`](https://yarnpkg.com/) over `npm`: +``` +yarn install +``` + +### Making Changes to Leaflet Source + +If you're not yet familiar with the way GitHub works (forking, pull requests, etc.), +be sure to check out the awesome [article about forking](https://help.github.com/articles/fork-a-repo) +on the GitHub Help website — it will get you started quickly. + +You should always write each batch of changes (feature, bugfix, etc.) in **its own topic branch**. +Please do not commit to the `master` branch, or your unrelated changes will go into the same pull request. + +You should also follow the code style and whitespace conventions of the original codebase. +In particular, use tabs for indentation and spaces for alignment. + +Before committing your changes, run `npm run lint` to catch any JS errors in the code and fix them. +If you add any new files to the Leaflet source, make sure to also add them to `build/deps.js` +so that the build system knows about them. + +Also, please make sure that you have [line endings configured properly](https://help.github.com/articles/dealing-with-line-endings) in Git! Otherwise the diff will show that all lines of a file were changed even if you touched only one. + +Happy coding! + +### Using RollupJS + +The source JavaScript code for Leaflet is a few dozen files, in the `src/` directory. +But normally, Leaflet is loaded in a web browser as just one JavaScript file. + +In order to create this file, run `npm run rollup` or `yarn run rollup`. + +You'll find `dist/leaflet-src.js` and `dist/leaflet.js`. The difference is that +`dist/leaflet-src.js` has sourcemaps and it's not uglified, so it's better for +development. `dist/leaflet.js` is uglified and thus is smaller, so it's better +for deployment. + +When developing (or bugfixing) core Leaflet functionalities, it's common to use +the webpages in the `debug/` directory, and run the unit tests (`spec/index.html`) +in a graphical browser. This requires regenerating the bundled files quickly. + +In order to do so, run `npm run watch` or `yarn run watch`. This will keep +on rebuilding the bundles whenever any source file changes. + +## Running the Tests + +To run the tests from the command line, +install [PhantomJS](http://phantomjs.org/) (and make sure it's in your `PATH`), +then run: + +``` +npm test +``` + +To run all the tests in actual browsers at the same time, you can do: + +``` +npm test -- -- --browsers Firefox,Chrome,Safari,IE +``` + +(Note: the doubling of "`--`" [special option](https://docs.npmjs.com/cli/run-script#description) is [important](https://github.com/Leaflet/Leaflet/pull/6166#issuecomment-390959903)) + +To run the tests in a browser manually, open `spec/index.html`. + +## Code Coverage + +To generate a detailed report about test coverage (which helps tremendously when working on test improvements), run: + +``` +npm test -- --cov +``` + +After that, open `coverage//index.html` in a browser to see the report. +From there you can click through folders/files to get details on their individual coverage. + +## Improving Documentation + +The code of the live Leaflet website that contains all documentation and examples is located in the `docs/` directory of the `master` branch +and is automatically generated from a set of HTML and Markdown files by [Jekyll](http://jekyllrb.com/). + +The easiest way to make little improvements such as fixing typos without even leaving the browser +is by editing one of the files with the online GitHub editor: +browse the [`docs/ directory`](https://github.com/Leaflet/Leaflet/tree/master/docs), +choose a certain file for editing (e.g. `plugins.md` for the list of Leaflet plugins), +click the Edit button, make changes and follow instructions from there. +Once it gets merged, the changes will immediately appear on the website. + +If you need to make edits in a local repository to see how it looks in the process, do the following: + + 1. [Install Ruby](http://www.ruby-lang.org/en/) if don't have it yet. + 2. Run `gem install jekyll`. + 3. Enter the directory where you cloned the Leaflet repository + 4. Run `bundle install` + 5. Make sure you are in the `master` branch by running `git checkout master` + 6. Enter the documentation subdirectory by running `cd docs` + 7. Run `jekyll serve --watch`. + 8. Open `localhost:4000` in your web browser. + +Now any file changes will be updated when you reload pages automatically. +After committing the changes, just send a pull request. + +### API documentation + +Since Leaflet 1.0.0-rc1, the API documentation in `reference-1.0.0.html` is handled +via [Leafdoc](https://github.com/Leaflet/Leafdoc). This means that next to the +code for every method, option or property there is a special code comment documenting +that feature. In order to edit the API documentation, just edit these comments in the +source code. + +In order to generate the documentation, make sure that the development dependencies +are installed (run either `npm install` or `yarn install`), then just run + +``` +npm run docs +``` + +and you'll find a `.html` file in the `dist/` directory. + +On every release of a new Leaflet version, this file will be generated and copied +over to `docs/reference.html` - there is no need to send pull requests with changes to this file to update the API documentation. + +## Code of Conduct + +Everyone is invited to participate in the Leaflet community and related projects: +we want to create a welcoming and friendly environment. +Harassment of participants or other unethical and unprofessional behavior will not be tolerated in our spaces. +The [Contributor Covenant](http://contributor-covenant.org/version/1/3/0/) +applies to all projects under the Leaflet organization. +Report any issues to agafonkin@gmail.com. + +## Thank You + +Not only does your contribution to Leaflet and its community earn our gratitude, but it also makes you AWESOME. +Join [this approved list of awesome people](https://github.com/Leaflet/Leaflet/graphs/contributors) +and help us push the limits of what's possible with online maps! diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/FAQ.md b/vendor/assets/javascripts/Leaflet-1.4.0/FAQ.md new file mode 100644 index 000000000..c4d0ee636 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/FAQ.md @@ -0,0 +1,141 @@ +# Leaflet FAQ + +This is a collection of answers to the most frequently asked questions about Leaflet. + + 1. [Data Providers](#data-providers) + 2. [Commercial Use and Licensing](#commercial-use-and-licensing) + 3. [Features](#features) + 4. [Performance](#performance) + 5. [Misc](#misc) + +## Data Providers + +#### The map is wrong in my neighborhood, could you fix it? + +Nope, but you can. +The map you see on Leaflet examples is based on [OpenStreetMap](http://openstreetmap.org), +a free editable map of the world. +Signing up and editing the map there is easy, +and the changes will be reflected on the map in a few minutes. + +#### What map tiles can I use with Leaflet? Is it limited to OpenStreetMap? + +Leaflet is provider-agnostic, meaning you can use any map provider as long as you conform to its terms of use. +You can roll your own tiles as well. +[OpenStreetMap](http://openstreetmap.org) is the most popular data source among different tile providers, +but there are providers that use other sources. + +Check out [this example](http://leaflet-extras.github.io/leaflet-providers/preview/) +with over seventy different layers to choose from. +Popular commercial options, free up to a particular number of requests, include +[MapBox](http://mapbox.com), +[Bing Maps](http://www.microsoft.com/maps/choose-your-bing-maps-API.aspx) (using a [plugin](https://github.com/shramov/leaflet-plugins)), +[Esri ArcGIS](http://www.esri.com/software/arcgis/arcgisonline/maps/maps-and-map-layers) ([official plugin](https://github.com/Esri/esri-leaflet)), +[MapQuest](https://developer.mapquest.com/products) ([official plugins](https://developer.mapquest.com/documentation/leaflet-plugins)) +and [Here Maps](https://developer.here.com/). + +Always be sure to **read the terms of use** of a chosen tile provider, **know its limitations**, and **attribute it properly** in your app. + +#### I'm looking for satellite imagery to use with my Leaflet map, any options? + +[MapBox](http://mapbox.com), +[Bing Maps](http://www.microsoft.com/maps/choose-your-bing-maps-API.aspx), +[ArcGIS](http://www.esri.com/software/arcgis/arcgisonline/maps/maps-and-map-layers) +and [MapQuest Open](http://developer.mapquest.com/web/products/open/map) provide satellite imagery among others. + +#### I want to use Google Maps API tiles with Leaflet, can I do that? + +The problem with Google is that its [Terms of Use](https://developers.google.com/maps/terms) forbid any means of tile access other than through the Google Maps API. + +You can add the Google Maps API as a Leaflet layer with the [GoogleMutant plugin](https://gitlab.com/IvanSanchez/Leaflet.GridLayer.GoogleMutant). But note that the map experience will not be perfect, because Leaflet must wait for the Google Maps JS engine to load the map tiles, so you might experience glitches and lagging when using it. + +#### I want to roll my own OSM tile server for Leaflet, where do I start? + +Check out [this excellent guide](http://switch2osm.org/serving-tiles/). + +#### I want to create tiles from my own data for use with Leaflet, what are the options? + +There's a number of services that allow you to do this easily, +notably [MapBox](https://www.mapbox.com/), [CartoDB](http://cartodb.com/) and [GIS Cloud](http://www.giscloud.com/). +If you want to make tiles on your own, probably the easiest way is using [TileMill](https://www.mapbox.com/tilemill/). +TileMill can export your map as a single [.mbtiles](https://www.mapbox.com/developers/mbtiles/) file, which can be copied to a webserver and accessed by Leaflet with [a small PHP script](https://github.com/infostreams/mbtiles-php). +Alternatively, you can [extract](https://github.com/mapbox/mbutil) the tiled images from the .mbtiles database and place them directly on your webserver with absolutely no server-side dependencies. + +## Commercial Use and Licensing + +#### I have an app that gets lots of hits a day, and I want to switch from Google/Bing/whatever to Leaflet. Is there a fee for using it? + +Leaflet, unlike Google Maps and other all-in-one solutions, is just a JavaScript library. +It's free to use, but doesn't provide map imagery on its own — +you have to choose a tile service to combine with it. + +There are [plenty of options](#what-map-tiles-can-i-use-with-leaflet-is-it-limited-to-openstreetmap) for a tile service, +each with their own terms of use, prices (some of them free), features, limitations, etc. +Choice is yours. + +#### I'm building a commercial app that I plan to sell. Can I use Leaflet in it? + +You're welcome, as the code is published under the very permissive [2-clause BSD License](https://github.com/Leaflet/Leaflet/blob/master/LICENSE). +Just make sure to attribute the use of the library somewhere in the app UI or the distribution +(e.g. keep the Leaflet link on the map, or mention the use on the About page or a Readme file, etc.) and you'll be fine. + +That only applies to the code though. +Make sure you conform to the terms of use of the tile images provider(s) that you choose as well. + + +## Features + +#### What's the best way to put the data I have on a Leaflet map? + +Check out [this awesome cheatsheet](https://github.com/tmcw/mapmakers-cheatsheet). + +#### Why is there still no feature X in Leaflet? + +First of all, did you check out the [Leaflet plugins page](http://leafletjs.com/plugins.html)? +It lists about a hundred plugins doing all kinds of crazy stuff, +and there's a high possibility that it has what you're looking for. + +Generally, we do our best to keep the Leaflet core small, lightweight and simple, +focusing on _quality_ instead of _quantity_, and leaving all the rest to plugin authors. + +Check out [this video](http://www.youtube.com/watch?v=_P2SaCPbJ4w) of a talk by the Leaflet creator for more background on the story and philosophy behind Leaflet. +Another essential read is [Advocating Simplicity in Open Source](http://blog.universalmind.com/advocating-simplicity-in-open-source/) by the same guy. + + +## Performance + +#### I have thousands of markers on my map. How do I make it faster and more usable? + +Check out the [Leaflet.markercluster](https://github.com/Leaflet/Leaflet.markercluster) plugin. It's amazing. + +#### I have vector data with many thousands of points on my map. Any performance tips? + +Leaflet generally does a pretty good job of handling heavy vector data +with its real-time clipping and simplification algorithms, +but browser technology still has its limits. +Try [switching from SVG to Canvas as the default rendering back-end](http://leafletjs.com/reference.html#global), +it may help considerably (depends on the app and the data). + +If you still have too much data to render, you'll have to use some help of a server-side service +like [MapBox](https://www.mapbox.com/), +[CartoDB](http://cartodb.com/) +and [GIS Cloud](http://www.giscloud.com/) +(they all work great with Leaflet). +What they do under the hood is serving rendered data as image tiles, +along with additional data to enable interactivity like hovering shapes +(e.g. done using [UTFGrid](https://www.mapbox.com/developers/utfgrid/) — +Leaflet [has a nice plugin](https://github.com/danzel/Leaflet.utfgrid) for it). + + +## Misc + +#### I downloaded the Leaflet source but didn't find `leaflet.js` there. Why is that? + +You can download the built versions using links from the [download page](http://leafletjs.com/download.html). +It even includes the latest build of the development version (`master` branch), +updated automatically on each commit to the repo. + +We removed the built versions from the repository because it's a chore to build and commit them manually on each change, +and it often complicates merging branches and managing contributions. + +There's a common complaint that Leaflet can't be used with [Bower](http://bower.io/) because of that, but we'll resolve the issue soon. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/LICENSE b/vendor/assets/javascripts/Leaflet-1.4.0/LICENSE new file mode 100644 index 000000000..3bc5660a3 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2010-2018, Vladimir Agafonkin +Copyright (c) 2010-2011, CloudMade +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/PLUGIN-GUIDE.md b/vendor/assets/javascripts/Leaflet-1.4.0/PLUGIN-GUIDE.md new file mode 100644 index 000000000..d337ac0d7 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/PLUGIN-GUIDE.md @@ -0,0 +1,221 @@ +# Leaflet Plugin Authoring Guide + +One of the greatest things about Leaflet is its powerful plugin ecosystem. +The [Leaflet plugins page](http://leafletjs.com/plugins.html) lists dozens of awesome plugins, and more are being added every week. + +This guide lists a number of best practices for publishing a Leaflet plugin that meets the quality standards of Leaflet itself. + +1. [Presentation](#presentation) + - [Repository](#repository) + - [Name](#name) + - [Demo](#demo) + - [Readme](#readme) + - [License](#license) +2. [Code](#code) + - [File Structure](#file-structure) + - [Code Conventions](#code-conventions) + - [Plugin API](#plugin-api) +3. [Publishing on NPM](#publishing-on-npm) +4. [Module Loaders](#module-loaders) +5. [Adding to the plugins list](#adding-to-the-plugins-list) + +## Presentation + +### Repository + +The best place to put your Leaflet plugin is a separate [GitHub](http://github.com) repository. +If you create a collection of plugins for different uses, +don't put them in one repo — +it's usually easier to work with small, self-contained plugins in individual repositories. + +### Name + +Most existing plugins follow the convention of naming plugins (and repos) like this: `Leaflet.MyPluginName`. +You can use other forms (e.g. "leaflet-my-plugin-name"), +just make sure to include the word "Leaflet" in the name so that it's obvious that it's a Leaflet plugin. + +### Demo + +The most essential thing to do when publishing a plugin is to include a demo that showcases what the plugin does — +it's usually the first thing people will look for. + +The easiest way to put up a demo is using [GitHub Pages](http://pages.github.com/). +A good [starting point](https://help.github.com/articles/creating-project-pages-manually) is creating a `gh-pages` branch in your repo and adding an `index.html` page to it — +after pushing, it'll be published as `http://.github.io/`. + +### Readme + +The next thing you need to have is a [good `README.md`](https://github.com/noffle/art-of-readme) in the root of the repo (or a link to a website with a similar content). +At a minimum it should contain the following items: + +- name of the plugin +- a simple, concise description of what it does +- requirements + - Leaflet version + - other external dependencies (if any) + - browser / device compatibility +- links to demos +- instructions for including the plugin +- simple usage code example +- API reference (methods, options, events) + +### License + +Every open source repository should include a license. +If you don't know what open source license to choose for your code, +[MIT License](http://opensource.org/licenses/MIT) and [BSD 2-Clause License](http://opensource.org/licenses/BSD-2-Clause) are both good choices. +You can either put it in the repo as a `LICENSE` file or just link to the license from the Readme. + +## Code + +### File Structure + +Keep the file structure clean and simple, +don't pile up lots of files in one place — +make it easy for a new person to find their way in your repo. + +A barebones repo for a simple plugin would look like this: + +``` +my-plugin.js +README.md +``` + +An example of a more sophisticated plugin file structure: + +``` +/src - JS source files +/dist - minified plugin JS, CSS, images +/spec - test files +/lib - any external libraries/plugins if necessary +/examples - HTML examples of plugin usage +README.md +LICENSE +package.json +``` + +### Code Conventions + +Everyone's tastes are different, but it's important to be consistent with whatever conventions you choose for your plugin. + +For a good starting point, check out [Airbnb JavaScript Guide](https://github.com/airbnb/javascript). +Leaflet follows pretty much the same conventions +except for using smart tabs (hard tabs for indentation, spaces for alignment) +and putting a space after the `function` keyword. + +### Plugin API + +Never expose global variables in your plugin.
+If you have a new class, put it directly in the `L` namespace (`L.MyPlugin`).
+If you inherit one of the existing classes, make it a sub-property (`L.TileLayer.Banana`).
+Every class should have a factory function in camelCase, e.g. (`L.tileLayer.banana`).
+If you want to add new methods to existing Leaflet classes, you can do it like this: `L.Marker.include({myPlugin: …})`. + +Function, method, property and factory names should be in `camelCase`.
+Class names should be in `CapitalizedCamelCase`. + +If you have a lot of arguments in your function, consider accepting an options object instead +(putting default values where possible so that users don't need to specify all of them): + +```js +// bad +marker.myPlugin('bla', 'foo', null, {}, 5, 0); + + // good +marker.myPlugin('bla', { + optionOne: 'foo', + optionThree: 5 +}); +``` + +And most importantly, keep it simple. Leaflet is all about *simplicity*. + +## Publishing on NPM + +NPM (Node Packaged Modules) is a package manager and code repository for JavaScript. Publishing your module on NPM allows other developers to quickly find and install your plugin as well as any other plugins it depends on. + +NPM has an excellent [developers guide](https://www.npmjs.org/doc/misc/npm-developers.html) to help you through the process. + +When you publish your plugin you should add a dependency on `leaflet` to your `package.json` file. This will automatically install Leaflet when your package is installed. + +Here is an example of a `package.json` file for a Leaflet plugin. + +```json +{ + "name": "my-leaflet-plugin", + "version": "1.0.0", + "description": "A simple leaflet plugin.", + "main": "my-plugin.js", + "author": "You", + "license": "IST", + "peerDependencies": { + "leaflet": "^1.0.0" + } +} +``` + +If possible, do not commit your minified files (e.g. `dist`) to a repo; this can +lead to confusion when trying to debug the wrong file. Instead, use `npm` to +trigger a build/minification just before publishing your package with a +[`prepublish` script](https://docs.npmjs.com/misc/scripts#common-uses), for example: + +```json +{ + "name": "my-leaflet-plugin", + ... + "scripts": { + "prepublish": "grunt build" + } +} +``` + +You can then use the [`.gitignore`](https://help.github.com/articles/ignoring-files/) +file to make sure the minified files are not versioned, and an +[empty `.npmignore`](https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package) +to ensure that they are published to NPM. + +## Module Loaders + +Module loaders such as [RequireJS](http://requirejs.org/) and [Browserify](http://browserify.org/) implement module systems like AMD (Asynchronous Module Definition) and CommonJS to allow developers to modularize and load their code. + +You can add support for AMD/CommonJS loaders to your Leaflet plugin by following this pattern based on the [Universal Module Definition](https://github.com/umdjs/umd/blob/master/templates/returnExportsGlobal.js) + +```js +(function (factory, window) { + + // define an AMD module that relies on 'leaflet' + if (typeof define === 'function' && define.amd) { + define(['leaflet'], factory); + + // define a Common JS module that relies on 'leaflet' + } else if (typeof exports === 'object') { + module.exports = factory(require('leaflet')); + } + + // attach your plugin to the global 'L' variable + if (typeof window !== 'undefined' && window.L) { + window.L.YourPlugin = factory(L); + } +}(function (L) { + var MyLeafletPlugin = {}; + // implement your plugin + + // return your plugin when you are done + return MyLeafletPlugin; +}, window)); +``` + +Now your plugin is available as an AMD and CommonJS module and can be used in module loaders like Browserify and RequireJS. + + +## Adding to the plugins list + +Once your plugin is published, it is a good idea to add it to the [Leaflet plugins list](http://leafletjs.com/plugins.html). To do so: + +* [Fork](https://help.github.com/articles/fork-a-repo/) the Leaflet repo. +* In the `docs/plugins.md` file, find the section your plugin should go in, and add a table row with information and links about your plugin. +* Commit the code to your fork. +* [Open a pull request](https://help.github.com/articles/creating-a-pull-request/) from your fork to Leaflet's original repo. + +Once the pull request is done, a Leaflet maintainer will have a quick look at your +plugin and, if everything looks right, your plugin will appear in the list shortly thereafter. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/README.md b/vendor/assets/javascripts/Leaflet-1.4.0/README.md new file mode 100644 index 000000000..81d7736a2 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/README.md @@ -0,0 +1,32 @@ +Leaflet + +Leaflet is the leading open-source JavaScript library for **mobile-friendly interactive maps**. +Weighing just about 37 KB of gzipped JS code, it has all the mapping [features][] most developers ever need. + +Leaflet is designed with *simplicity*, *performance* and *usability* in mind. +It works efficiently across all major desktop and mobile platforms out of the box, +taking advantage of HTML5 and CSS3 on modern browsers while being accessible on older ones too. +It can be extended with a huge amount of [plugins][], +has a beautiful, easy to use and [well-documented][] API +and a simple, readable [source code][] that is a joy to [contribute][] to. + +For more info, docs and tutorials, check out the [official website][].
+For **Leaflet downloads** (including the built master version), check out the [download page][]. + +We're happy to meet new contributors. +If you want to **get involved** with Leaflet development, check out the [contribution guide][contribute]. +Let's make the best mapping library that will ever exist, +and push the limits of what's possible with online maps! + +[![Build Status](https://travis-ci.org/Leaflet/Leaflet.svg?branch=master)](https://travis-ci.org/Leaflet/Leaflet) + + [contributors]: https://github.com/Leaflet/Leaflet/graphs/contributors + [features]: http://leafletjs.com/#features + [plugins]: http://leafletjs.com/plugins.html + [well-documented]: http://leafletjs.com/reference.html "Leaflet API reference" + [source code]: https://github.com/Leaflet/Leaflet "Leaflet GitHub repository" + [hosted on GitHub]: http://github.com/Leaflet/Leaflet + [contribute]: https://github.com/Leaflet/Leaflet/blob/master/CONTRIBUTING.md "A guide to contributing to Leaflet" + [official website]: http://leafletjs.com + [download page]: http://leafletjs.com/download.html + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/RELEASE.md b/vendor/assets/javascripts/Leaflet-1.4.0/RELEASE.md new file mode 100644 index 000000000..96f54c025 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/RELEASE.md @@ -0,0 +1,29 @@ +Documentation for the release process of Leaflet. + +**Please note that you will need to have a git remote called `origin` that points to Leaflet's GitHub repo, since the publish script assumes it** +- [ ] Make a new release branch (for example named `prepare-X.Y.Z`) +- [ ] Make sure you do not have any `package.lock.json` or `yarn.lock` locally, since they can potentially make you build with the wrong package versions +- [ ] Update [the changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md) since last release and commit to the release branch +- [ ] Write a blog post about the new release and put in `/docs/_posts` and commit to the release branch +- [ ] Bump version number in `package.json` and commit to `master` +- [ ] Run `npm run release` +- [ ] Verify that the release was correctly published to NPM by checking: + - [ ] [Leaflet NPM package page](https://www.npmjs.com/package/leaflet) + - [ ] files on [Leaflet unpkg page](https://unpkg.com/leaflet@latest/) +- [ ] Update API docs: + - [ ] run `npm run docs` + - [ ] Copy the built docs from `dist/reference-X.Y.Z.html` to `docs/reference-X.Y.Z.html` + - [ ] Update the built docs header to use Jekyll style; see commit [11d716f0964d8bc0d058ca09e9ba8003451b4b8d](https://github.com/Leaflet/Leaflet/commit/11d716f0964d8bc0d058ca09e9ba8003451b4b8d) as reference for the needed changes + - [ ] Commit the new docs to the release branch +- [ ] Update `docs/reference.html` to redirect to the new version and commit the change to the release branch +- [ ] Update integrity hashes: + - [ ] Checkout the release tag (`git checkout vX.Y.Z`) + - [ ] Run `npm run integrity` or simply `node ./build/integrity.js` if you're not on Debian + - [ ] Copy the hashes and update `integrity_hash_css`, `integrity_hash_source` and `integrity_hash_uglified` in `docs/_config.yml`; commit changes to the release branch +- [ ] Update link to latest release in `docs/download.html`, and commit to the release branch +- [ ] Add link to new version reference in `docs/reference-versions.html`, and commit to the release branch +- [ ] Update `latest_leaflet_version` in `docs/_config.yml` and commit to the release branch +- [ ] Update the announcement section in `docs/index.html` and commit to the release branch +- [ ] If it looks like everything is good at this point, merge the release branch into `master` +- [ ] Make a new release on [Leaflet's GitHub release page](https://github.com/Leaflet/Leaflet/releases/) with the most important parts of the changelog +- [ ] Post an announcement comment in [thread #6295](https://github.com/Leaflet/Leaflet/issues/6295) diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/docs-index.leafdoc b/vendor/assets/javascripts/Leaflet-1.4.0/build/docs-index.leafdoc new file mode 100644 index 000000000..67e75a4a6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/docs-index.leafdoc @@ -0,0 +1,63 @@ +This file just defines the order of the classes in the docs. + + + + +@class Map + +@class Marker +@class Popup +@class Tooltip + +@class TileLayer +@class TileLayer.WMS +@class ImageOverlay +@class VideoOverlay + +@class Path +@class Polyline +@class Polygon +@class Rectangle +@class Circle +@class CircleMarker +@class SVG +@class Canvas + +@class LayerGroup +@class FeatureGroup +@class GeoJSON +@class GridLayer + +@class LatLng +@class LatLngBounds +@class Point +@class Bounds +@class Icon +@class DivIcon + +@class Control.Zoom +@class Control.Attribution +@class Control.Layers +@class Control.Scale + +@class Browser +@class Util +@class Transformation +@class LineUtil +@class PolyUtil + +@class DomEvent +@class DomUtil +@class PosAnimation +@class Draggable + +@class Class +@class Evented +@class Layer +@class Interactive layer +@class Control +@class Handler +@class Projection +@class CRS +@class Renderer +@class Event objects diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/docs-misc.leafdoc b/vendor/assets/javascripts/Leaflet-1.4.0/build/docs-misc.leafdoc new file mode 100644 index 000000000..a9082c405 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/docs-misc.leafdoc @@ -0,0 +1,51 @@ +Miscellaneous bits of documentation that don't really fit anywhere else + + + +@namespace Global Switches + +Global switches are created for rare cases and generally make +Leaflet to not detect a particular browser feature even if it's +there. You need to set the switch as a global variable to true +before including Leaflet on the page, like this: + +```html + + +``` + +| Switch | Description | +| -------------- | ---------------- | +| `L_NO_TOUCH` | Forces Leaflet to not use touch events even if it detects them. | +| `L_DISABLE_3D` | Forces Leaflet to not use hardware-accelerated CSS 3D transforms for positioning (which may cause glitches in some rare environments) even if they're supported. | + + +@namespace noConflict + +This method restores the `L` global variable to the original value +it had before Leaflet inclusion, and returns the real Leaflet +namespace so you can put it elsewhere, like this: + +```html + +``` + + +@namespace version + +A constant that represents the Leaflet version in use. + +```js +L.version; // contains "1.0.0" (or whatever version is currently in use) +``` + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/docs.js b/vendor/assets/javascripts/Leaflet-1.4.0/build/docs.js new file mode 100755 index 000000000..fbc0e268b --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/docs.js @@ -0,0 +1,40 @@ +var packageDef = require('../package.json'); + +function buildDocs() { + + console.log('Building Leaflet documentation with Leafdoc'); + + var LeafDoc = require('leafdoc'); + var doc = new LeafDoc({ + templateDir: 'build/leafdoc-templates', + showInheritancesWhenEmpty: true, + leadingCharacter: '@' + }); + + // Note to Vladimir: Iván's never gonna uncomment the following line. He's + // too proud of the little leaves around the code. + //doc.setLeadingChar('@'); + + // Leaflet uses a couple of non-standard documentable things. They are not + // important enough to be classes/namespaces of their own, and should + // just be listed in a table like the rest of documentables: + doc.registerDocumentable('pane', 'Map panes'); + doc.registerDocumentable('projection', 'Defined projections'); + doc.registerDocumentable('crs', 'Defined CRSs'); + + doc.addFile('build/docs-index.leafdoc', false); + doc.addDir('src'); + doc.addFile('build/docs-misc.leafdoc', false); + + var out = doc.outputStr(); + + var fs = require('fs'); + + fs.writeFileSync('dist/reference-' + packageDef.version + '.html', out); +} + +if (require.main === module) { + buildDocs(); +} else { + module.exports = buildDocs; +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/integrity.js b/vendor/assets/javascripts/Leaflet-1.4.0/build/integrity.js new file mode 100755 index 000000000..d6d92076c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/integrity.js @@ -0,0 +1,28 @@ +// This script calculates the integrity hashes of the files in dist/ , and +// **overwrites** the values in the documentation. + +var ssri = require('ssri'); +var fs = require('fs'); +var version = require('../package.json').version; + +const integritySrc = ssri.fromData(fs.readFileSync('dist/leaflet-src.js')); +const integrityUglified = ssri.fromData(fs.readFileSync('dist/leaflet.js')); +const integrityCss = ssri.fromData(fs.readFileSync('dist/leaflet.css')); + + +console.log('Integrity hashes for ', version, ':'); +console.log('dist/leaflet-src.js: ', integritySrc.toString()); +console.log('dist/leaflet.js: ', integrityUglified.toString()); +console.log('dist/leaflet.css: ', integrityCss.toString()); + +var docConfig = fs.readFileSync('docs/_config.yml').toString(); + +docConfig = docConfig. + replace(/latest_leaflet_version:.*/, 'latest_leaflet_version: ' + version). + replace(/integrity_hash_source:.*/, 'integrity_hash_source: "' + integritySrc.toString() + '"'). + replace(/integrity_hash_uglified:.*/, 'integrity_hash_uglified: "' + integrityUglified.toString() + '"'). + replace(/integrity_hash_css:.*/, 'integrity_hash_css: "' + integrityCss.toString() + '"'); + +// console.log('New jekyll docs config: \n', docConfig); + +fs.writeFileSync('docs/_config.yml', docConfig); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/comments.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/comments.hbs new file mode 100644 index 000000000..8faffef07 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/comments.hbs @@ -0,0 +1 @@ +{{{rawmarkdown comments}}} \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/constructor.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/constructor.hbs new file mode 100644 index 000000000..eef26ad26 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/constructor.hbs @@ -0,0 +1,17 @@ + + + + + + + {{#each documentables}} + + + + + {{/each}} +
ConstructorDescription
{{name}}( + {{~#each params~}} + {{#if type}}<{{{type type}}}> {{/if}}{{name}} + {{~#unless @last}}, {{/unless}}{{/each~}} + ){{{markdown comments}}}
diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/crs.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/crs.hbs new file mode 100644 index 000000000..e28758703 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/crs.hbs @@ -0,0 +1,13 @@ + + + + + + + {{#each documentables}} + + + + + {{/each}} +
CRSDescription
{{name}}{{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/destructor.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/destructor.hbs new file mode 100644 index 000000000..78ab70a07 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/destructor.hbs @@ -0,0 +1,17 @@ + + + + + + + {{#each documentables}} + + + + + {{/each}} +
DestructorDescription
{{name}}( + {{~#each params~}} + {{#if type}}<{{{type type}}}> {{/if}}{{name}} + {{~#unless @last}}, {{/unless}}{{/each~}} + ){{{markdown comments}}}
diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/event.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/event.hbs new file mode 100644 index 000000000..b55c22a14 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/event.hbs @@ -0,0 +1,15 @@ + + + + + + + + {{#each documentables}} + + + + + {{/each}} +
EventDataDescription
{{name}} + {{{type type}}}{{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/example.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/example.hbs new file mode 100644 index 000000000..7b63b4d5f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/example.hbs @@ -0,0 +1,4 @@ + +{{#each documentables}} +{{{rawmarkdown comments}}} +{{/each}} \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/factory.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/factory.hbs new file mode 100644 index 000000000..e3b4bfeb2 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/factory.hbs @@ -0,0 +1,17 @@ + + + + + + + {{#each documentables}} + + + + + {{/each}} +
FactoryDescription
{{name}}( + {{~#each params~}} + {{#if type}}<{{{type type}}}> {{/if}}{{name}} + {{~#unless @last}}, {{/unless}}{{/each~}} + ){{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/function.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/function.hbs new file mode 100644 index 000000000..d01d5615e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/function.hbs @@ -0,0 +1,19 @@ + + + + + + + + {{#each documentables}} + + + + + + {{/each}} +
FunctionReturnsDescription
{{name}}( + {{~#each params~}} + {{#if type}}<{{{type type}}}> {{/if}}{{name}} + {{~#unless @last}}, {{/unless}}{{/each~}} + ){{{type type}}}{{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/html.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/html.hbs new file mode 100644 index 000000000..978147532 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/html.hbs @@ -0,0 +1,319 @@ + + + + {{ title }} + + + + + + + + + + +
+ +

Leaflet API reference

+
+ +
+

UI Layers

+ +

Raster Layers

+ +

Vector Layers

+ +
+
+

Other Layers

+ +

Basic Types

+ +

Controls

+ +
+
+ + + + + + +

Utility

+ +

DOM Utility

+ +
+
+

Base Classes

+ + +

Misc

+ +
+
+ + {{{ body }}} + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/inherited.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/inherited.hbs new file mode 100644 index 000000000..405988829 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/inherited.hbs @@ -0,0 +1,7 @@ + +
+ +
+
{{{inherited}}}
+
+
diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/method.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/method.hbs new file mode 100644 index 000000000..865af0196 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/method.hbs @@ -0,0 +1,19 @@ + + + + + + + + {{#each documentables}} + + + + + + {{/each}} +
MethodReturnsDescription
{{name}}( + {{~#each params~}} + {{#if type}}<{{{type type}}}> {{/if}}{{name}} + {{~#unless @last}}, {{/unless}}{{/each~}} + ){{{type type}}}{{{rawmarkdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/namespace.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/namespace.hbs new file mode 100644 index 000000000..2a90a7010 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/namespace.hbs @@ -0,0 +1,7 @@ +{{#if name ~}} +

{{name}}

+{{~ else ~}} + +{{/if}} +{{{rawmarkdown comments}}} +{{{supersections}}} \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/option.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/option.hbs new file mode 100644 index 000000000..61d406591 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/option.hbs @@ -0,0 +1,17 @@ + + + + + + + + + {{#each documentables}} + + + + + + {{/each}} +
OptionTypeDefaultDescription
{{name}}{{{type type}}} + {{defaultValue}}{{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/pane.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/pane.hbs new file mode 100644 index 000000000..1e3ee9971 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/pane.hbs @@ -0,0 +1,17 @@ + + + + + + + + + {{#each documentables}} + + + + + + {{/each}} +
PaneTypeZ-indexDescription
{{name}}{{{type type}}} + {{defaultValue}}{{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/projection.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/projection.hbs new file mode 100644 index 000000000..dc2b9f286 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/projection.hbs @@ -0,0 +1,13 @@ + + + + + + + {{#each documentables}} + + + + + {{/each}} +
ProjectionDescription
{{name}}{{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/property.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/property.hbs new file mode 100644 index 000000000..ee4e9f2e7 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/property.hbs @@ -0,0 +1,15 @@ + + + + + + + + {{#each documentables}} + + + + + {{/each}} +
PropertyTypeDescription
{{name}} + {{{type type}}}{{{markdown comments}}}
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/section.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/section.hbs new file mode 100644 index 000000000..4aba7770e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/section.hbs @@ -0,0 +1,11 @@ +
+ +{{#if name}}

{{name}}

{{/if}} + +{{#if comments~}} +
{{{markdown comments}}}
+{{/if}} + +{{{documentables}}} + +
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/supersection.hbs b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/supersection.hbs new file mode 100644 index 000000000..09026390f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/leafdoc-templates/supersection.hbs @@ -0,0 +1,7 @@ +
+

{{name}}

+{{markdown comments}} +{{{sections}}} + +{{{inheritances}}} +
\ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/publish.sh b/vendor/assets/javascripts/Leaflet-1.4.0/build/publish.sh new file mode 100755 index 000000000..31b9876c4 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/publish.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +npm update + +VERSION=$(node --eval "console.log(require('./package.json').version);") + +npm test || exit 1 + +echo "Ready to publish Leaflet version $VERSION." +echo "Has the version number been bumped?" +read -n1 -r -p "Press Ctrl+C to cancel, or any other key to continue." key + +git checkout -b build + +export NODE_ENV=release + +npm run-script build + +echo "Creating git tag v$VERSION..." + +git add dist/leaflet-src.js dist/leaflet.js dist/leaflet-src.esm.js dist/leaflet-src.js.map dist/leaflet.js.map dist/leaflet-src.esm.js.map -f + +git commit -m "v$VERSION" + +git tag v$VERSION -f +git push --tags -f + +echo "Uploading to NPM..." + +npm publish + +git checkout master +git branch -D build + +echo "All done." +echo "Remember to run 'npm run-script integrity' and then commit the changes to the master branch, in order to update the website." diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/rollup-config.js b/vendor/assets/javascripts/Leaflet-1.4.0/build/rollup-config.js new file mode 100644 index 000000000..4b8a58fe4 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/rollup-config.js @@ -0,0 +1,58 @@ +// Config file for running Rollup in "normal" mode (non-watch) + +import rollupGitVersion from 'rollup-plugin-git-version' +import json from 'rollup-plugin-json' +import gitRev from 'git-rev-sync' +import pkg from '../package.json' + +let {version} = pkg; +let release; + +// Skip the git branch+rev in the banner when doing a release build +if (process.env.NODE_ENV === 'release') { + release = true; +} else { + release = false; + const branch = gitRev.branch(); + const rev = gitRev.short(); + version += '+' + branch + '.' + rev; +} + +const banner = `/* @preserve + * Leaflet ${version}, a JS library for interactive maps. http://leafletjs.com + * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade + */ +`; + +const outro = `var oldL = window.L; +exports.noConflict = function() { + window.L = oldL; + return this; +} + +// Always export us to window global (see #2364) +window.L = exports;`; + +export default { + input: 'src/Leaflet.js', + output: [ + { + file: pkg.main, + format: 'umd', + name: 'L', + banner: banner, + outro: outro, + sourcemap: true + }, + { + file: 'dist/leaflet-src.esm.js', + format: 'es', + banner: banner, + sourcemap: true + } + ], + legacy: true, // Needed to create files loadable by IE8 + plugins: [ + release ? json() : rollupGitVersion() + ] +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/build/rollup-watch-config.js b/vendor/assets/javascripts/Leaflet-1.4.0/build/rollup-watch-config.js new file mode 100644 index 000000000..0c4a0869b --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/build/rollup-watch-config.js @@ -0,0 +1,29 @@ +// Config file for running Rollup in "watch" mode +// This adds a sanity check to help ourselves to run 'rollup -w' as needed. + +import rollupGitVersion from 'rollup-plugin-git-version' +import gitRev from 'git-rev-sync' + +const branch = gitRev.branch(); +const rev = gitRev.short(); +const version = require('../package.json').version + '+' + branch + '.' + rev; +const banner = `/* @preserve + * Leaflet ${version}, a JS library for interactive maps. http://leafletjs.com + * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade + */ +`; + +export default { + input: 'src/Leaflet.js', + output: { + file: 'dist/leaflet-src.js', + format: 'umd', + name: 'L', + banner: banner, + sourcemap: true + }, + legacy: true, // Needed to create files loadable by IE8 + plugins: [ + rollupGitVersion() + ] +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/css/mobile.css b/vendor/assets/javascripts/Leaflet-1.4.0/debug/css/mobile.css new file mode 100644 index 000000000..d8f46f32e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/css/mobile.css @@ -0,0 +1,6 @@ +html, body, #map { + margin: 0; + padding: 0; + width: 100%; + height: 100%; +} \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/css/screen.css b/vendor/assets/javascripts/Leaflet-1.4.0/debug/css/screen.css new file mode 100644 index 000000000..f98869870 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/css/screen.css @@ -0,0 +1,5 @@ +#map { + width: 800px; + height: 600px; + border: 1px solid #ccc; + } \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/hacks/jitter.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/hacks/jitter.html new file mode 100644 index 000000000..14858f816 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/hacks/jitter.html @@ -0,0 +1,39 @@ + + + + Leaflet debug page + + + + + + + + + + +
+
+
Click in field then scroll map (in up/left direction) to see shift of map tiles. +
: + +
+
+ Bug tested to occur on: Safari on Mac (Tested in 5.1.7), iPad/iPhone 5.1.1., Android 4 Browser. Hack is in L.Browser.chrome and TileLayer._addTile + +
+ + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/leaflet-include.js b/vendor/assets/javascripts/Leaflet-1.4.0/debug/leaflet-include.js new file mode 120000 index 000000000..23dfb1d9b --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/leaflet-include.js @@ -0,0 +1 @@ +../dist/leaflet-src.js \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/canvas.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/canvas.html new file mode 100644 index 000000000..9234b356c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/canvas.html @@ -0,0 +1,48 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/control-layers.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/control-layers.html new file mode 100644 index 000000000..32b87b03f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/control-layers.html @@ -0,0 +1,50 @@ + + + + Leaflet debug page + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/controls.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/controls.html new file mode 100644 index 000000000..be9488897 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/controls.html @@ -0,0 +1,45 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/geolocation.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/geolocation.html new file mode 100644 index 000000000..e54d34744 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/geolocation.html @@ -0,0 +1,33 @@ + + + + Leaflet geolocation debug page + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/grid.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/grid.html new file mode 100644 index 000000000..11f4b6005 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/grid.html @@ -0,0 +1,48 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/iframe.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/iframe.html new file mode 100644 index 000000000..b1035aab6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/iframe.html @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/image-overlay.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/image-overlay.html new file mode 100644 index 000000000..13790b508 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/image-overlay.html @@ -0,0 +1,48 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/layer_remove_add.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/layer_remove_add.html new file mode 100644 index 000000000..3fd813284 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/layer_remove_add.html @@ -0,0 +1,37 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-mobile.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-mobile.html new file mode 100644 index 000000000..fa9ec2878 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-mobile.html @@ -0,0 +1,33 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-popup.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-popup.html new file mode 100644 index 000000000..a0cf98d9c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-popup.html @@ -0,0 +1,56 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-scaled.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-scaled.html new file mode 100644 index 000000000..8b88ff7b9 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map-scaled.html @@ -0,0 +1,65 @@ + + + + Leaflet debug page + + + + + + + + + + + + + +
+
+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map.html new file mode 100644 index 000000000..489fb13df --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/map.html @@ -0,0 +1,69 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/marker-autopan.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/marker-autopan.html new file mode 100644 index 000000000..6bad94391 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/marker-autopan.html @@ -0,0 +1,63 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/markers.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/markers.html new file mode 100644 index 000000000..0730f3ea9 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/markers.html @@ -0,0 +1,62 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds-bouncy.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds-bouncy.html new file mode 100644 index 000000000..bd6d866ae --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds-bouncy.html @@ -0,0 +1,51 @@ + + + + Leaflet debug page + + + + + + + + + + + +

Left: Bouncy maxBounds. Right: Not bouncy.

+ +
+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds-infinite.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds-infinite.html new file mode 100644 index 000000000..e7c460b78 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds-infinite.html @@ -0,0 +1,36 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds.html new file mode 100644 index 000000000..5e4bf9ccf --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/max-bounds.html @@ -0,0 +1,41 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/opacity.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/opacity.html new file mode 100644 index 000000000..a83a1530f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/opacity.html @@ -0,0 +1,197 @@ + + + + Leaflet debug page + + + + + + + + + + + +

These should all render identically.

+
+ CASE 1: no opacity set on any layers +
+
+
+
+ CASE 2: opacity set to .99 on overlays but not on basemap +
+
+
+
+ CASE 3: opacity set on overlays but not on basemap, zIndex option set to 0 on basemap +
+
+
+
+ CASE 4: opacity set to .99 on overlays but set to 1 on basemap +
+
+
+
+ CASE 5: opacity set to .99 on all layers +
+
+
+
+ CASE 6: opacity set to .99 on 1st and 3rd layers and 1 on middle layer +
+
+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/popup.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/popup.html new file mode 100644 index 000000000..b2149f638 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/popup.html @@ -0,0 +1,85 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/rollup.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/rollup.html new file mode 100644 index 000000000..c15f28c7e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/rollup.html @@ -0,0 +1,104 @@ + + + + Leaflet debug page + + + + + + + + + + + + +
+ + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/scroll.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/scroll.html new file mode 100644 index 000000000..bfb1202fe --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/scroll.html @@ -0,0 +1,40 @@ + + + + Leaflet debug page + + + + + + + + + +
+
+
+
+
+
+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/simple-proj.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/simple-proj.html new file mode 100644 index 000000000..275dea8d1 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/simple-proj.html @@ -0,0 +1,58 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tile-debug.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tile-debug.html new file mode 100644 index 000000000..39a0b5ba6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tile-debug.html @@ -0,0 +1,248 @@ + + + + Leaflet tile debug + + + + + + + + + + + +
+
+
+ +
+
+
(flyTo)
+
(setView)
+
(flyTo)
+
(fract. zoom)
+
(setView, fract. zoom)
+
(fitBounds)
+
(image overlay)
+
+
+ + + + + + + + +
on movestart
on zoomstart
on move
on moveend
on zoomend
on grid load
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
eventGridPositron
tileloadstart
tileload
tileerror
tileunload
visible
grid load
+ +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tile-opacity.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tile-opacity.html new file mode 100644 index 000000000..5ddf63642 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tile-opacity.html @@ -0,0 +1,31 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tooltip.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tooltip.html new file mode 100644 index 000000000..2cd73ec3a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/tooltip.html @@ -0,0 +1,68 @@ + + + + Leaflet debug page + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/videooverlay.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/videooverlay.html new file mode 100644 index 000000000..1490f68eb --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/videooverlay.html @@ -0,0 +1,78 @@ + + + + Leaflet debug page + + + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/wms-marble.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/wms-marble.html new file mode 100644 index 000000000..fdf67e803 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/wms-marble.html @@ -0,0 +1,29 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/wms.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/wms.html new file mode 100644 index 000000000..805ed48cd --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/wms.html @@ -0,0 +1,39 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoom-delta.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoom-delta.html new file mode 100644 index 000000000..7e0f39e99 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoom-delta.html @@ -0,0 +1,108 @@ + + + + Leaflet debug page + + + + + + + + + + + + +

Zoom delta test.

+ +

Zooming with touch zoom, box zoom or flyTo then map.stop() must make the zoom level snap to the value of the zoomSnap option. Zoom interactions (keyboard, mouse wheel, zoom control buttons must change the zoom by the amount in the zoomDelta option.

+ +
+ + + +
+ +
+ Snap: 0.25. Delta: 0.5. +
+ +
+
+ Snap: 0 (off). Delta: 0.25. +
+ +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoom-remain-centered.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoom-remain-centered.html new file mode 100644 index 000000000..3c371f61a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoom-remain-centered.html @@ -0,0 +1,43 @@ + + + + Leaflet debug page + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoomlevels.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoomlevels.html new file mode 100644 index 000000000..58e8091fb --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoomlevels.html @@ -0,0 +1,52 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoompan.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoompan.html new file mode 100644 index 000000000..099236cb6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/map/zoompan.html @@ -0,0 +1,104 @@ + + + + Leaflet debug page + + + + + + + + + + + + +
+ +
+
(flyTo)
+
(setView, 5 sec)
+
(flyTo 20 sec)
+
(fract. zoom)
+
(setView, fract. zoom)
+
(fitBounds)
+
(image overlay)
+
+ + + + + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/add_remove_layers.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/add_remove_layers.html new file mode 100644 index 000000000..3b61b1845 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/add_remove_layers.html @@ -0,0 +1,70 @@ + + + + Leaflet debug page + + + + + + + + + + +
+
+ + +
+ + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/bringtoback.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/bringtoback.html new file mode 100644 index 000000000..e6460255a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/bringtoback.html @@ -0,0 +1,35 @@ + + + + Leaflet debug page + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/canvasloop.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/canvasloop.html new file mode 100644 index 000000000..997f8ff07 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/canvasloop.html @@ -0,0 +1,38 @@ + + + + + + + + + + +
+ + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/click_on_canvas.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/click_on_canvas.html new file mode 100644 index 000000000..d4e02de03 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/click_on_canvas.html @@ -0,0 +1,53 @@ + + + + Leaflet debug page + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/custom-panes.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/custom-panes.html new file mode 100644 index 000000000..0a6fd0861 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/custom-panes.html @@ -0,0 +1,69 @@ + + + + Leaflet debug page + + + + + + + + + + + + + +
+

Canvas

+
+
+
+

SVG

+
+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/detached-dom-memory-leak.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/detached-dom-memory-leak.html new file mode 100644 index 000000000..b2fd18df4 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/detached-dom-memory-leak.html @@ -0,0 +1,55 @@ + + + + Leaflet debug page + + + + + + + + +This page will destroy and recreate a map div lots of times. Developer tools shall not display a memory leak. + +
+ + + +
+ + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/doubleclick-events-slowdown.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/doubleclick-events-slowdown.html new file mode 100644 index 000000000..2338e82f0 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/doubleclick-events-slowdown.html @@ -0,0 +1,82 @@ + + + + Leaflet debug page + + + + + + + + + + + +

This test is meant for testing the performance of doubleclick event handler in IE. See #4127 and #2820

+ +
+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/dragging_and_copyworldjump.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/dragging_and_copyworldjump.html new file mode 100644 index 000000000..3abaef050 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/dragging_and_copyworldjump.html @@ -0,0 +1,57 @@ + + + + + Leaflet debug page + + + + + + + + + +

+ On the left Map dragging and worldCopyJump are enabled during initialisation.
+ On the right Map worldCopyJump is enabled. Dragging is enabled by clicking the button. +

+
+
+
+
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/dragging_cursors.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/dragging_cursors.html new file mode 100644 index 000000000..0a51e7e97 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/dragging_cursors.html @@ -0,0 +1,53 @@ + + + + + Leaflet debug page + + + + + + + + + + This page tests if the cursors for dragging the map and the markers behave as expected. The left marker is draggable, the right one is not. + +
+ +
Map dragging enabled:
+
+ +
+ +
Map dragging disabled:
+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/event-perf-2.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/event-perf-2.html new file mode 100644 index 000000000..604c0311c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/event-perf-2.html @@ -0,0 +1,81 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/event-perf.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/event-perf.html new file mode 100644 index 000000000..a87f2d619 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/event-perf.html @@ -0,0 +1,91 @@ + + + + + + + + + + Leaflet test for event adding/firing/removing performance + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/mousemove_on_polygons.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/mousemove_on_polygons.html new file mode 100644 index 000000000..fbb06a36c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/mousemove_on_polygons.html @@ -0,0 +1,106 @@ + + + + Leaflet debug page + + + + + + + + +
on movestart
on zoomstart
on move
on moveend
on zoomend
on grid load
+ + + + +
Enter Move Exit Click
Triangle 1:
Triangle 2:
Map:
+ + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/opacity.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/opacity.html new file mode 100644 index 000000000..6747d9d2e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/opacity.html @@ -0,0 +1,57 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/popup_offset.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/popup_offset.html new file mode 100644 index 000000000..a101853d7 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/popup_offset.html @@ -0,0 +1,35 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/popupcontextmenuclicks.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/popupcontextmenuclicks.html new file mode 100644 index 000000000..8080f9e1e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/popupcontextmenuclicks.html @@ -0,0 +1,57 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/remove_while_dragging.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/remove_while_dragging.html new file mode 100644 index 000000000..6539738e3 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/remove_while_dragging.html @@ -0,0 +1,27 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/removetilewhilepan.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/removetilewhilepan.html new file mode 100644 index 000000000..8475b0fff --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/removetilewhilepan.html @@ -0,0 +1,40 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/reuse_popups.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/reuse_popups.html new file mode 100644 index 000000000..f1bafbfad --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/reuse_popups.html @@ -0,0 +1,36 @@ + + + + Leaflet debug page + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/rtl.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/rtl.html new file mode 100644 index 000000000..2344856cf --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/rtl.html @@ -0,0 +1,39 @@ + + + + Leaflet debug page + + + + + + + + + + + + +

Click the map to place a popup at the mouse location

+
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/rtl2.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/rtl2.html new file mode 100644 index 000000000..f6b754da6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/rtl2.html @@ -0,0 +1,25 @@ + + + + + + + + + + + + + +
+ + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/set_icon_reuse_dom.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/set_icon_reuse_dom.html new file mode 100644 index 000000000..e4bb7d489 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/set_icon_reuse_dom.html @@ -0,0 +1,42 @@ + + +Test for preservation of Icon DOM element + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/svg_clicks.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/svg_clicks.html new file mode 100644 index 000000000..9056d75e7 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/svg_clicks.html @@ -0,0 +1,53 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-bounds.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-bounds.html new file mode 100644 index 000000000..c5e6b757d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-bounds.html @@ -0,0 +1,62 @@ + + + + Leaflet debug page + + + + + + + + + + + + + The CSS in this page makes the boundaries of the GridLayer tiles visible. Tiles which do not overlap the map bounds shall not be shown, even at fractional zoom levels. + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-events.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-events.html new file mode 100644 index 000000000..3631b9201 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-events.html @@ -0,0 +1,156 @@ + + + + Leaflet debug page + + + + + + + + + + + + +

Keep track of how many tileload/tileunload events are being fired. The counts should always match. See #4093, #4193

+ +
+ + + + + +
+ Start + Load + Error + Unload + Visible + Grid load +
Grid + + + + + + +
Positron + + + + + + +
+ +

start = unload + visible on screen

+ +
(flyTo)
+
(setView, 5 sec)
+
(flyTo 20 sec)
+
(fract. zoom)
+
(setView, fract. zoom)
+
(fitBounds)
+
(image overlay)
+
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-opacity.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-opacity.html new file mode 100644 index 000000000..71e1bd0c1 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/tile-opacity.html @@ -0,0 +1,43 @@ + + + + Leaflet debug page + + + + + + + + + + + + + The opacity of the "toner" layer should pulse nicely, even when dragging/zooming the map around with new tiles. +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/touch-shake.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/touch-shake.html new file mode 100644 index 000000000..7ecdf14d4 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/touch-shake.html @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + Leaflet test for pinch-zoom-without-bounce + + + + + This is a semi-automated test for checking touch-zoom shaking. + +
+ + + + +
+ +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/touch-zoom-bounce.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/touch-zoom-bounce.html new file mode 100644 index 000000000..e5486062e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/tests/touch-zoom-bounce.html @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + Leaflet test for pinch-zoom-without-bounce + + + + + This is an automated test for #3530. + +
+ + + + +
+ +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/bounds-extend.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/bounds-extend.html new file mode 100644 index 000000000..611460fcf --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/bounds-extend.html @@ -0,0 +1,87 @@ + + + + Leaflet debug page + + + + + + + + +
+ + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/feature-group-bounds.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/feature-group-bounds.html new file mode 100644 index 000000000..de2bc24d6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/feature-group-bounds.html @@ -0,0 +1,89 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/geojson-sample.js b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/geojson-sample.js new file mode 100644 index 000000000..16f6f5749 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/geojson-sample.js @@ -0,0 +1,53 @@ +var geojsonSample = { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [102.0, 0.5] + }, + "properties": { + "prop0": "value0", + "color": "blue" + } + }, + + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [[102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]] + }, + "properties": { + "color": "red", + "prop1": 0.0 + } + }, + + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]]] + }, + "properties": { + "color": "green", + "prop1": { + "this": "that" + } + } + }, + + { + "type": "Feature", + "geometry": { + "type": "MultiPolygon", + "coordinates": [[[[100.0, 1.5], [100.5, 1.5], [100.5, 2.0], [100.0, 2.0], [100.0, 1.5]]], [[[100.5, 2.0], [100.5, 2.5], [101.0, 2.5], [101.0, 2.0], [100.5, 2.0]]]] + }, + "properties": { + "color": "purple" + } + } + ] +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/geojson.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/geojson.html new file mode 100644 index 000000000..b13733c83 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/geojson.html @@ -0,0 +1,171 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/inherit-dashArray.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/inherit-dashArray.html new file mode 100644 index 000000000..01d0019e8 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/inherit-dashArray.html @@ -0,0 +1,37 @@ + + + + Leaflet debug page + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/moving-canvas.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/moving-canvas.html new file mode 100644 index 000000000..043bad5d4 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/moving-canvas.html @@ -0,0 +1,50 @@ + + + + Leaflet debug page + + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/rectangle.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/rectangle.html new file mode 100644 index 000000000..2d73b0c44 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/rectangle.html @@ -0,0 +1,54 @@ + + + + Leaflet debug page + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/route.js b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/route.js new file mode 100644 index 000000000..457c258d3 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/route.js @@ -0,0 +1,11 @@ +/* + Route exported from CloudMade; + + Map data used is Copyright (c) OpenStreetMap contributors 2010 + OpenStreetMap® is open data, licensed under the + Open Data Commons Open Database License (ODbL) by + the OpenStreetMap Foundation (OSMF). + + See full license: https://www.openstreetmap.org/copyright +*/ +var route = [[51.452339,-0.26291],[51.452011,-0.26479],[51.451839,-0.26624],[51.45187,-0.26706],[51.451881,-0.26733],[51.452049,-0.26734],[51.453098,-0.26734],[51.453838,-0.26717],[51.454849,-0.267],[51.45575,-0.26704],[51.45631,-0.26723],[51.456402,-0.26729],[51.456669,-0.26745],[51.45689,-0.26755],[51.457001,-0.26758],[51.45797,-0.26776],[51.458359,-0.26786],[51.459019,-0.26783],[51.459629,-0.26785],[51.459888,-0.26809],[51.460178,-0.26845],[51.46077,-0.26841],[51.461102,-0.26838],[51.461479,-0.2685],[51.46159,-0.26848],[51.462479,-0.26776],[51.462921,-0.26766],[51.463291,-0.26754],[51.463558,-0.26736],[51.46373,-0.26728],[51.464291,-0.26676],[51.464432,-0.26675],[51.464722,-0.26671],[51.464821,-0.2657],[51.46484,-0.2655],[51.464851,-0.26504],[51.46489,-0.26456],[51.464951,-0.26397],[51.464981,-0.26357],[51.46497,-0.26344],[51.465031,-0.26294],[51.46508,-0.26224],[51.465111,-0.26179],[51.46513,-0.26157],[51.465149,-0.261],[51.465149,-0.26077],[51.465149,-0.26051],[51.465149,-0.26011],[51.46513,-0.25982],[51.46513,-0.25955],[51.46513,-0.25929],[51.465111,-0.25872],[51.46513,-0.2583],[51.46513,-0.25771],[51.465141,-0.25753],[51.46516,-0.25675],[51.46516,-0.25658],[51.46516,-0.25647],[51.465179,-0.25574],[51.465191,-0.25525],[51.465199,-0.25486],[51.46521,-0.25455],[51.46521,-0.25413],[51.46524,-0.25293],[51.465229,-0.25186],[51.465191,-0.25085],[51.46513,-0.25001],[51.46508,-0.24926],[51.465069,-0.24862],[51.465111,-0.24775],[51.465149,-0.2472],[51.465172,-0.24675],[51.46524,-0.24571],[51.465279,-0.24482],[51.465321,-0.24423],[51.465229,-0.24372],[51.465149,-0.24266],[51.465118,-0.24208],[51.465069,-0.24147],[51.464939,-0.24028],[51.464821,-0.2395],[51.46476,-0.2389],[51.464729,-0.23852],[51.464642,-0.23755],[51.464569,-0.23693],[51.464481,-0.2365],[51.464371,-0.23557],[51.464211,-0.23437],[51.46418,-0.23421],[51.464001,-0.23334],[51.463959,-0.23316],[51.463829,-0.23253],[51.463779,-0.23235],[51.463699,-0.23189],[51.463661,-0.2317],[51.463589,-0.23136],[51.463539,-0.23106],[51.463402,-0.23025],[51.463341,-0.2299],[51.463249,-0.22924],[51.463139,-0.22838],[51.46312,-0.22823],[51.463001,-0.22726],[51.462959,-0.22698],[51.462891,-0.22645],[51.462769,-0.22551],[51.462761,-0.22516],[51.462681,-0.22436],[51.46262,-0.224],[51.462521,-0.22297],[51.462421,-0.22247],[51.462181,-0.22183],[51.462009,-0.22149],[51.461731,-0.22074],[51.461399,-0.2196],[51.461361,-0.21948],[51.46122,-0.21878],[51.461109,-0.21824],[51.460979,-0.2175],[51.460789,-0.21715],[51.46069,-0.21685],[51.460522,-0.21596],[51.4604,-0.21533],[51.460361,-0.21511],[51.460251,-0.21458],[51.46022,-0.2144],[51.460159,-0.21411],[51.460121,-0.21389],[51.46011,-0.2138],[51.459961,-0.21308],[51.459942,-0.21294],[51.459702,-0.21186],[51.459702,-0.21184],[51.45948,-0.21112],[51.459259,-0.21038],[51.459011,-0.20963],[51.45892,-0.2094],[51.458809,-0.2091],[51.458759,-0.20898],[51.45858,-0.20853],[51.458328,-0.20795],[51.458179,-0.2076],[51.458141,-0.20751],[51.458099,-0.20743],[51.457981,-0.2072],[51.45771,-0.20668],[51.4575,-0.20638],[51.457321,-0.20614],[51.45718,-0.20596],[51.457088,-0.20584],[51.456921,-0.20558],[51.456829,-0.20541],[51.456772,-0.20522],[51.45676,-0.20518],[51.456749,-0.20509],[51.45673,-0.20469],[51.456718,-0.20466],[51.456699,-0.20425],[51.456692,-0.20391],[51.456692,-0.20371],[51.456661,-0.20284],[51.456661,-0.20272],[51.456661,-0.20254],[51.456669,-0.20231],[51.456692,-0.20178],[51.456699,-0.20148],[51.45673,-0.20116],[51.45676,-0.20077],[51.45686,-0.19978],[51.45697,-0.19857],[51.457001,-0.19826],[51.457039,-0.19806],[51.45705,-0.19793],[51.457142,-0.19781],[51.457211,-0.19776],[51.45742,-0.19785],[51.45763,-0.19794],[51.45776,-0.19795],[51.457829,-0.19791],[51.45789,-0.19784],[51.458,-0.19751],[51.458172,-0.19697],[51.458271,-0.19654],[51.458439,-0.19585],[51.458599,-0.19507],[51.45863,-0.1949],[51.458729,-0.19437],[51.458809,-0.19394],[51.45892,-0.19318],[51.45892,-0.1926],[51.458839,-0.19206],[51.458858,-0.19189],[51.45887,-0.1917],[51.459049,-0.19117],[51.45916,-0.19078],[51.459148,-0.19065],[51.45908,-0.19055],[51.458679,-0.19041],[51.458511,-0.19034],[51.458271,-0.19026],[51.457939,-0.19013],[51.457329,-0.1899],[51.457199,-0.18985],[51.456829,-0.18972],[51.457069,-0.18858],[51.457142,-0.18824],[51.457211,-0.18785],[51.45731,-0.18732],[51.457581,-0.1857],[51.457649,-0.18525],[51.457878,-0.18476],[51.45797,-0.18457],[51.45829,-0.18387],[51.45866,-0.18305],[51.458771,-0.18276],[51.458801,-0.18269],[51.4589,-0.18243],[51.458981,-0.18222],[51.45911,-0.1819],[51.459229,-0.1815],[51.459358,-0.18094],[51.459431,-0.18064],[51.45956,-0.18014],[51.459518,-0.18],[51.459469,-0.17984],[51.45882,-0.1796],[51.458431,-0.17945],[51.458351,-0.17935],[51.458279,-0.17924],[51.458309,-0.17861],[51.458401,-0.17714],[51.458511,-0.17525],[51.45853,-0.17515],[51.45858,-0.17493],[51.458912,-0.17401],[51.459,-0.17374],[51.459179,-0.1732],[51.45929,-0.17292],[51.459461,-0.17245],[51.459579,-0.1721],[51.459919,-0.17123],[51.460232,-0.17037],[51.4604,-0.16967],[51.46048,-0.16947],[51.460579,-0.16882],[51.460751,-0.16781],[51.460838,-0.16703],[51.460781,-0.16653],[51.460819,-0.16599],[51.460831,-0.1658],[51.460869,-0.16534],[51.46088,-0.16485],[51.460899,-0.16431],[51.460979,-0.16321],[51.460999,-0.16296],[51.461021,-0.16268],[51.461021,-0.1625],[51.46104,-0.16213],[51.46106,-0.16186],[51.461151,-0.16126],[51.46122,-0.1602],[51.4613,-0.15897],[51.461319,-0.15819],[51.461281,-0.15716],[51.4613,-0.15642],[51.460049,-0.15658],[51.45993,-0.15658],[51.459759,-0.15659],[51.45969,-0.15658],[51.458931,-0.15604],[51.458172,-0.15538],[51.457878,-0.1551],[51.45742,-0.15465],[51.456821,-0.15379],[51.455681,-0.15134],[51.455528,-0.15098],[51.45475,-0.14926],[51.453999,-0.14742],[51.45401,-0.14732],[51.454159,-0.14628],[51.453369,-0.14419],[51.452862,-0.14297],[51.452332,-0.14222],[51.451832,-0.14213],[51.45174,-0.14214],[51.451328,-0.14212],[51.451099,-0.14197],[51.451012,-0.14191],[51.450729,-0.14134],[51.450691,-0.14118],[51.450489,-0.1404],[51.449871,-0.13813],[51.449799,-0.13787],[51.449539,-0.13695],[51.449261,-0.13612],[51.44915,-0.13577],[51.448811,-0.13476],[51.448502,-0.13383],[51.448391,-0.13351],[51.44833,-0.13332],[51.44812,-0.13277],[51.447861,-0.13189],[51.447609,-0.13092],[51.447552,-0.13067],[51.44735,-0.12992],[51.44717,-0.12935],[51.447071,-0.12885],[51.446991,-0.12862],[51.446972,-0.12857],[51.44685,-0.1282],[51.445992,-0.12606],[51.44511,-0.12436],[51.44492,-0.12368],[51.44487,-0.12353],[51.444752,-0.12276],[51.444721,-0.12266],[51.444641,-0.12243],[51.44453,-0.12213],[51.444389,-0.12187],[51.44434,-0.12167],[51.444118,-0.12058],[51.444012,-0.12013],[51.44371,-0.11895],[51.443531,-0.1182],[51.443489,-0.11803],[51.443451,-0.11786],[51.443371,-0.11758],[51.4431,-0.11661],[51.44276,-0.1158],[51.44212,-0.11491],[51.441689,-0.11427],[51.44138,-0.11364],[51.441151,-0.11289],[51.441101,-0.11274],[51.441059,-0.11257],[51.440651,-0.11082],[51.440578,-0.11025],[51.440392,-0.10871],[51.441078,-0.10854],[51.441441,-0.10829],[51.44109,-0.10701],[51.44101,-0.10662],[51.440941,-0.10626],[51.440929,-0.10578],[51.440891,-0.1052],[51.440762,-0.10446],[51.44051,-0.10355],[51.440441,-0.10333],[51.440189,-0.10274],[51.43964,-0.10179],[51.439461,-0.10091],[51.439339,-0.10016],[51.43935,-0.10003],[51.439339,-0.09909],[51.4394,-0.09832],[51.439548,-0.0979],[51.43969,-0.09752],[51.43985,-0.09727],[51.440189,-0.09671],[51.44043,-0.09609],[51.44046,-0.09599],[51.44072,-0.09489],[51.440948,-0.09397],[51.441071,-0.09291],[51.441101,-0.09183],[51.441109,-0.09137],[51.441109,-0.091],[51.441101,-0.09],[51.44104,-0.0892],[51.440861,-0.08854],[51.440891,-0.08813],[51.440979,-0.08768],[51.44173,-0.08473],[51.44183,-0.08436],[51.441891,-0.08413],[51.44191,-0.08401],[51.44199,-0.08292],[51.442089,-0.08137],[51.4422,-0.08036],[51.442242,-0.08006],[51.44228,-0.07963],[51.44231,-0.07934],[51.442451,-0.07843],[51.442551,-0.07765],[51.442669,-0.07675],[51.442982,-0.07507],[51.443298,-0.07406],[51.443489,-0.07357],[51.443562,-0.07321],[51.443569,-0.0728],[51.443489,-0.07209],[51.443359,-0.07099],[51.443119,-0.0694],[51.4431,-0.06915],[51.443089,-0.06894],[51.443138,-0.06811],[51.44318,-0.06783],[51.443199,-0.06772],[51.443291,-0.06757],[51.443069,-0.06722],[51.442532,-0.06649],[51.442421,-0.06637],[51.4422,-0.06613],[51.442059,-0.06597],[51.44186,-0.06575],[51.44178,-0.06567],[51.441761,-0.06555],[51.441269,-0.06498],[51.44112,-0.06465],[51.44104,-0.06435],[51.441021,-0.06425],[51.440948,-0.06408],[51.440609,-0.06253],[51.440601,-0.0622],[51.440559,-0.06188],[51.440552,-0.06152],[51.44054,-0.0609],[51.440529,-0.06047],[51.44051,-0.06015],[51.44051,-0.05982],[51.44054,-0.05915],[51.44054,-0.05889],[51.440552,-0.0586],[51.440552,-0.0584],[51.440472,-0.05796],[51.440361,-0.05765],[51.440239,-0.05739],[51.440109,-0.05707],[51.43969,-0.05579],[51.43924,-0.05458],[51.43911,-0.05418],[51.439049,-0.054],[51.439289,-0.05379],[51.439751,-0.0538],[51.440102,-0.05379],[51.440201,-0.05371],[51.440239,-0.05359],[51.440269,-0.05332],[51.4403,-0.05295],[51.440281,-0.05266],[51.440231,-0.05243],[51.440022,-0.05139],[51.43998,-0.05115],[51.440071,-0.0507],[51.440479,-0.04968],[51.440762,-0.04884],[51.44138,-0.04734],[51.442162,-0.04733],[51.442181,-0.04733],[51.442268,-0.04725],[51.442329,-0.04588],[51.442329,-0.04563],[51.44228,-0.04412],[51.442242,-0.04251],[51.44215,-0.04132],[51.44202,-0.03995],[51.442051,-0.03951],[51.442089,-0.03879],[51.442211,-0.03746],[51.442299,-0.03678],[51.442329,-0.03654],[51.442341,-0.03618],[51.442341,-0.03586],[51.442322,-0.03489],[51.442291,-0.03441],[51.442081,-0.03347],[51.441929,-0.03274],[51.441898,-0.03239],[51.441959,-0.03208],[51.442131,-0.03124],[51.442322,-0.03081],[51.442692,-0.02992],[51.4431,-0.02868],[51.443138,-0.028],[51.443169,-0.0276],[51.44323,-0.02698],[51.443352,-0.02683],[51.443741,-0.02636],[51.443851,-0.02623],[51.443932,-0.02613],[51.444221,-0.02538],[51.44455,-0.02409],[51.444618,-0.02361],[51.444691,-0.02308],[51.44479,-0.02226],[51.444801,-0.02197],[51.444809,-0.02115],[51.44487,-0.02082],[51.444939,-0.02056],[51.445019,-0.02034],[51.445122,-0.02013],[51.445229,-0.01994],[51.445431,-0.01983],[51.445969,-0.01957],[51.446129,-0.01946],[51.446072,-0.01873],[51.44595,-0.01764],[51.4459,-0.01725],[51.445709,-0.01584],[51.445511,-0.0145],[51.445339,-0.01315],[51.445068,-0.01105],[51.445068,-0.00916],[51.445068,-0.00897],[51.445099,-0.00713],[51.44511,-0.00561],[51.445099,-0.00474],[51.44508,-0.00345],[51.445122,-0.00221],[51.44516,-0.00109],[51.445171,0.00011],[51.44519,0.00135],[51.445202,0.00247],[51.445221,0.00356],[51.445278,0.00442],[51.445301,0.00467],[51.445389,0.00518],[51.44556,0.00565],[51.44558,0.00603],[51.44556,0.00663],[51.445572,0.00772],[51.445641,0.00859],[51.445679,0.00959],[51.445721,0.01089],[51.445801,0.0115],[51.445889,0.0127],[51.446159,0.01386],[51.446381,0.01466],[51.446609,0.0156],[51.447708,0.02026],[51.44775,0.02043],[51.448189,0.02234],[51.44825,0.02255],[51.448292,0.0227],[51.448441,0.0232],[51.448669,0.02399],[51.448879,0.02476],[51.44902,0.02536],[51.449089,0.02561],[51.44978,0.02794],[51.450119,0.02896],[51.450191,0.02912],[51.450249,0.02914],[51.450279,0.02917],[51.450298,0.0292],[51.450329,0.02924],[51.450352,0.02933],[51.450359,0.02943],[51.45034,0.02953],[51.450279,0.02964],[51.45023,0.02969],[51.450161,0.0297],[51.4501,0.02967],[51.450039,0.02965],[51.44997,0.02965],[51.44978,0.02972],[51.4492,0.02993],[51.44857,0.03013],[51.448021,0.03033],[51.44772,0.03043],[51.44696,0.03077],[51.446739,0.03084],[51.446419,0.03088],[51.44614,0.0309],[51.44577,0.03095],[51.445438,0.03104],[51.445148,0.03122],[51.444939,0.03145],[51.444721,0.03171],[51.444561,0.03193],[51.444401,0.03219],[51.444241,0.0325],[51.443958,0.03315],[51.443501,0.03425],[51.4431,0.03519],[51.442791,0.03597],[51.442471,0.03678],[51.44228,0.03729],[51.442131,0.0378],[51.441811,0.03879],[51.441368,0.04027],[51.441231,0.04084],[51.44101,0.04174],[51.440479,0.04412],[51.43972,0.04768],[51.439651,0.04802],[51.4394,0.04924],[51.439369,0.04944],[51.439178,0.05038],[51.43911,0.05061],[51.438999,0.05081],[51.438789,0.05132],[51.438568,0.05182],[51.438358,0.05242],[51.438179,0.05313],[51.43795,0.05417],[51.437191,0.05753],[51.436932,0.05848],[51.436871,0.05864],[51.43679,0.05888],[51.436581,0.0594],[51.435188,0.0627],[51.434921,0.0634],[51.43483,0.06364],[51.434711,0.06398],[51.43462,0.06424],[51.434502,0.06462],[51.43433,0.06534],[51.43401,0.06693],[51.43359,0.06872],[51.433361,0.0698],[51.43288,0.07194],[51.432598,0.07332],[51.432369,0.07429],[51.43206,0.07563],[51.431351,0.07868],[51.431042,0.07999],[51.430489,0.08221],[51.430351,0.08261],[51.430119,0.08312],[51.429951,0.08344],[51.429798,0.08367],[51.429409,0.08413],[51.42889,0.08458],[51.427738,0.08559],[51.426731,0.08656],[51.4259,0.08747],[51.424511,0.08901],[51.422531,0.09173],[51.421539,0.09321],[51.420368,0.09517],[51.418839,0.09795],[51.417141,0.10123],[51.416222,0.10311],[51.415829,0.10403],[51.415371,0.10513],[51.415119,0.10581],[51.41444,0.10769],[51.414009,0.10905],[51.413521,0.11098],[51.41264,0.11505],[51.412041,0.11826],[51.41124,0.12231],[51.410992,0.12349],[51.410671,0.12522],[51.410599,0.12554],[51.41003,0.12827],[51.409771,0.12976],[51.409649,0.13078],[51.409561,0.13171],[51.409512,0.13284],[51.4095,0.13436],[51.409489,0.13994],[51.409489,0.1408],[51.4095,0.14117],[51.409489,0.1419],[51.40947,0.14288],[51.409389,0.14418],[51.40921,0.14569],[51.409069,0.14648],[51.408932,0.14716],[51.408749,0.14788],[51.40852,0.14863],[51.408131,0.14982],[51.407532,0.15119],[51.40696,0.15228],[51.40654,0.15293],[51.406269,0.15334],[51.405628,0.15413],[51.4049,0.15499],[51.404308,0.15556],[51.404129,0.15573],[51.403271,0.15645],[51.402302,0.15709],[51.401112,0.15767],[51.399971,0.15804],[51.399109,0.15828],[51.398079,0.15855],[51.397049,0.15889],[51.396179,0.15931],[51.39547,0.1598],[51.39452,0.16056],[51.393681,0.1614],[51.392921,0.16234],[51.392551,0.16289],[51.39212,0.16354],[51.391571,0.16447],[51.39085,0.166],[51.390228,0.1678],[51.38979,0.16935],[51.389469,0.17106],[51.389259,0.1728],[51.389172,0.17438],[51.38916,0.17585],[51.389221,0.17702],[51.389542,0.18034],[51.38969,0.18225],[51.38974,0.18407],[51.38974,0.18552],[51.389679,0.18714],[51.38942,0.18934],[51.389172,0.19115],[51.38876,0.19339],[51.388161,0.196],[51.38747,0.19845],[51.38702,0.19998],[51.38678,0.20088],[51.38625,0.20298],[51.385509,0.20598],[51.38522,0.20735],[51.385052,0.20821],[51.38467,0.21019],[51.38448,0.21191],[51.384418,0.21259],[51.384392,0.21318],[51.38435,0.21409],[51.3843,0.21612],[51.384171,0.22142],[51.384029,0.22337],[51.383831,0.22515],[51.38345,0.22739],[51.383411,0.22763],[51.383362,0.22786],[51.382919,0.22983],[51.382351,0.23176],[51.38184,0.23328],[51.381142,0.23508],[51.380901,0.23562],[51.38076,0.23596],[51.38039,0.23683],[51.37867,0.24056],[51.377449,0.24298],[51.37598,0.2457],[51.375271,0.24696],[51.373531,0.24988],[51.37122,0.25339],[51.3703,0.2548],[51.36866,0.25733],[51.366501,0.26056],[51.365349,0.26232],[51.364361,0.26381],[51.3634,0.26522],[51.362431,0.26644],[51.361179,0.26788],[51.360851,0.26818],[51.360149,0.26885],[51.359001,0.26981],[51.357712,0.27082],[51.355461,0.27233],[51.3531,0.27363],[51.351528,0.27437],[51.349098,0.27529],[51.347988,0.27563],[51.346981,0.27589],[51.34605,0.27605],[51.3451,0.27615],[51.344181,0.27614],[51.343079,0.27607],[51.340969,0.27571],[51.340099,0.27544],[51.33886,0.27496],[51.336941,0.27424],[51.336651,0.27417],[51.335949,0.274],[51.334801,0.27373],[51.33308,0.27351],[51.33073,0.27348],[51.329079,0.27365],[51.327808,0.27388],[51.326462,0.2743],[51.32526,0.27495],[51.323929,0.27599],[51.322701,0.27727],[51.321671,0.27865],[51.32098,0.27987],[51.32074,0.28029],[51.319931,0.28203],[51.319359,0.28364],[51.318668,0.28581],[51.318241,0.28741],[51.317829,0.28888],[51.31641,0.29444],[51.315529,0.29828],[51.315029,0.30069],[51.314289,0.30436],[51.313911,0.30597],[51.31348,0.30744],[51.312672,0.30974],[51.311611,0.31285],[51.311081,0.31464],[51.31041,0.31727],[51.309399,0.32178],[51.308849,0.32467],[51.308479,0.32698],[51.308041,0.32987],[51.307991,0.33014],[51.307961,0.33033],[51.30772,0.33232],[51.307419,0.3351],[51.30714,0.33829],[51.306919,0.34202],[51.306789,0.34573],[51.30677,0.34766],[51.30682,0.35044],[51.306919,0.35324],[51.307178,0.35651],[51.307468,0.35934],[51.30772,0.36124],[51.308189,0.36418],[51.308651,0.36814],[51.308708,0.36896],[51.30883,0.37218],[51.30891,0.3746],[51.30888,0.37754],[51.30901,0.38345],[51.309071,0.38842],[51.309261,0.39099],[51.309601,0.39395],[51.309959,0.39628],[51.31065,0.40007],[51.310909,0.40133],[51.311081,0.40247],[51.311211,0.40348],[51.311432,0.40537],[51.311531,0.4067],[51.3116,0.40831],[51.311611,0.40987],[51.311581,0.41178],[51.311569,0.41225],[51.311539,0.41272],[51.311481,0.41354],[51.311359,0.41489],[51.311192,0.41651],[51.310768,0.41924],[51.310379,0.42111],[51.310101,0.42242],[51.309231,0.42526],[51.308262,0.42798],[51.30727,0.43082],[51.306931,0.43183],[51.30674,0.43252],[51.306149,0.4349],[51.305901,0.43603],[51.305679,0.43715],[51.305038,0.44058],[51.30397,0.44616],[51.303379,0.44947],[51.303249,0.45038],[51.303162,0.45112],[51.30302,0.45268],[51.302769,0.45542],[51.302471,0.45849],[51.30238,0.45939],[51.302231,0.46031],[51.30196,0.46153],[51.30164,0.46285],[51.300961,0.4654],[51.300701,0.46637],[51.300461,0.46734],[51.300289,0.46822],[51.300121,0.46922],[51.300011,0.47011],[51.299931,0.47089],[51.299831,0.47189],[51.29977,0.47257],[51.29966,0.47387],[51.299591,0.47437],[51.299549,0.47468],[51.299541,0.47477],[51.29948,0.47513],[51.299438,0.47536],[51.299339,0.47598],[51.29911,0.47691],[51.298889,0.47756],[51.298691,0.47816],[51.298359,0.47894],[51.298241,0.47919],[51.297661,0.48044],[51.296921,0.48235],[51.296581,0.48351],[51.296398,0.48429],[51.29623,0.48525],[51.29612,0.48602],[51.29599,0.48772],[51.295959,0.49028],[51.295971,0.49123],[51.296001,0.49224],[51.29607,0.4932],[51.296188,0.4943],[51.29636,0.49533],[51.296558,0.49635],[51.29673,0.49698],[51.297211,0.49875],[51.297371,0.49922],[51.297459,0.49954],[51.297871,0.50098],[51.29808,0.50212],[51.298248,0.50355],[51.298351,0.50497],[51.298569,0.50858],[51.29879,0.51282],[51.298901,0.51441],[51.298969,0.51558],[51.29903,0.51657],[51.29908,0.51737],[51.29911,0.51794],[51.29911,0.51862],[51.299091,0.51915],[51.299,0.51987],[51.298908,0.52049],[51.298809,0.52116],[51.29863,0.52195],[51.298359,0.52297],[51.298168,0.52345],[51.297852,0.52421],[51.297489,0.52491],[51.29665,0.52623],[51.29557,0.52804],[51.29483,0.52931],[51.29427,0.53038],[51.292782,0.53339],[51.292221,0.53459],[51.291859,0.53532],[51.291599,0.53592],[51.291191,0.53707],[51.291019,0.53768],[51.290722,0.53911],[51.29047,0.54019],[51.290291,0.54093],[51.290131,0.54148],[51.28989,0.54226],[51.28923,0.544],[51.288582,0.54589],[51.288429,0.54636],[51.28828,0.54689],[51.288181,0.54746],[51.28804,0.54834],[51.287949,0.54936],[51.28791,0.55003],[51.287922,0.55088],[51.287971,0.55186],[51.288029,0.55306],[51.2882,0.55569],[51.28828,0.55696],[51.2883,0.55782],[51.288212,0.56001],[51.288101,0.56193],[51.28796,0.56383],[51.287762,0.56577],[51.287579,0.56706],[51.287361,0.56836],[51.286812,0.57094],[51.28624,0.57306],[51.285789,0.57454],[51.285332,0.57591],[51.284599,0.57786],[51.284061,0.57915],[51.283489,0.58035],[51.282799,0.58177],[51.28257,0.58224],[51.282299,0.58279],[51.280529,0.58595],[51.278931,0.58872],[51.277351,0.5914],[51.276951,0.59208],[51.275421,0.59477],[51.273571,0.59799],[51.271709,0.60145],[51.270592,0.60341],[51.270481,0.6036],[51.269989,0.60445],[51.269489,0.60531],[51.26915,0.60589],[51.268242,0.60747],[51.266701,0.60995],[51.26535,0.61188],[51.264179,0.61357],[51.263302,0.61501],[51.262489,0.6163],[51.261459,0.61795],[51.261311,0.61822],[51.261169,0.6185],[51.261051,0.61878],[51.260929,0.61903],[51.26062,0.61976],[51.260448,0.62018],[51.260201,0.6208],[51.259079,0.62382],[51.258289,0.62644],[51.25795,0.62747],[51.257641,0.62829],[51.256618,0.63055],[51.25634,0.63115],[51.256031,0.63176],[51.255371,0.63291],[51.255032,0.63346],[51.254688,0.63397],[51.252941,0.63631],[51.25243,0.63704],[51.252289,0.63724],[51.251289,0.63867],[51.250961,0.63918],[51.250599,0.63978],[51.249569,0.64159],[51.249271,0.64217],[51.24876,0.64322],[51.248112,0.64466],[51.24781,0.64535],[51.247509,0.64616],[51.247162,0.64707],[51.246861,0.64794],[51.246681,0.64849],[51.246471,0.64916],[51.246281,0.64979],[51.245949,0.65084],[51.245899,0.65104],[51.245171,0.65347],[51.244541,0.65575],[51.24361,0.65901],[51.242668,0.66237],[51.241711,0.66557],[51.241371,0.66662],[51.24102,0.66764],[51.240028,0.6704],[51.239609,0.67148],[51.23914,0.6726],[51.237942,0.67524],[51.237469,0.67616],[51.237041,0.67698],[51.236649,0.67772],[51.23645,0.6781],[51.23595,0.67909],[51.23518,0.68037],[51.234089,0.68227],[51.23365,0.68299],[51.233101,0.68384],[51.232632,0.68449],[51.232208,0.68509],[51.23159,0.68585],[51.231098,0.68638],[51.230659,0.68688],[51.229839,0.6878],[51.229019,0.6888],[51.228279,0.68988],[51.22797,0.69037],[51.227661,0.69092],[51.227211,0.6918],[51.2267,0.69285],[51.226509,0.69331],[51.226261,0.69388],[51.225819,0.69502],[51.225578,0.69575],[51.225281,0.69674],[51.22506,0.69754],[51.224869,0.69836],[51.224701,0.69918],[51.224548,0.69999],[51.224419,0.70091],[51.224339,0.70158],[51.224232,0.70277],[51.22414,0.70386],[51.22414,0.70392],[51.223942,0.70706],[51.223801,0.70842],[51.223709,0.70911],[51.223591,0.70976],[51.223358,0.71097],[51.223049,0.71225],[51.222851,0.71295],[51.22263,0.71364],[51.22224,0.71477],[51.221802,0.71586],[51.221561,0.71644],[51.221291,0.71697],[51.220409,0.71862],[51.220058,0.71922],[51.21965,0.71985],[51.21843,0.72149],[51.2178,0.72229],[51.217461,0.72274],[51.217072,0.72331],[51.21653,0.72418],[51.216202,0.72477],[51.215851,0.72538],[51.215481,0.72616],[51.215069,0.72716],[51.21442,0.72904],[51.21418,0.72975],[51.213928,0.73048],[51.21331,0.73252],[51.212719,0.7343],[51.212502,0.73491],[51.212261,0.73557],[51.21175,0.73686],[51.210781,0.73941],[51.210411,0.74033],[51.210091,0.74111],[51.208961,0.74368],[51.207371,0.7471],[51.205879,0.7505],[51.20435,0.75444],[51.20369,0.7563],[51.2029,0.75831],[51.202068,0.76009],[51.201199,0.76191],[51.199879,0.76458],[51.198879,0.76694],[51.198349,0.76836],[51.196941,0.77223],[51.195881,0.77579],[51.19482,0.77989],[51.19363,0.78381],[51.193481,0.78425],[51.192371,0.78747],[51.19109,0.79133],[51.190819,0.79238],[51.190521,0.79363],[51.190319,0.79462],[51.190182,0.79558],[51.18988,0.79784],[51.189522,0.80175],[51.189091,0.80706],[51.188862,0.8117],[51.188721,0.81612],[51.188599,0.82169],[51.18837,0.8241],[51.188251,0.82496],[51.188099,0.82587],[51.187962,0.82665],[51.187752,0.82763],[51.187569,0.82836],[51.187119,0.82975],[51.186378,0.83164],[51.185749,0.83293],[51.18531,0.83368],[51.184811,0.83448],[51.184299,0.83517],[51.183121,0.83649],[51.182381,0.83722],[51.18198,0.83761],[51.181862,0.83773],[51.179722,0.83981],[51.177509,0.84225],[51.17527,0.84496],[51.17326,0.84778],[51.171341,0.85072],[51.169498,0.85395],[51.167709,0.85684],[51.167049,0.85787],[51.166241,0.8591],[51.16478,0.86123],[51.163509,0.86324],[51.16193,0.86581],[51.1614,0.8668],[51.161079,0.86742],[51.160549,0.8685],[51.160221,0.86923],[51.15966,0.87046],[51.15884,0.87253],[51.157841,0.87482],[51.156559,0.87788],[51.15509,0.88152],[51.1548,0.88219],[51.15337,0.88568],[51.151508,0.89005],[51.15062,0.89223],[51.150249,0.89302],[51.150169,0.8932],[51.149899,0.8938],[51.149632,0.89439],[51.149109,0.89545],[51.148479,0.8966],[51.147461,0.89819],[51.146549,0.89942],[51.14473,0.90196],[51.142151,0.90519],[51.141788,0.90564],[51.140621,0.90699],[51.139591,0.90816],[51.138611,0.90931],[51.13802,0.91008],[51.137371,0.91099],[51.13644,0.91254],[51.135948,0.91346],[51.135071,0.91531],[51.13448,0.91676],[51.133438,0.91969],[51.13208,0.92321],[51.13131,0.92488],[51.13047,0.92637],[51.12999,0.92714],[51.129501,0.92789],[51.12772,0.93053],[51.127171,0.93141],[51.126259,0.93304],[51.125408,0.9346],[51.12484,0.93569],[51.123291,0.93894],[51.122822,0.93991],[51.121529,0.94233],[51.12104,0.94323],[51.119839,0.9451],[51.117802,0.94831],[51.11721,0.94936],[51.11676,0.95022],[51.116459,0.95082],[51.116219,0.95133],[51.115978,0.95189],[51.115761,0.95245],[51.11544,0.9533],[51.114738,0.95539],[51.113811,0.95882],[51.11272,0.96273],[51.111561,0.96647],[51.110279,0.97016],[51.108822,0.97406],[51.10833,0.97522],[51.107491,0.97725],[51.107121,0.97813],[51.106419,0.97979],[51.105999,0.98086],[51.105621,0.98185],[51.105209,0.98297],[51.104858,0.98403],[51.10453,0.98504],[51.10405,0.9866],[51.103519,0.98858],[51.103161,0.98998],[51.102631,0.99251],[51.10183,0.99697],[51.101261,1.00094],[51.100498,1.00727],[51.100441,1.00801],[51.100101,1.01554],[51.099789,1.02085],[51.09943,1.02433],[51.09914,1.02641],[51.098629,1.02937],[51.09795,1.03334],[51.097301,1.03712],[51.096981,1.03903],[51.096691,1.04113],[51.096191,1.04478],[51.09565,1.04961],[51.09523,1.05352],[51.095001,1.05578],[51.094818,1.05718],[51.094551,1.05899],[51.094002,1.0625],[51.093811,1.06352],[51.093479,1.06512],[51.09296,1.06772],[51.09272,1.06914],[51.092541,1.07024],[51.092381,1.07156],[51.09222,1.07294],[51.092091,1.07427],[51.091991,1.07574],[51.091911,1.07683],[51.09185,1.07825],[51.091801,1.08103],[51.09182,1.08295],[51.091881,1.08497],[51.091999,1.08669],[51.09206,1.08743],[51.092178,1.0886],[51.092339,1.09011],[51.092628,1.09246],[51.09293,1.09531],[51.093651,1.09994],[51.093788,1.10123],[51.093811,1.10192],[51.093849,1.10356],[51.0937,1.10681],[51.093472,1.10861],[51.09317,1.1104],[51.092239,1.11382],[51.091209,1.11814],[51.090988,1.12],[51.090889,1.12149],[51.090839,1.12251],[51.090839,1.12344],[51.090988,1.1267],[51.091251,1.12838],[51.091549,1.12994],[51.09219,1.13217],[51.09248,1.13289],[51.092812,1.13363],[51.093449,1.13509],[51.09383,1.13608],[51.09417,1.13718],[51.094791,1.14033],[51.09528,1.14437],[51.095539,1.14675],[51.09565,1.14905],[51.095638,1.15199],[51.0956,1.1539],[51.09557,1.15553],[51.0956,1.15691],[51.09565,1.15785],[51.095711,1.15863],[51.095791,1.15935],[51.095909,1.16004],[51.096081,1.16075],[51.096378,1.16185],[51.096771,1.16293],[51.097149,1.16373],[51.097439,1.16425],[51.09853,1.16572],[51.099621,1.16672],[51.099831,1.16689],[51.10281,1.16969],[51.104382,1.17116],[51.105709,1.17244],[51.106781,1.17389],[51.107849,1.17564],[51.108719,1.17739],[51.109619,1.17987],[51.110512,1.18248],[51.111488,1.18548],[51.112228,1.18863],[51.112499,1.19082],[51.112549,1.19196],[51.112549,1.19278],[51.112518,1.19351],[51.112469,1.19398],[51.11235,1.19533],[51.112228,1.19671],[51.112171,1.19839],[51.11219,1.19926],[51.112209,1.20014],[51.112331,1.20197],[51.112438,1.20275],[51.112541,1.20346],[51.112839,1.20577],[51.11301,1.20811],[51.113022,1.21006],[51.11293,1.2119],[51.11264,1.21474],[51.112301,1.21747],[51.111851,1.22028],[51.111382,1.22301],[51.110882,1.22546],[51.110329,1.22787],[51.10997,1.22901],[51.10955,1.23013],[51.108589,1.23208],[51.106739,1.23498],[51.105942,1.23623],[51.10466,1.23946],[51.104389,1.24029],[51.10429,1.24069],[51.104172,1.24137],[51.10397,1.24288],[51.103889,1.24393],[51.103859,1.24491],[51.10387,1.24596],[51.103958,1.24726],[51.10405,1.24807],[51.104221,1.24973],[51.104488,1.25164],[51.104809,1.25353],[51.10564,1.2573],[51.107071,1.26226],[51.107208,1.26301],[51.107529,1.26477],[51.107689,1.26757],[51.107849,1.27028],[51.108292,1.27241],[51.109692,1.27641],[51.11018,1.27878],[51.110298,1.28074],[51.110031,1.285],[51.110329,1.28792],[51.11063,1.28913],[51.111111,1.29063],[51.112011,1.29313],[51.11293,1.29586],[51.11335,1.29733],[51.113689,1.29877],[51.114029,1.30058],[51.114239,1.30197],[51.114311,1.3025],[51.11441,1.30284],[51.114471,1.30292],[51.11454,1.30295],[51.114601,1.30302],[51.114639,1.30313],[51.114651,1.30328],[51.114639,1.30338],[51.11459,1.30349],[51.114552,1.30354],[51.114559,1.30386],[51.114571,1.30415],[51.114658,1.30462],[51.114731,1.30493],[51.11491,1.30535],[51.11507,1.30566],[51.11525,1.30597],[51.115429,1.3062],[51.115829,1.30659],[51.11618,1.30687],[51.116539,1.30705],[51.11694,1.30718],[51.1171,1.3072],[51.117249,1.30716],[51.117298,1.30712],[51.11739,1.30709],[51.11747,1.30711],[51.11755,1.3072],[51.11771,1.30735],[51.117859,1.30746],[51.118038,1.30755],[51.118301,1.30769],[51.11861,1.30787],[51.118938,1.30809],[51.119362,1.30841],[51.119888,1.30906],[51.11993,1.30902],[51.11998,1.30901],[51.12001,1.30901],[51.12006,1.30904],[51.120098,1.30911],[51.120121,1.30918],[51.120121,1.30924],[51.120609,1.3098],[51.12125,1.31049],[51.122311,1.3116],[51.122829,1.31228],[51.123299,1.31321],[51.12336,1.31319],[51.12344,1.31321],[51.123489,1.31326],[51.123531,1.31334],[51.12355,1.31343],[51.12355,1.31351],[51.123531,1.3136],[51.123501,1.31366],[51.12384,1.31478],[51.123871,1.31488],[51.12392,1.31503],[51.1241,1.31553],[51.12455,1.3167],[51.125172,1.31831],[51.125408,1.31906],[51.125462,1.3194],[51.125481,1.31952],[51.1255,1.3205],[51.12537,1.3222],[51.12534,1.32278],[51.125351,1.32315],[51.12537,1.32341],[51.125389,1.32368],[51.1255,1.3245],[51.12595,1.32607],[51.126171,1.32679],[51.126251,1.32687],[51.126301,1.32687],[51.12635,1.32691],[51.126381,1.32697],[51.1264,1.32701],[51.126411,1.32709],[51.126411,1.32714],[51.12661,1.3272],[51.12674,1.32733],[51.127281,1.32823],[51.127659,1.32897],[51.12793,1.3295],[51.128151,1.33004],[51.128342,1.33049],[51.128391,1.33063],[51.128429,1.33076],[51.128479,1.331],[51.128502,1.33119],[51.128632,1.33167],[51.128719,1.33201],[51.12878,1.33245],[51.128799,1.3326],[51.12886,1.33275],[51.129009,1.33327],[51.12907,1.33347],[51.12907,1.33365],[51.12907,1.33392],[51.129421,1.33511],[51.12965,1.33549],[51.129799,1.33605],[51.12986,1.33621],[51.129921,1.33647],[51.12994,1.33681],[51.1301,1.33749],[51.130089,1.33783],[51.129978,1.33815],[51.129921,1.33843],[51.12991,1.33859],[51.12989,1.33884],[51.12989,1.33906],[51.129921,1.33965],[51.130001,1.34022],[51.130131,1.34103],[51.130161,1.34122],[51.13018,1.3414],[51.130169,1.34149],[51.13015,1.34158],[51.130112,1.34162],[51.130058,1.34167],[51.12999,1.34169],[51.129921,1.34164],[51.129879,1.34158],[51.129848,1.34154],[51.12981,1.34135],[51.12981,1.34135],[51.129761,1.34097],[51.1297,1.3406],[51.129681,1.34054],[51.129601,1.34023],[51.129601,1.3402],[51.129551,1.33999],[51.129539,1.3399],[51.12952,1.33983],[51.129509,1.33976],[51.12949,1.33967],[51.129478,1.33961],[51.129459,1.33953],[51.12944,1.33945],[51.129349,1.33897],[51.129341,1.3389],[51.129292,1.33865],[51.12928,1.33857],[51.129269,1.33852],[51.12925,1.33846],[51.1292,1.3382],[51.12899,1.33747],[51.128502,1.33599],[51.127621,1.33327],[51.127369,1.33316],[51.126629,1.33378],[51.126621,1.33374],[51.126621,1.33364],[51.12664,1.33357],[51.12669,1.33347],[51.124249,1.33631],[51.12339,1.33681],[51.122921,1.33723],[51.122219,1.33852],[51.121521,1.34088],[51.1213,1.34214],[51.120991,1.34396],[51.121029,1.34623],[51.12122,1.34811],[51.121658,1.3505],[51.122429,1.35514],[51.122669,1.35707],[51.12252,1.35925],[51.117809,1.37432],[51.113098,1.38939],[51.108391,1.40446],[51.10368,1.41953],[51.098961,1.4346],[51.09425,1.44967],[51.089539,1.46474],[51.084831,1.47981],[51.080109,1.49488],[51.068069,1.51962],[51.053921,1.56329],[51.04071,1.59852],[51.025211,1.63092],[51.001999,1.66988],[50.982979,1.702],[50.971821,1.73021],[50.965912,1.75008],[50.965778,1.7616],[50.967621,1.78272],[50.970249,1.81447],[50.9734,1.83058],[50.971569,1.84148],[50.970322,1.84528],[50.96946,1.84855],[50.968941,1.85085],[50.967468,1.851],[50.9664,1.85395],[50.965809,1.85499],[50.965721,1.85539],[50.965389,1.85658],[50.965279,1.857],[50.965061,1.85736],[50.964859,1.85768],[50.964828,1.85799],[50.964859,1.85852],[50.96513,1.86018],[50.965439,1.86224],[50.96553,1.86291],[50.965591,1.86335],[50.965679,1.86408],[50.965759,1.86463],[50.965801,1.86492],[50.96571,1.86559],[50.966,1.86722],[50.966209,1.86859],[50.9664,1.86985],[50.966579,1.87094],[50.966721,1.87124],[50.966881,1.87146],[50.967152,1.87174],[50.967251,1.87199],[50.967319,1.87213],[50.967339,1.8723],[50.967319,1.87242],[50.967258,1.87253],[50.967171,1.87264],[50.967049,1.87269],[50.966961,1.87267],[50.9669,1.87264],[50.966782,1.87256],[50.966679,1.87258],[50.966621,1.87266],[50.966579,1.87277],[50.966572,1.87295],[50.966591,1.87306],[50.966709,1.87319],[50.966831,1.87318],[50.9669,1.87312],[50.966942,1.87316],[50.967289,1.87339],[50.9678,1.87385],[50.968369,1.87442],[50.968632,1.87467],[50.968922,1.87501],[50.968971,1.87539],[50.969151,1.87581],[50.96944,1.87606],[50.969521,1.87685],[50.969688,1.87737],[50.97023,1.87846],[50.970631,1.88081],[50.971611,1.88645],[50.97216,1.88977],[50.972839,1.89413],[50.973099,1.89619],[50.973129,1.89712],[50.97298,1.89819],[50.972778,1.8989],[50.972679,1.89918],[50.972198,1.90005],[50.971581,1.90064],[50.97086,1.90113],[50.970188,1.9014],[50.969372,1.90176],[50.96859,1.90212],[50.967812,1.90248],[50.964081,1.90407],[50.961891,1.9049],[50.96096,1.9052],[50.959148,1.90522],[50.95834,1.90519],[50.95726,1.90522],[50.956211,1.90542],[50.955238,1.90564],[50.9543,1.90587],[50.95359,1.90598],[50.95314,1.90604],[50.951931,1.90612],[50.950241,1.90554],[50.948601,1.90488],[50.94746,1.90462],[50.946918,1.90463],[50.946239,1.90463],[50.94558,1.90469],[50.94376,1.90518],[50.941341,1.90606],[50.93996,1.90648],[50.938591,1.90685],[50.938332,1.90688],[50.93803,1.90684],[50.937759,1.90675],[50.93718,1.90661],[50.936871,1.90664],[50.936359,1.90679],[50.936211,1.90684],[50.935741,1.907],[50.93536,1.90711],[50.93515,1.90722],[50.93494,1.90754],[50.934849,1.90806],[50.93491,1.90848],[50.935089,1.90874],[50.935341,1.909],[50.93557,1.90922],[50.935749,1.90945],[50.935871,1.90982],[50.935982,1.91027],[50.9361,1.91173],[50.93652,1.91885],[50.936661,1.92109],[50.93705,1.9273],[50.937328,1.93228],[50.93745,1.93517],[50.937481,1.93688],[50.937592,1.94222],[50.93758,1.94278],[50.937469,1.94724],[50.937031,1.954],[50.936668,1.95871],[50.936298,1.96403],[50.936111,1.96788],[50.936081,1.96839],[50.936081,1.96851],[50.93605,1.96892],[50.935841,1.97239],[50.935669,1.97436],[50.935249,1.97886],[50.934761,1.98359],[50.93433,1.98798],[50.933788,1.99334],[50.933262,1.99872],[50.93314,1.99992],[50.93272,2.00394],[50.932549,2.00585],[50.932232,2.00935],[50.931931,2.01479],[50.931839,2.0177],[50.931839,2.02036],[50.931911,2.0256],[50.932259,2.03095],[50.932838,2.0366],[50.93351,2.04213],[50.93404,2.04668],[50.934681,2.0518],[50.934731,2.05231],[50.93486,2.05341],[50.935459,2.05849],[50.93618,2.06459],[50.936821,2.06931],[50.937,2.07046],[50.93721,2.07157],[50.938049,2.07576],[50.939331,2.08131],[50.940979,2.08698],[50.943771,2.09651],[50.944969,2.10024],[50.945171,2.10083],[50.945358,2.10132],[50.94603,2.103],[50.947449,2.10617],[50.948669,2.10898],[50.94949,2.11112],[50.95013,2.11311],[50.950569,2.11476],[50.95084,2.11595],[50.951061,2.11703],[50.951229,2.11799],[50.95134,2.11879],[50.95142,2.11946],[50.951481,2.12005],[50.951561,2.12091],[50.951611,2.12154],[50.95163,2.12226],[50.95166,2.12399],[50.95163,2.12719],[50.95166,2.12849],[50.951679,2.12922],[50.95174,2.12994],[50.951801,2.13068],[50.952049,2.13256],[50.95219,2.13337],[50.952339,2.13407],[50.95245,2.13468],[50.952751,2.13587],[50.95314,2.13722],[50.95356,2.1384],[50.955509,2.14382],[50.95594,2.14511],[50.956402,2.14664],[50.956619,2.14741],[50.957272,2.15017],[50.957581,2.15165],[50.95792,2.15362],[50.958241,2.1558],[50.958389,2.15706],[50.958488,2.15826],[50.958569,2.15916],[50.958691,2.16131],[50.958729,2.16278],[50.958759,2.16826],[50.958771,2.17093],[50.958771,2.1724],[50.958778,2.17312],[50.958771,2.17719],[50.958809,2.18107],[50.958809,2.18387],[50.958832,2.18546],[50.95887,2.18725],[50.958931,2.1886],[50.959,2.18962],[50.959042,2.19044],[50.959202,2.1941],[50.95929,2.19583],[50.959358,2.19713],[50.959431,2.19857],[50.95977,2.2044],[50.959888,2.20581],[50.959999,2.20656],[50.960129,2.20742],[50.9603,2.2083],[50.960491,2.20918],[50.96106,2.21099],[50.961369,2.21185],[50.96188,2.21307],[50.962372,2.2141],[50.963051,2.2153],[50.9636,2.21608],[50.964081,2.21676],[50.964951,2.21779],[50.966351,2.21906],[50.967548,2.21984],[50.968819,2.2204],[50.969082,2.22051],[50.96999,2.22091],[50.971722,2.22168],[50.973011,2.22223],[50.975269,2.22326],[50.977989,2.22447],[50.979801,2.22537],[50.981491,2.22651],[50.98312,2.22801],[50.98465,2.22979],[50.985142,2.23047],[50.98571,2.23135],[50.98613,2.23207],[50.987309,2.23417],[50.98785,2.23533],[50.988258,2.23622],[50.988621,2.2371],[50.988838,2.23776],[50.988979,2.23815],[50.98951,2.23991],[50.98983,2.24111],[50.990131,2.24249],[50.990311,2.24335],[50.990471,2.24433],[50.990582,2.2451],[50.990631,2.24546],[50.990749,2.24652],[50.990849,2.24767],[50.991001,2.24997],[50.991089,2.25132],[50.991219,2.25285],[50.991371,2.25542],[50.991428,2.25736],[50.99139,2.25824],[50.99131,2.25904],[50.991131,2.26062],[50.990978,2.26203],[50.990929,2.2628],[50.990929,2.26349],[50.990959,2.26412],[50.991089,2.26534],[50.991329,2.26651],[50.991539,2.26752],[50.99189,2.26896],[50.992081,2.26975],[50.992519,2.27123],[50.99271,2.27176],[50.992908,2.27231],[50.993698,2.27429],[50.993881,2.27475],[50.994141,2.27543],[50.994438,2.27647],[50.994991,2.27878],[50.9953,2.2799],[50.99596,2.28193],[50.99688,2.28418],[50.997162,2.2849],[50.997421,2.28563],[50.998192,2.2878],[50.99921,2.29085],[50.999458,2.29158],[51.000069,2.29328],[51.00098,2.29593],[51.002178,2.29964],[51.002411,2.30036],[51.002861,2.30196],[51.003071,2.3028],[51.003368,2.30435],[51.003601,2.30583],[51.004189,2.3101],[51.00425,2.31055],[51.00428,2.31072],[51.004551,2.31257],[51.00457,2.31275],[51.004662,2.3134],[51.005409,2.31722],[51.006069,2.31984],[51.00629,2.32056],[51.007221,2.32332],[51.00766,2.32452],[51.008259,2.32605],[51.008968,2.32791],[51.00951,2.32936],[51.00988,2.33063],[51.01022,2.3319],[51.010448,2.3329],[51.01078,2.33461],[51.01096,2.33604],[51.011009,2.33643],[51.011589,2.34118],[51.01228,2.34741],[51.012379,2.34865],[51.012421,2.34995],[51.012428,2.35025],[51.01247,2.35212],[51.012482,2.35917],[51.01247,2.36228],[51.01247,2.36496],[51.012508,2.36668],[51.012539,2.36733],[51.012569,2.36826],[51.01263,2.36958],[51.012718,2.37139],[51.01276,2.37266],[51.01281,2.37337],[51.012859,2.37427],[51.012989,2.37692],[51.013031,2.37775],[51.0131,2.37894],[51.013119,2.37918],[51.013168,2.37968],[51.013229,2.38015],[51.01339,2.38113],[51.01387,2.38398],[51.013981,2.38455],[51.014462,2.38727],[51.015091,2.39079],[51.01532,2.39201],[51.015518,2.39305],[51.01577,2.39428],[51.016029,2.39543],[51.016209,2.39619],[51.016369,2.39682],[51.01656,2.39753],[51.017361,2.40001],[51.01757,2.40063],[51.018608,2.40362],[51.018929,2.40452],[51.020679,2.40955],[51.02113,2.41077],[51.02158,2.41194],[51.022331,2.41373],[51.02293,2.41513],[51.02372,2.41692],[51.024632,2.41896],[51.026299,2.42273],[51.02718,2.42467],[51.028221,2.42699],[51.030571,2.43217],[51.031361,2.43401],[51.033642,2.43905],[51.035229,2.44255],[51.036591,2.44564],[51.03743,2.4476],[51.037861,2.44877],[51.03817,2.44976],[51.03846,2.45073],[51.038769,2.45191],[51.039108,2.45333],[51.039459,2.45497],[51.040298,2.45914],[51.04211,2.46828],[51.042839,2.47194],[51.043209,2.47404],[51.043419,2.47535],[51.043671,2.47711],[51.043831,2.47876],[51.04398,2.48044],[51.044079,2.4824],[51.04414,2.48386],[51.04417,2.48536],[51.04414,2.48689],[51.044071,2.48871],[51.044022,2.48969],[51.043941,2.49072],[51.043228,2.49809],[51.042229,2.50844],[51.042099,2.51063],[51.042042,2.51265],[51.04208,2.51446],[51.04216,2.51609],[51.042301,2.5175],[51.042431,2.51842],[51.042789,2.52042],[51.043201,2.52211],[51.043598,2.52368],[51.044231,2.52565],[51.04472,2.5272],[51.044941,2.52797],[51.045132,2.52855],[51.04546,2.52966],[51.04578,2.53064],[51.045891,2.53098],[51.046169,2.5318],[51.04644,2.5325],[51.046551,2.5328],[51.047539,2.53531],[51.048191,2.53675],[51.048828,2.53811],[51.051281,2.54349],[51.052811,2.54681],[51.053501,2.5486],[51.054089,2.5503],[51.054699,2.55229],[51.055302,2.55448],[51.055779,2.55651],[51.056301,2.55905],[51.056591,2.56043],[51.057049,2.56247],[51.057251,2.5634],[51.058319,2.56843],[51.058601,2.56969],[51.05888,2.57087],[51.059212,2.57214],[51.05962,2.57351],[51.060001,2.57471],[51.060371,2.57579],[51.060902,2.57714],[51.061588,2.57888],[51.062038,2.58001],[51.063679,2.58404],[51.064041,2.58492],[51.0644,2.58588],[51.064911,2.58728],[51.065319,2.58853],[51.065651,2.58961],[51.066101,2.59122],[51.066479,2.59272],[51.06683,2.59427],[51.067131,2.59571],[51.06741,2.59735],[51.06752,2.59797],[51.067711,2.59921],[51.06786,2.6003],[51.068031,2.60169],[51.068169,2.60318],[51.06831,2.60502],[51.06839,2.60678],[51.068409,2.6073],[51.068439,2.60869],[51.068439,2.6096],[51.068409,2.61156],[51.068352,2.61305],[51.068291,2.61409],[51.068241,2.61486],[51.068169,2.61588],[51.06805,2.61712],[51.067928,2.61827],[51.067799,2.61933],[51.067631,2.62045],[51.06739,2.62205],[51.067131,2.62364],[51.066879,2.62531],[51.066589,2.62707],[51.066341,2.62856],[51.06609,2.63003],[51.065769,2.63167],[51.065529,2.63282],[51.065239,2.63404],[51.064911,2.63527],[51.064499,2.63671],[51.064251,2.63747],[51.064041,2.63811],[51.063499,2.63943],[51.06292,2.64086],[51.06221,2.64252],[51.061131,2.64454],[51.06012,2.64638],[51.059299,2.64799],[51.05862,2.6494],[51.058022,2.65077],[51.057529,2.6522],[51.05703,2.65394],[51.056808,2.65493],[51.056419,2.65689],[51.05621,2.65862],[51.056099,2.65998],[51.056091,2.66042],[51.056019,2.66226],[51.056011,2.66247],[51.05621,2.66523],[51.056252,2.66562],[51.05637,2.66661],[51.056469,2.66746],[51.05687,2.67003],[51.057079,2.67121],[51.057301,2.67227],[51.057659,2.67373],[51.058041,2.67517],[51.0583,2.676],[51.058529,2.67676],[51.059441,2.67934],[51.059929,2.68044],[51.060501,2.68175],[51.061081,2.68296],[51.061581,2.68396],[51.062191,2.68504],[51.06329,2.68672],[51.066238,2.69064],[51.069191,2.6946],[51.06953,2.69505],[51.07011,2.69584],[51.071651,2.69795],[51.072418,2.69904],[51.072762,2.69952],[51.07328,2.70028],[51.073631,2.70076],[51.075062,2.70318],[51.075989,2.70478],[51.076469,2.7056],[51.07737,2.70742],[51.078041,2.70881],[51.080669,2.71368],[51.082119,2.71651],[51.08403,2.72024],[51.08596,2.72395],[51.08749,2.72654],[51.08762,2.72676],[51.088009,2.72735],[51.08828,2.72776],[51.089901,2.72983],[51.090542,2.73054],[51.092491,2.73254],[51.097069,2.73603],[51.100849,2.7394],[51.10141,2.73993],[51.102261,2.74083],[51.104359,2.74302],[51.10585,2.74498],[51.106361,2.74564],[51.10854,2.7486],[51.109261,2.74981],[51.11198,2.75436],[51.11467,2.76005],[51.114891,2.76061],[51.115601,2.7626],[51.115761,2.76306],[51.116161,2.76409],[51.116589,2.76529],[51.117771,2.76841],[51.12117,2.77827],[51.12418,2.78692],[51.124359,2.78746],[51.124859,2.78887],[51.12764,2.7969],[51.127831,2.79746],[51.12862,2.79973],[51.129101,2.80112],[51.129269,2.80159],[51.132858,2.81214],[51.133221,2.81331],[51.133461,2.8141],[51.133888,2.81561],[51.134201,2.81676],[51.134811,2.8192],[51.135349,2.82163],[51.13567,2.82325],[51.135899,2.82449],[51.136089,2.82548],[51.136349,2.82713],[51.1371,2.83239],[51.13726,2.83359],[51.137409,2.83465],[51.138371,2.8417],[51.139099,2.84658],[51.140308,2.85454],[51.141491,2.86184],[51.14164,2.86276],[51.1422,2.86733],[51.142479,2.86962],[51.14296,2.87444],[51.144299,2.8852],[51.145679,2.89336],[51.146931,2.89956],[51.147221,2.90083],[51.147518,2.90218],[51.149181,2.9089],[51.150909,2.91532],[51.15292,2.92111],[51.153099,2.92162],[51.15398,2.92417],[51.154831,2.92664],[51.157249,2.93277],[51.158779,2.9367],[51.161579,2.94386],[51.162491,2.94619],[51.163288,2.94829],[51.16412,2.95068],[51.16468,2.95227],[51.16494,2.95305],[51.165619,2.95527],[51.166962,2.96013],[51.16769,2.96342],[51.168159,2.96567],[51.16877,2.96918],[51.16906,2.97102],[51.169399,2.97327],[51.171879,2.99036],[51.17207,2.99165],[51.172211,2.99269],[51.172989,2.99807],[51.17305,2.99851],[51.17329,3.00016],[51.173649,3.00226],[51.17411,3.0044],[51.17445,3.0058],[51.174931,3.00759],[51.175331,3.00901],[51.17564,3.00987],[51.17952,3.01954],[51.179989,3.02066],[51.18058,3.02217],[51.18092,3.02299],[51.18111,3.02352],[51.181301,3.02409],[51.18166,3.02515],[51.182072,3.02648],[51.182388,3.02762],[51.18367,3.03306],[51.185581,3.04182],[51.189091,3.05743],[51.18932,3.0583],[51.18961,3.05942],[51.190521,3.06289],[51.191109,3.06485],[51.19252,3.06975],[51.19273,3.07071],[51.192909,3.07177],[51.193031,3.0727],[51.19313,3.07392],[51.193161,3.07501],[51.19313,3.07626],[51.193081,3.07739],[51.193001,3.07852],[51.19286,3.07972],[51.192612,3.08154],[51.191601,3.0869],[51.191349,3.08837],[51.189911,3.09536],[51.189129,3.0984],[51.1884,3.10066],[51.18821,3.10126],[51.186199,3.10705],[51.184799,3.11107],[51.18198,3.11918],[51.18063,3.1231],[51.177151,3.13324],[51.172661,3.14639],[51.170872,3.15257],[51.17012,3.15582],[51.168468,3.16401],[51.166939,3.17116],[51.163761,3.18813],[51.163589,3.18902],[51.163559,3.18919],[51.162868,3.19267],[51.162819,3.19292],[51.162769,3.19321],[51.16209,3.19636],[51.161621,3.19818],[51.16148,3.19868],[51.16127,3.19942],[51.160938,3.20048],[51.160412,3.20206],[51.160301,3.20234],[51.159901,3.20339],[51.159859,3.2035],[51.159431,3.20455],[51.158451,3.20644],[51.1577,3.20792],[51.15741,3.2085],[51.157162,3.209],[51.156761,3.20971],[51.155579,3.21174],[51.1549,3.21289],[51.153931,3.2146],[51.15324,3.21591],[51.15237,3.2175],[51.152191,3.21782],[51.15126,3.21969],[51.151169,3.21993],[51.15036,3.22156],[51.14901,3.22481],[51.14785,3.22818],[51.146881,3.23154],[51.146709,3.23211],[51.14645,3.23302],[51.144199,3.24088],[51.141628,3.25038],[51.141071,3.25233],[51.14082,3.25322],[51.140671,3.25373],[51.13924,3.25883],[51.136539,3.26866],[51.13134,3.28713],[51.128139,3.29863],[51.123081,3.3166],[51.12204,3.32055],[51.120621,3.32559],[51.118851,3.33186],[51.115269,3.34479],[51.112011,3.35628],[51.111431,3.35809],[51.110771,3.35983],[51.104359,3.37599],[51.1012,3.38387],[51.099739,3.38761],[51.095131,3.39893],[51.094082,3.40177],[51.09256,3.40559],[51.09137,3.40854],[51.089691,3.41275],[51.087132,3.41912],[51.085651,3.42274],[51.084728,3.42507],[51.083801,3.42739],[51.082878,3.42956],[51.081799,3.43221],[51.077339,3.4436],[51.076519,3.44591],[51.07608,3.44729],[51.075981,3.44763],[51.07539,3.44979],[51.07523,3.45041],[51.074879,3.4518],[51.074501,3.45334],[51.07251,3.46253],[51.07196,3.46512],[51.066978,3.48751],[51.06411,3.50061],[51.06105,3.51623],[51.05904,3.5268],[51.058491,3.52974],[51.05685,3.53852],[51.052608,3.55965],[51.05125,3.56586],[51.050892,3.56749],[51.050529,3.56911],[51.050449,3.56951],[51.048389,3.5789],[51.043869,3.59986],[51.03994,3.61792],[51.03949,3.61953],[51.03775,3.62573],[51.034882,3.63601],[51.03474,3.63647],[51.0336,3.64051],[51.033539,3.6407],[51.032398,3.64472],[51.031979,3.64616],[51.030102,3.65281],[51.024891,3.67076],[51.02475,3.67125],[51.023972,3.67402],[51.023472,3.67574],[51.022491,3.67923],[51.022339,3.67977],[51.021801,3.68161],[51.021339,3.68336],[51.02124,3.68376],[51.020981,3.68476],[51.020741,3.68568],[51.020451,3.68685],[51.019531,3.69031],[51.019001,3.69241],[51.018669,3.69363],[51.017109,3.70012],[51.014702,3.71009],[51.014622,3.71042],[51.014179,3.71226],[51.012611,3.71878],[51.01199,3.72128],[51.011631,3.72217],[51.011311,3.72284],[51.010921,3.72339],[51.010578,3.72382],[51.010239,3.72423],[51.009869,3.72483],[51.00975,3.72508],[51.00951,3.72588],[51.00948,3.72621],[51.009491,3.72647],[51.009541,3.72679],[51.009609,3.72702],[51.00983,3.72759],[51.01009,3.72808],[51.010429,3.72839],[51.01075,3.7285],[51.010948,3.72849],[51.01115,3.7284],[51.01136,3.72827],[51.011532,3.72811],[51.011829,3.72787],[51.012039,3.72778],[51.012211,3.72778],[51.012581,3.72798],[51.01424,3.72894],[51.014629,3.72916],[51.014919,3.72937],[51.01688,3.73074],[51.018459,3.73179],[51.020302,3.73307],[51.021832,3.73444],[51.02388,3.7366],[51.025539,3.73839],[51.026699,3.74038],[51.026909,3.74077],[51.028519,3.74369],[51.028671,3.744],[51.028851,3.74435],[51.02964,3.74592],[51.031132,3.74879],[51.03175,3.74997],[51.033428,3.75321],[51.03426,3.75482],[51.03434,3.755],[51.034649,3.75563],[51.03513,3.75661],[51.03561,3.75785],[51.035999,3.75894],[51.036079,3.75915],[51.036282,3.75982],[51.03661,3.76089],[51.037029,3.76254],[51.037769,3.76571],[51.039028,3.771],[51.040112,3.77556],[51.040489,3.77719],[51.04076,3.77847],[51.042011,3.7838],[51.043049,3.78806],[51.043869,3.79144],[51.044189,3.7928],[51.044739,3.79514],[51.044922,3.79591],[51.046181,3.80122],[51.047771,3.80846],[51.04842,3.81174],[51.051239,3.82769],[51.052109,3.8319],[51.053669,3.83831],[51.055191,3.84386],[51.061069,3.8642],[51.064442,3.87572],[51.06472,3.87678],[51.066898,3.88445],[51.06712,3.88559],[51.06768,3.88811],[51.067719,3.88837],[51.068501,3.89206],[51.06926,3.89805],[51.06974,3.90363],[51.070461,3.91495],[51.070679,3.91877],[51.07111,3.92565],[51.073029,3.95806],[51.07357,3.96646],[51.07431,3.97915],[51.075008,3.98714],[51.0751,3.98797],[51.075199,3.98883],[51.07579,3.99259],[51.07642,3.99564],[51.077061,3.99842],[51.0779,4.00133],[51.07872,4.00399],[51.079762,4.00683],[51.0811,4.01003],[51.08247,4.01287],[51.083832,4.0154],[51.084141,4.01594],[51.084549,4.01667],[51.086521,4.02014],[51.087921,4.02232],[51.08857,4.02339],[51.089588,4.02513],[51.09214,4.02944],[51.094528,4.03348],[51.095089,4.03443],[51.095211,4.03463],[51.100471,4.04349],[51.103989,4.049],[51.1068,4.05277],[51.11087,4.05734],[51.11171,4.05818],[51.112061,4.05854],[51.114491,4.06102],[51.116741,4.06331],[51.119381,4.0661],[51.120918,4.06809],[51.122429,4.07029],[51.123482,4.07216],[51.12402,4.07318],[51.124882,4.07494],[51.125778,4.07704],[51.126629,4.07964],[51.1269,4.08055],[51.127289,4.08194],[51.127541,4.08293],[51.12801,4.08511],[51.128479,4.08777],[51.128948,4.09103],[51.129021,4.09139],[51.13044,4.10455],[51.131821,4.1169],[51.132099,4.1194],[51.132549,4.12348],[51.13287,4.12635],[51.13327,4.12978],[51.133492,4.1312],[51.133839,4.13343],[51.134129,4.13519],[51.13456,4.13755],[51.13567,4.14353],[51.13641,4.14755],[51.137051,4.15104],[51.137211,4.15195],[51.13842,4.15828],[51.13921,4.16272],[51.1399,4.16663],[51.140591,4.17049],[51.141171,4.17362],[51.141891,4.17733],[51.142601,4.181],[51.142792,4.1819],[51.14307,4.18315],[51.143871,4.18615],[51.144581,4.18849],[51.145512,4.1912],[51.146679,4.19441],[51.147179,4.19574],[51.148769,4.20004],[51.149929,4.2034],[51.151112,4.20707],[51.152241,4.21068],[51.15329,4.21422],[51.154541,4.21836],[51.15575,4.22231],[51.157169,4.22699],[51.15839,4.23061],[51.159031,4.23227],[51.15947,4.23338],[51.160358,4.23531],[51.16151,4.23769],[51.16222,4.23907],[51.163422,4.24145],[51.16465,4.24383],[51.166279,4.24703],[51.166729,4.24793],[51.16856,4.25151],[51.170139,4.25456],[51.171581,4.25746],[51.172611,4.25952],[51.173389,4.26121],[51.174561,4.26389],[51.175739,4.26696],[51.176899,4.26997],[51.17799,4.27286],[51.1791,4.27582],[51.180599,4.2799],[51.181931,4.2834],[51.182461,4.28477],[51.183208,4.28673],[51.184212,4.28934],[51.18536,4.29224],[51.18586,4.29331],[51.18729,4.29642],[51.188278,4.29836],[51.18964,4.30093],[51.191269,4.30374],[51.192951,4.30655],[51.19482,4.30962],[51.19622,4.31194],[51.19809,4.3151],[51.200298,4.31877],[51.20142,4.32063],[51.201969,4.32153],[51.202431,4.32237],[51.202721,4.32293],[51.203899,4.32522],[51.204651,4.32687],[51.205391,4.32855],[51.206261,4.33073],[51.208328,4.33607],[51.208649,4.33695],[51.210098,4.34071],[51.211281,4.34388],[51.21146,4.34438],[51.211811,4.3453],[51.21233,4.34667],[51.212791,4.348],[51.213051,4.34876],[51.21312,4.34901],[51.213211,4.34932],[51.21349,4.35058],[51.21365,4.3516],[51.213749,4.35238],[51.21384,4.35324],[51.21389,4.35429],[51.213909,4.35537],[51.21386,4.35653],[51.21368,4.35807],[51.21347,4.35916],[51.213249,4.36017],[51.212978,4.36114],[51.21265,4.3621],[51.212238,4.36311],[51.211731,4.36418],[51.21101,4.36534],[51.210381,4.3662],[51.208759,4.36794],[51.208309,4.36843],[51.20274,4.37432],[51.20155,4.3756],[51.20089,4.37635],[51.2006,4.37673],[51.200272,4.37721],[51.19981,4.37797],[51.199322,4.37899],[51.199009,4.37978],[51.19873,4.38062],[51.198471,4.38164],[51.198238,4.38273],[51.19799,4.38423],[51.197701,4.38573],[51.19759,4.38626],[51.197311,4.38756],[51.19706,4.3886],[51.19685,4.38936],[51.19664,4.39006],[51.196251,4.39129],[51.195099,4.39424],[51.194302,4.39627],[51.193001,4.39983],[51.192059,4.40279],[51.191349,4.40556],[51.190941,4.40767],[51.190632,4.40985],[51.190472,4.41161],[51.19038,4.41322],[51.19035,4.41513],[51.19038,4.41674],[51.190498,4.4188],[51.190659,4.42035],[51.190891,4.42221],[51.191311,4.42416],[51.191719,4.42575],[51.192131,4.42716],[51.192619,4.42862],[51.193001,4.42966],[51.193321,4.43038],[51.193649,4.43107],[51.19397,4.43165],[51.194241,4.4321],[51.194618,4.43266],[51.194981,4.43311],[51.195259,4.43343],[51.19561,4.43381],[51.19595,4.43416],[51.196289,4.43445],[51.196659,4.43472],[51.197411,4.43528],[51.198662,4.43609],[51.201191,4.43746],[51.202412,4.43821],[51.203381,4.43891],[51.20462,4.43994],[51.206181,4.44129],[51.206921,4.44199],[51.207901,4.44294],[51.20924,4.44419],[51.210659,4.44546],[51.21167,4.44639],[51.21254,4.44721],[51.213921,4.44847],[51.214569,4.44921],[51.21471,4.4494],[51.214809,4.44956],[51.214951,4.4498],[51.215069,4.45005],[51.215179,4.45031],[51.215279,4.45061],[51.21553,4.45146],[51.215752,4.45216],[51.215969,4.45301],[51.216179,4.45406],[51.21629,4.45504],[51.21624,4.4558],[51.216091,4.45644],[51.21587,4.45707],[51.215561,4.4577],[51.21513,4.45828],[51.214211,4.45917],[51.214001,4.45936],[51.213348,4.45995],[51.212799,4.46049],[51.212372,4.46099],[51.21188,4.46168],[51.211639,4.46209],[51.211399,4.4626],[51.21117,4.46318],[51.210999,4.46376],[51.21085,4.46433],[51.21072,4.46503],[51.21064,4.46571],[51.21059,4.46636],[51.21059,4.46705],[51.21064,4.46793],[51.21069,4.46847],[51.210751,4.4691],[51.210831,4.4697],[51.210949,4.47055],[51.211071,4.47136],[51.211208,4.47228],[51.21133,4.47315],[51.211391,4.47381],[51.21143,4.47447],[51.211441,4.47509],[51.211418,4.4757],[51.211369,4.4763],[51.211288,4.47694],[51.211151,4.47781],[51.21104,4.47848],[51.210621,4.48085],[51.210522,4.48162],[51.210468,4.48231],[51.210442,4.48312],[51.210449,4.48395],[51.210522,4.485],[51.21067,4.48653],[51.2108,4.4878],[51.211021,4.49018],[51.211121,4.49141],[51.211189,4.49236],[51.211281,4.49391],[51.211311,4.49473],[51.211399,4.49656],[51.211411,4.49859],[51.21143,4.49937],[51.211521,4.50276],[51.211601,4.50624],[51.211712,4.51037],[51.211819,4.51426],[51.211979,4.51977],[51.212101,4.52414],[51.212139,4.52645],[51.212139,4.5272],[51.212139,4.52783],[51.212101,4.52956],[51.212009,4.53141],[51.211868,4.53313],[51.21167,4.53514],[51.211361,4.53743],[51.211048,4.5392],[51.210789,4.54045],[51.210499,4.54188],[51.210258,4.54291],[51.20974,4.54486],[51.20895,4.54791],[51.207958,4.55163],[51.207031,4.55523],[51.206242,4.55827],[51.205238,4.56186],[51.204288,4.56546],[51.203209,4.5695],[51.202259,4.57309],[51.201279,4.57603],[51.200741,4.57732],[51.200111,4.57852],[51.199451,4.57959],[51.198872,4.58057],[51.19838,4.58161],[51.19804,4.58262],[51.1978,4.5836],[51.197651,4.58463],[51.197559,4.58614],[51.197651,4.5877],[51.197849,4.58903],[51.198071,4.58982],[51.19841,4.59072],[51.198761,4.59151],[51.199219,4.59231],[51.19952,4.59268],[51.199821,4.59306],[51.2006,4.59405],[51.201351,4.59523],[51.202019,4.59651],[51.202499,4.5977],[51.20274,4.59835],[51.203411,4.60025],[51.2048,4.60414],[51.205589,4.60638],[51.20805,4.61359],[51.20908,4.61659],[51.209782,4.61862],[51.2118,4.62442],[51.211979,4.62497],[51.21299,4.62775],[51.21402,4.63045],[51.215729,4.63444],[51.217651,4.63834],[51.220181,4.64284],[51.22282,4.64712],[51.231232,4.66047],[51.233978,4.66484],[51.236111,4.66835],[51.237961,4.67215],[51.238979,4.67465],[51.239761,4.67689],[51.240608,4.67974],[51.241291,4.68251],[51.241741,4.68479],[51.24213,4.68706],[51.242741,4.6915],[51.243031,4.69416],[51.243351,4.69842],[51.243519,4.70165],[51.24366,4.70643],[51.243729,4.71221],[51.24371,4.71458],[51.243629,4.72741],[51.24353,4.74118],[51.243649,4.75037],[51.243801,4.7541],[51.244019,4.75768],[51.244381,4.76209],[51.24469,4.765],[51.245781,4.77292],[51.24646,4.77688],[51.24728,4.78085],[51.248569,4.7859],[51.250038,4.79077],[51.250561,4.79228],[51.252048,4.79611],[51.254349,4.80124],[51.25631,4.80483],[51.257271,4.80658],[51.259121,4.80975],[51.260399,4.81183],[51.266781,4.82263],[51.279442,4.84386],[51.282082,4.84837],[51.284592,4.85299],[51.285591,4.85501],[51.286049,4.85596],[51.287418,4.85902],[51.288658,4.862],[51.28981,4.86514],[51.290352,4.86664],[51.291531,4.87026],[51.29224,4.87277],[51.292912,4.87527],[51.29356,4.87801],[51.29409,4.88039],[51.294601,4.88287],[51.295071,4.88551],[51.29549,4.88814],[51.29586,4.89084],[51.29615,4.89339],[51.29641,4.89605],[51.296761,4.90148],[51.29689,4.90434],[51.297009,4.90816],[51.297138,4.91369],[51.29726,4.91806],[51.297291,4.91929],[51.297428,4.92479],[51.297451,4.92556],[51.29755,4.92814],[51.29763,4.93275],[51.29784,4.94177],[51.297951,4.94568],[51.298038,4.94993],[51.298092,4.95214],[51.298229,4.95715],[51.298328,4.96224],[51.298389,4.96824],[51.298351,4.97133],[51.298229,4.97483],[51.298038,4.97831],[51.297821,4.98128],[51.297489,4.98522],[51.297081,4.9888],[51.296631,4.99216],[51.295898,4.9968],[51.29517,5.00171],[51.294781,5.00454],[51.294411,5.00746],[51.294209,5.00934],[51.29406,5.01122],[51.293911,5.01361],[51.293781,5.01604],[51.29372,5.01984],[51.293751,5.02273],[51.293812,5.02471],[51.293911,5.02694],[51.294369,5.03214],[51.29475,5.03562],[51.29538,5.04046],[51.296322,5.04725],[51.296661,5.05005],[51.296989,5.05315],[51.29726,5.05621],[51.297401,5.05818],[51.297489,5.06011],[51.297539,5.0623],[51.29755,5.06443],[51.297489,5.06721],[51.29734,5.07002],[51.297009,5.07402],[51.296612,5.07796],[51.295879,5.08397],[51.29549,5.08691],[51.295132,5.09009],[51.294731,5.09394],[51.29464,5.09467],[51.294441,5.09768],[51.294319,5.10016],[51.29425,5.10457],[51.294312,5.10802],[51.294498,5.11234],[51.294731,5.11532],[51.29509,5.11857],[51.295509,5.12156],[51.29599,5.12459],[51.296761,5.12847],[51.298199,5.13422],[51.300072,5.14081],[51.300591,5.14276],[51.301399,5.1459],[51.301991,5.14842],[51.30265,5.15159],[51.303249,5.15458],[51.303871,5.15814],[51.30452,5.16165],[51.305229,5.16517],[51.30595,5.16817],[51.306999,5.17226],[51.30851,5.17732],[51.310181,5.18249],[51.31218,5.18855],[51.312382,5.1892],[51.314838,5.19669],[51.318821,5.20905],[51.32016,5.21303],[51.320591,5.21436],[51.321072,5.21581],[51.321671,5.21766],[51.322681,5.22073],[51.323341,5.22275],[51.324051,5.22488],[51.32439,5.22589],[51.325031,5.22768],[51.325691,5.2294],[51.326279,5.23089],[51.327061,5.23264],[51.327991,5.23451],[51.32906,5.23651],[51.33009,5.23831],[51.331451,5.24065],[51.337521,5.25108],[51.344028,5.26264],[51.349178,5.27182],[51.351452,5.27587],[51.352482,5.27774],[51.353378,5.27947],[51.353821,5.28036],[51.35434,5.28142],[51.35508,5.28302],[51.355801,5.28465],[51.356491,5.28625],[51.36055,5.29579],[51.360729,5.29619],[51.363239,5.30209],[51.36348,5.30268],[51.364941,5.30605],[51.365059,5.30632],[51.36898,5.31556],[51.370361,5.31878],[51.37159,5.32166],[51.374432,5.32837],[51.375191,5.33016],[51.376862,5.33405],[51.382038,5.34624],[51.38332,5.34934],[51.384441,5.35214],[51.385429,5.35471],[51.387878,5.3613],[51.388371,5.36264],[51.389221,5.36492],[51.390381,5.36807],[51.39267,5.37428],[51.393459,5.37644],[51.39439,5.379],[51.394581,5.37961],[51.394798,5.3803],[51.394989,5.38097],[51.395168,5.38164],[51.395432,5.38274],[51.39555,5.38332],[51.395679,5.38394],[51.395851,5.38488],[51.395931,5.38535],[51.396049,5.38617],[51.396118,5.38674],[51.396259,5.38787],[51.396339,5.38878],[51.39642,5.38967],[51.39653,5.39132],[51.396641,5.393],[51.39674,5.39426],[51.396851,5.39539],[51.396912,5.39591],[51.397099,5.39728],[51.397221,5.39805],[51.397369,5.39886],[51.397449,5.39924],[51.397629,5.40014],[51.39777,5.40073],[51.397919,5.40135],[51.398209,5.40239],[51.40057,5.41075],[51.400631,5.41097],[51.402519,5.41765],[51.40287,5.41891],[51.403229,5.42027],[51.403629,5.422],[51.403839,5.42325],[51.403992,5.42403],[51.404099,5.42481],[51.40416,5.4252],[51.404202,5.42569],[51.404209,5.42611],[51.404221,5.42679],[51.404221,5.42789],[51.404209,5.42864],[51.404202,5.42919],[51.40419,5.42974],[51.404209,5.4303],[51.404209,5.43096],[51.404228,5.43145],[51.404259,5.43249],[51.404289,5.43305],[51.40435,5.43362],[51.404461,5.43508],[51.40453,5.43605],[51.404621,5.43689],[51.40485,5.43825],[51.404949,5.43928],[51.405041,5.44026],[51.405121,5.44118],[51.405201,5.44248],[51.405251,5.44356],[51.405369,5.44983],[51.405399,5.45333],[51.405449,5.45596],[51.405491,5.4582],[51.405571,5.46179],[51.40559,5.46252],[51.405609,5.4658],[51.405609,5.46911],[51.405521,5.47301],[51.40551,5.47352],[51.405399,5.47652],[51.40538,5.47713],[51.40527,5.48024],[51.405239,5.48126],[51.404968,5.48955],[51.404942,5.49025],[51.404911,5.49086],[51.404839,5.49202],[51.404781,5.49246],[51.404701,5.49293],[51.40461,5.49339],[51.40453,5.49377],[51.404469,5.4942],[51.404419,5.49469],[51.404388,5.495],[51.404388,5.49536],[51.404388,5.49565],[51.40443,5.49614],[51.404449,5.49643],[51.40448,5.4969],[51.404541,5.49732],[51.404621,5.49771],[51.404709,5.49809],[51.4048,5.49852],[51.404861,5.49884],[51.4049,5.49925],[51.404919,5.49962],[51.40493,5.49999],[51.404919,5.50091],[51.404919,5.50125],[51.4049,5.50403],[51.4049,5.50435],[51.40493,5.51077],[51.40493,5.51908],[51.404911,5.53358],[51.4049,5.53708],[51.4049,5.54587],[51.404911,5.54781],[51.404961,5.54935],[51.405041,5.5509],[51.40517,5.55247],[51.405239,5.55322],[51.40538,5.55445],[51.405571,5.55591],[51.405788,5.55737],[51.40588,5.55797],[51.40617,5.55947],[51.40646,5.56091],[51.40659,5.56148],[51.40731,5.56419],[51.407681,5.56548],[51.408421,5.56768],[51.408791,5.56875],[51.408951,5.56924],[51.41061,5.57402],[51.411709,5.57722],[51.413349,5.582],[51.416458,5.5911],[51.41695,5.59265],[51.417591,5.59477],[51.417992,5.59638],[51.418369,5.59811],[51.41872,5.59991],[51.418949,5.60137],[51.419189,5.60318],[51.419449,5.60551],[51.420132,5.61227],[51.421539,5.62703],[51.421829,5.63011],[51.42268,5.63891],[51.423019,5.64245],[51.423439,5.64695],[51.423569,5.64864],[51.423649,5.6499],[51.423691,5.6508],[51.423698,5.65328],[51.423672,5.65704],[51.423641,5.6593],[51.42358,5.66349],[51.4235,5.66887],[51.423439,5.67272],[51.423409,5.676],[51.423359,5.67842],[51.423241,5.68237],[51.423222,5.68285],[51.42308,5.68647],[51.422939,5.6889],[51.422791,5.69085],[51.422359,5.69652],[51.422218,5.69818],[51.42205,5.70026],[51.421551,5.7066],[51.4212,5.7111],[51.42083,5.7156],[51.42057,5.71879],[51.420441,5.72116],[51.420319,5.723],[51.42025,5.72475],[51.420109,5.72959],[51.42012,5.73225],[51.42017,5.73484],[51.420212,5.73755],[51.420219,5.73999],[51.42017,5.74142],[51.42009,5.74328],[51.419949,5.74522],[51.419701,5.74773],[51.419529,5.74925],[51.419449,5.74987],[51.419128,5.75225],[51.418869,5.75407],[51.41861,5.75592],[51.418388,5.75762],[51.418079,5.75985],[51.41795,5.76072],[51.417461,5.76412],[51.417301,5.76526],[51.41711,5.76661],[51.41692,5.76774],[51.416599,5.76945],[51.41618,5.77184],[51.41555,5.77506],[51.415131,5.77699],[51.41449,5.7797],[51.414021,5.78159],[51.41349,5.7837],[51.412601,5.7868],[51.411781,5.78951],[51.410831,5.79252],[51.4072,5.80385],[51.407001,5.80447],[51.40556,5.80905],[51.404072,5.81369],[51.403431,5.81581],[51.402599,5.81868],[51.401981,5.82092],[51.3988,5.83371],[51.397251,5.83991],[51.396141,5.84441],[51.39502,5.8489],[51.393501,5.85508],[51.39146,5.86325],[51.39127,5.864],[51.390388,5.86731],[51.389561,5.87036],[51.387989,5.87586],[51.3848,5.88699],[51.382519,5.89479],[51.380829,5.90075],[51.380119,5.90336],[51.37936,5.90683],[51.37886,5.90941],[51.378521,5.91146],[51.378189,5.91406],[51.377979,5.9158],[51.377789,5.91788],[51.377682,5.91923],[51.377468,5.92297],[51.377441,5.92369],[51.377411,5.92498],[51.377399,5.92758],[51.377499,5.93505],[51.377659,5.94228],[51.377918,5.95907],[51.37801,5.96417],[51.378029,5.96599],[51.37801,5.96775],[51.377918,5.97046],[51.377781,5.97305],[51.377548,5.97627],[51.377331,5.98114],[51.37735,5.9839],[51.37735,5.98477],[51.37759,5.99092],[51.37812,5.99769],[51.37854,6.00253],[51.378769,6.00521],[51.378971,6.00723],[51.37949,6.01193],[51.380131,6.01689],[51.380531,6.01951],[51.381161,6.02336],[51.381538,6.02554],[51.38237,6.02959],[51.382751,6.03147],[51.383732,6.03571],[51.387409,6.05021],[51.389172,6.05713],[51.393082,6.07238],[51.393429,6.07391],[51.393791,6.0758],[51.393978,6.077],[51.394131,6.07807],[51.394249,6.07917],[51.394329,6.0803],[51.394421,6.08177],[51.394451,6.08392],[51.394199,6.09123],[51.394039,6.09627],[51.393539,6.10898],[51.393478,6.1104],[51.39336,6.11481],[51.39333,6.11742],[51.393471,6.1237],[51.393688,6.12859],[51.394279,6.13838],[51.39436,6.13939],[51.394451,6.14064],[51.394501,6.14145],[51.39518,6.15196],[51.39534,6.15451],[51.395611,6.15861],[51.395901,6.16434],[51.39592,6.16507],[51.39595,6.16609],[51.395969,6.1688],[51.395931,6.17027],[51.395851,6.17172],[51.395809,6.17254],[51.395741,6.17316],[51.39547,6.17562],[51.39521,6.17761],[51.39481,6.17986],[51.394588,6.18087],[51.39426,6.18234],[51.393848,6.18393],[51.393051,6.18666],[51.391201,6.19293],[51.389439,6.19895],[51.387581,6.20492],[51.387119,6.20635],[51.386139,6.20954],[51.384048,6.21632],[51.382431,6.22147],[51.382191,6.2223],[51.38166,6.22413],[51.381069,6.2267],[51.380482,6.23024],[51.380211,6.23265],[51.380039,6.23456],[51.379971,6.23568],[51.379929,6.23745],[51.379971,6.23919],[51.38002,6.24017],[51.380169,6.24235],[51.380199,6.24288],[51.380268,6.24355],[51.380409,6.24457],[51.38081,6.24762],[51.381229,6.24972],[51.381771,6.25191],[51.381851,6.25218],[51.3825,6.25446],[51.382992,6.25592],[51.384571,6.25981],[51.38628,6.26362],[51.38763,6.26717],[51.387741,6.26748],[51.388821,6.27117],[51.388981,6.27186],[51.389351,6.27366],[51.389759,6.27584],[51.38987,6.27655],[51.389969,6.27729],[51.390339,6.28112],[51.390339,6.28241],[51.390339,6.28301],[51.39035,6.28613],[51.390091,6.29202],[51.389912,6.29597],[51.38982,6.29785],[51.389729,6.30039],[51.389488,6.30467],[51.389172,6.31284],[51.388729,6.32214],[51.38855,6.329],[51.388599,6.33371],[51.388821,6.33742],[51.38884,6.33765],[51.38884,6.33775],[51.389149,6.34048],[51.389622,6.34365],[51.39024,6.3467],[51.390331,6.34707],[51.390652,6.34839],[51.391491,6.35144],[51.392441,6.35452],[51.393871,6.3589],[51.394058,6.35941],[51.394421,6.3605],[51.394821,6.36159],[51.39584,6.36458],[51.39621,6.36582],[51.39698,6.36793],[51.399311,6.3749],[51.400372,6.37825],[51.400539,6.37881],[51.401581,6.38237],[51.403149,6.38824],[51.403801,6.39103],[51.404282,6.39306],[51.404369,6.39346],[51.40443,6.39371],[51.40451,6.39412],[51.405708,6.40013],[51.406979,6.40767],[51.40802,6.41569],[51.40815,6.41689],[51.40823,6.41773],[51.408329,6.41866],[51.40844,6.41988],[51.408619,6.42204],[51.408718,6.42343],[51.408958,6.42648],[51.409351,6.43376],[51.410229,6.44922],[51.410912,6.46069],[51.411388,6.46954],[51.41164,6.47208],[51.411819,6.47329],[51.41193,6.47387],[51.412102,6.47472],[51.412529,6.47644],[51.41304,6.47806],[51.413429,6.47915],[51.41362,6.47958],[51.41433,6.48118],[51.416302,6.4848],[51.418781,6.48943],[51.419121,6.4901],[51.419258,6.49035],[51.419521,6.49084],[51.419819,6.49143],[51.420101,6.49197],[51.42136,6.49432],[51.423061,6.49833],[51.42363,6.49987],[51.42461,6.50291],[51.425228,6.50535],[51.426071,6.50966],[51.426102,6.50984],[51.426151,6.51011],[51.426491,6.51252],[51.426498,6.51262],[51.42659,6.51358],[51.426762,6.51535],[51.427052,6.52207],[51.427231,6.53069],[51.427238,6.53088],[51.427368,6.53329],[51.427521,6.53609],[51.42799,6.54291],[51.42828,6.54714],[51.428631,6.55212],[51.428928,6.55589],[51.429508,6.56421],[51.43005,6.56866],[51.43092,6.57325],[51.431541,6.57603],[51.432091,6.57825],[51.432789,6.58093],[51.433418,6.58378],[51.434471,6.58956],[51.435162,6.59419],[51.435532,6.59735],[51.435841,6.60087],[51.435982,6.60295],[51.436031,6.60391],[51.436089,6.60506],[51.436169,6.60728],[51.436211,6.60933],[51.43623,6.61085],[51.436218,6.61229],[51.436211,6.61338],[51.43618,6.61485],[51.436161,6.61573],[51.436119,6.61677],[51.436001,6.61847],[51.435909,6.62006],[51.43589,6.62054],[51.435791,6.62232],[51.435719,6.6238],[51.435619,6.6272],[51.435631,6.63186],[51.435719,6.63537],[51.435928,6.63872],[51.436218,6.64277],[51.43652,6.64744],[51.43663,6.64967],[51.43671,6.65219],[51.436729,6.65546],[51.43679,6.65711],[51.43697,6.66175],[51.437,6.66234],[51.437019,6.66297],[51.437279,6.67126],[51.437321,6.67279],[51.437359,6.67531],[51.43742,6.68066],[51.437401,6.68155],[51.43737,6.68277],[51.437271,6.68504],[51.437111,6.68668],[51.43681,6.6887],[51.43618,6.69207],[51.435699,6.69477],[51.435581,6.69569],[51.435509,6.69632],[51.43541,6.69751],[51.435349,6.69886],[51.435329,6.70035],[51.435379,6.70175],[51.435509,6.70337],[51.435692,6.70467],[51.436069,6.7069],[51.43811,6.71953],[51.438358,6.72115],[51.438541,6.7228],[51.438629,6.72482],[51.438511,6.72655],[51.438271,6.72848],[51.437729,6.73069],[51.436901,6.7328],[51.436451,6.73392],[51.436169,6.73462],[51.43568,6.73624],[51.435421,6.73745],[51.435291,6.73821],[51.435051,6.73985],[51.43491,6.74152],[51.43486,6.74321],[51.434849,6.74462],[51.434929,6.74645],[51.435169,6.74879],[51.435349,6.7499],[51.435471,6.75059],[51.43568,6.75184],[51.43605,6.75345],[51.436588,6.75525],[51.437061,6.75633],[51.43734,6.75687],[51.438301,6.7584],[51.439831,6.76023],[51.44173,6.76266],[51.44257,6.76421],[51.443211,6.76552],[51.443981,6.76754],[51.444592,6.7697],[51.445171,6.77222],[51.44598,6.77676],[51.44632,6.77867],[51.446621,6.78057],[51.447021,6.78296],[51.447361,6.78519],[51.44762,6.78704],[51.4478,6.78876],[51.44783,6.79036],[51.4478,6.79163],[51.447601,6.79349],[51.447311,6.79505],[51.44696,6.79636],[51.446671,6.79732],[51.44632,6.79822],[51.446072,6.79865],[51.445259,6.80026],[51.444401,6.80188],[51.44429,6.80213],[51.443951,6.80283],[51.443432,6.80394],[51.44305,6.80456],[51.44294,6.80471],[51.442791,6.80487],[51.44265,6.80495],[51.442459,6.80499],[51.442329,6.80496],[51.442181,6.80488],[51.442081,6.80479],[51.44194,6.80458],[51.44186,6.8043],[51.441811,6.8041],[51.441792,6.8038],[51.441792,6.80368],[51.441811,6.80346],[51.441879,6.80322],[51.441959,6.80295],[51.442089,6.80256],[51.442211,6.80226],[51.442429,6.80195],[51.442871,6.80134],[51.44342,6.8007],[51.444061,6.80015],[51.444431,6.79987],[51.444641,6.79971],[51.444809,6.7996],[51.44566,6.79921],[51.446529,6.799],[51.447182,6.79889],[51.447929,6.79884],[51.449249,6.79886],[51.450062,6.79895],[51.451248,6.7991],[51.45211,6.79927],[51.45311,6.79947],[51.454029,6.79984],[51.454899,6.80039],[51.45573,6.80101],[51.45639,6.80168],[51.456959,6.80235],[51.457588,6.80329],[51.458141,6.80427],[51.45866,6.80531],[51.459122,6.80651],[51.459789,6.80861],[51.460159,6.8097],[51.460659,6.81081],[51.46172,6.81251],[51.461948,6.81283],[51.462391,6.81341],[51.462681,6.81371],[51.463501,6.81453],[51.46389,6.81483],[51.464821,6.81552],[51.465771,6.8159],[51.466869,6.81625],[51.468349,6.81658],[51.470051,6.81669],[51.471851,6.8165],[51.473011,6.81621],[51.47398,6.81587],[51.474541,6.8157],[51.47541,6.81537],[51.47633,6.81497],[51.477489,6.81446],[51.478821,6.81388],[51.47916,6.81377],[51.480099,6.81351],[51.48127,6.81332],[51.48185,6.8133],[51.483139,6.81333],[51.483341,6.81342],[51.483582,6.81349],[51.484051,6.8136],[51.484409,6.8137],[51.4851,6.814],[51.4855,6.81421],[51.485771,6.8144],[51.486031,6.8146],[51.486149,6.81473],[51.48632,6.81496],[51.486488,6.81527],[51.48661,6.81557],[51.48674,6.81603],[51.486801,6.81641],[51.48682,6.81667],[51.486832,6.81699],[51.486809,6.81731],[51.486252,6.82101],[51.486198,6.82155],[51.486191,6.82224],[51.48613,6.82305],[51.486099,6.82352],[51.486069,6.82462],[51.486118,6.82628],[51.48629,6.82779],[51.48674,6.83007],[51.4874,6.83218],[51.488831,6.836],[51.489079,6.83642],[51.48975,6.83737],[51.490349,6.83822],[51.490829,6.83886],[51.49268,6.84133],[51.492962,6.84171],[51.493629,6.84264],[51.49432,6.84385],[51.4949,6.84507],[51.495281,6.84597],[51.49572,6.84735],[51.496052,6.8486],[51.496349,6.85008],[51.496571,6.85205],[51.496651,6.85463],[51.49654,6.85815],[51.496441,6.86022],[51.496342,6.86164],[51.49622,6.8647],[51.496101,6.86872],[51.496132,6.87109],[51.496342,6.88355],[51.496422,6.88532],[51.496639,6.8891],[51.496681,6.88994],[51.496769,6.89124],[51.49688,6.89292],[51.49704,6.89456],[51.49754,6.90146],[51.49781,6.91115],[51.49823,6.9167],[51.498699,6.92018],[51.499279,6.92279],[51.49995,6.9251],[51.500381,6.92628],[51.502979,6.93204],[51.503391,6.93294],[51.50415,6.93473],[51.50428,6.93505],[51.504478,6.93559],[51.50473,6.93621],[51.505058,6.93707],[51.50531,6.93774],[51.50568,6.93884],[51.505909,6.93961],[51.506149,6.94042],[51.50634,6.94113],[51.506481,6.94171],[51.50668,6.94259],[51.506882,6.94349],[51.507061,6.94441],[51.507309,6.94577],[51.507511,6.94717],[51.507629,6.94811],[51.507679,6.9483],[51.507751,6.94906],[51.507851,6.95002],[51.507919,6.95101],[51.50798,6.95199],[51.508011,6.95296],[51.508049,6.95394],[51.508049,6.95491],[51.50803,6.95637],[51.508011,6.95741],[51.507969,6.95846],[51.5079,6.95952],[51.507809,6.96061],[51.50771,6.96166],[51.50761,6.96267],[51.507511,6.96364],[51.507401,6.96457],[51.507301,6.96548],[51.50721,6.96642],[51.507099,6.96736],[51.507011,6.96826],[51.506908,6.96914],[51.506802,6.97007],[51.506618,6.97107],[51.506481,6.97167],[51.506088,6.97303],[51.50581,6.97399],[51.50378,6.97994],[51.50354,6.9808],[51.503361,6.98158],[51.50322,6.98288],[51.503109,6.98417],[51.503059,6.98502],[51.503059,6.98587],[51.503132,6.98712],[51.503201,6.98794],[51.50338,6.98916],[51.503559,6.98996],[51.50386,6.99122],[51.50407,6.99203],[51.504471,6.99341],[51.504799,6.99441],[51.505051,6.99517],[51.50531,6.99594],[51.505661,6.99694],[51.505951,6.99787],[51.50618,6.99864],[51.50639,6.99936],[51.506611,7.0001],[51.50679,7.00076],[51.50692,7.00141],[51.50713,7.00247],[51.507252,7.0032],[51.507309,7.00377],[51.507389,7.00478],[51.507469,7.00601],[51.507511,7.00706],[51.507568,7.00815],[51.507622,7.0094],[51.50771,7.01091],[51.507778,7.01189],[51.5079,7.01303],[51.50798,7.01356],[51.50808,7.01418],[51.50853,7.01628],[51.508598,7.01657],[51.50882,7.01736],[51.508911,7.01776],[51.508991,7.01802],[51.509449,7.01924],[51.509651,7.01977],[51.51001,7.02061],[51.510441,7.0216],[51.51067,7.02212],[51.510971,7.02282],[51.511318,7.02362],[51.511749,7.02466],[51.51218,7.02575],[51.512489,7.02662],[51.51302,7.02839],[51.51318,7.02901],[51.513241,7.02923],[51.513378,7.02978],[51.5135,7.03033],[51.51379,7.03182],[51.51405,7.03356],[51.514198,7.03489],[51.514351,7.03674],[51.51437,7.03743],[51.514381,7.03811],[51.5144,7.03938],[51.51442,7.04053],[51.514431,7.04131],[51.514469,7.04353],[51.514469,7.04414],[51.514488,7.04472],[51.514542,7.04728],[51.51458,7.04906],[51.514709,7.0513],[51.514931,7.05337],[51.515228,7.05491],[51.51569,7.05666],[51.51609,7.0581],[51.51664,7.05958],[51.51804,7.06284],[51.519421,7.06611],[51.51976,7.06685],[51.520069,7.0676],[51.520451,7.06844],[51.521461,7.07034],[51.522091,7.07128],[51.522469,7.07174],[51.522919,7.07226],[51.523548,7.07292],[51.523918,7.07324],[51.524281,7.07349],[51.52504,7.07395],[51.525612,7.07422],[51.526218,7.0745],[51.52739,7.07508],[51.528431,7.07578],[51.529202,7.07652],[51.529968,7.07744],[51.530621,7.07847],[51.531349,7.07998],[51.531639,7.08085],[51.53178,7.08126],[51.532188,7.08277],[51.532478,7.08456],[51.532539,7.08514],[51.532681,7.0868],[51.532902,7.08914],[51.533161,7.09096],[51.533421,7.09249],[51.533749,7.09376],[51.534119,7.09503],[51.534389,7.09584],[51.534439,7.09597],[51.534561,7.09629],[51.53529,7.09819],[51.535419,7.09858],[51.535782,7.09977],[51.536011,7.10056],[51.536228,7.10172],[51.536419,7.10277],[51.536591,7.10419],[51.53746,7.11268],[51.537781,7.11582],[51.537899,7.117],[51.53796,7.11818],[51.537991,7.11909],[51.537979,7.12019],[51.53783,7.12271],[51.53772,7.12502],[51.537651,7.12646],[51.537651,7.12701],[51.53764,7.1282],[51.53764,7.12896],[51.537651,7.12917],[51.53764,7.12952],[51.53801,7.135],[51.538422,7.1388],[51.538589,7.1399],[51.538929,7.14149],[51.53949,7.14344],[51.540791,7.14728],[51.540798,7.14734],[51.541142,7.14849],[51.541241,7.14885],[51.541569,7.15025],[51.54187,7.15221],[51.542019,7.15344],[51.54203,7.15516],[51.541931,7.15783],[51.541889,7.15901],[51.541821,7.16064],[51.541889,7.16227],[51.541931,7.16295],[51.54224,7.16765],[51.542301,7.16893],[51.542358,7.17118],[51.542389,7.17196],[51.5424,7.17221],[51.54258,7.17451],[51.54261,7.17482],[51.54285,7.17645],[51.542992,7.17739],[51.543129,7.17809],[51.543251,7.17887],[51.543362,7.17973],[51.543541,7.18114],[51.54364,7.18225],[51.54372,7.18371],[51.54377,7.18551],[51.543739,7.18735],[51.543751,7.18831],[51.543739,7.1901],[51.54377,7.19114],[51.54377,7.19203],[51.5438,7.19345],[51.5439,7.19547],[51.54401,7.197],[51.54406,7.19781],[51.544159,7.19858],[51.544319,7.19959],[51.544491,7.20032],[51.544949,7.20227],[51.545071,7.20274],[51.545212,7.20327],[51.5453,7.20364],[51.545719,7.20504],[51.547321,7.20951],[51.548038,7.2115],[51.54821,7.21198],[51.548439,7.2125],[51.549198,7.21465],[51.5495,7.21541],[51.555611,7.23041],[51.555901,7.23109],[51.55603,7.23137],[51.556141,7.23164],[51.556469,7.23245],[51.556751,7.2331],[51.557121,7.2339],[51.557549,7.23481],[51.557961,7.23604],[51.55835,7.23732],[51.558632,7.23866],[51.55888,7.24011],[51.559021,7.24148],[51.559101,7.2429],[51.559132,7.24386],[51.55899,7.24571],[51.558868,7.24714],[51.558651,7.24856],[51.5583,7.25041],[51.55806,7.25159],[51.557812,7.25266],[51.557541,7.25399],[51.55732,7.25532],[51.557159,7.25671],[51.55706,7.25809],[51.556992,7.25947],[51.557011,7.26144],[51.55706,7.26255],[51.557159,7.26354],[51.55751,7.26621],[51.557701,7.26752],[51.557861,7.26839],[51.557949,7.26905],[51.558071,7.26972],[51.55827,7.27111],[51.558392,7.27207],[51.558529,7.27356],[51.558609,7.27506],[51.55862,7.27656],[51.55859,7.27804],[51.558529,7.27895],[51.558529,7.27951],[51.558418,7.28097],[51.558361,7.28194],[51.558289,7.28291],[51.558239,7.28386],[51.558189,7.28481],[51.558159,7.28624],[51.558189,7.28766],[51.55827,7.28906],[51.558411,7.29047],[51.558571,7.29187],[51.558601,7.29208],[51.55867,7.29261],[51.55883,7.29417],[51.558949,7.29507],[51.559071,7.29598],[51.559189,7.29688],[51.559299,7.29778],[51.559422,7.29868],[51.559528,7.29958],[51.559639,7.30045],[51.559731,7.30127],[51.55983,7.30207],[51.559929,7.30283],[51.560032,7.30362],[51.56012,7.30442],[51.560211,7.3052],[51.56031,7.30583],[51.560349,7.30618],[51.560471,7.30717],[51.560551,7.30793],[51.560669,7.30902],[51.56078,7.30999],[51.56105,7.31307],[51.561241,7.3154],[51.56147,7.31788],[51.561569,7.31974],[51.561611,7.32072],[51.56171,7.32205],[51.561779,7.32318],[51.56184,7.32389],[51.562012,7.32659],[51.562149,7.33011],[51.56229,7.3331],[51.562389,7.33599],[51.562469,7.33965],[51.562519,7.34197],[51.562519,7.34284],[51.562519,7.34333],[51.562531,7.34573],[51.562469,7.3485],[51.562328,7.35043],[51.562069,7.35259],[51.562031,7.35289],[51.561779,7.35495],[51.561531,7.35659],[51.561291,7.35808],[51.561291,7.35811],[51.561199,7.35845],[51.561008,7.35929],[51.560909,7.3595],[51.56078,7.35966],[51.560692,7.35974],[51.560589,7.35978],[51.56049,7.35978],[51.560291,7.3597],[51.5602,7.3596],[51.56007,7.35931],[51.560032,7.35916],[51.560032,7.35899],[51.560059,7.35869],[51.560101,7.35858],[51.560181,7.35841],[51.560299,7.35828],[51.560379,7.35823],[51.560551,7.3582],[51.561131,7.35833],[51.561661,7.35851],[51.561779,7.35856],[51.561939,7.35859],[51.562241,7.3587],[51.562809,7.35894],[51.563351,7.35919],[51.563709,7.35935],[51.564259,7.35961],[51.564602,7.35978],[51.564892,7.35988],[51.56517,7.35999],[51.565578,7.36019],[51.566071,7.36044],[51.56638,7.3606],[51.566589,7.36071],[51.566719,7.36077],[51.56686,7.36084],[51.566952,7.36086],[51.567051,7.36085],[51.56723,7.36094],[51.567402,7.36103],[51.567589,7.36112],[51.568249,7.36145],[51.568581,7.36161],[51.568901,7.36176],[51.569561,7.36207],[51.569901,7.36223],[51.570229,7.36237],[51.571281,7.36284],[51.571812,7.36307],[51.572319,7.36329],[51.57275,7.36346],[51.573139,7.36362],[51.573471,7.36376],[51.573818,7.3639],[51.574638,7.36421],[51.575439,7.36451],[51.576359,7.36484],[51.576591,7.36492],[51.576988,7.36506],[51.5774,7.36519],[51.57777,7.36532],[51.578259,7.36548],[51.579189,7.36578],[51.579529,7.36596],[51.579689,7.36601],[51.580959,7.36641],[51.581139,7.36647],[51.582199,7.36688],[51.58263,7.36702],[51.58305,7.36722],[51.58326,7.36734],[51.583469,7.36749],[51.583649,7.36767],[51.583839,7.36786],[51.58403,7.36812],[51.58419,7.36836],[51.584339,7.36861],[51.58448,7.36891],[51.584629,7.36921],[51.58482,7.36963],[51.584969,7.36999],[51.585041,7.37021],[51.585091,7.37044],[51.585121,7.37069],[51.585152,7.37097],[51.585159,7.37122],[51.585159,7.37148],[51.585121,7.37199],[51.584991,7.37375],[51.584991,7.374],[51.584671,7.37836],[51.584621,7.37916],[51.58432,7.38337],[51.584221,7.3848],[51.584122,7.38621],[51.584019,7.38768],[51.583721,7.39179],[51.583691,7.39218],[51.583611,7.39328],[51.583569,7.39381],[51.583542,7.39437],[51.583488,7.39536],[51.58345,7.39625],[51.583389,7.39708],[51.58334,7.39788],[51.58329,7.3991],[51.583279,7.40034],[51.58329,7.40065],[51.583309,7.40171],[51.583382,7.40315],[51.583439,7.4039],[51.5835,7.40464],[51.583519,7.40483],[51.583591,7.40521],[51.583672,7.40557],[51.583721,7.40612],[51.58382,7.40704],[51.58392,7.40807],[51.58403,7.40904],[51.584202,7.41055],[51.58432,7.41158],[51.584431,7.41267],[51.584499,7.41334],[51.584549,7.41403],[51.584579,7.4145],[51.58461,7.4151],[51.584641,7.4157],[51.58466,7.41627],[51.584671,7.41685],[51.584671,7.41771],[51.584648,7.41847],[51.584629,7.41912],[51.584599,7.41974],[51.584549,7.42059],[51.584492,7.42138],[51.584431,7.42199],[51.584351,7.42266],[51.584221,7.42369],[51.58408,7.42462],[51.583832,7.42597],[51.583691,7.42671],[51.58353,7.42746],[51.58337,7.4282],[51.58321,7.42895],[51.582531,7.43192],[51.58099,7.43861],[51.577789,7.45246],[51.576969,7.45601],[51.57658,7.45769],[51.576351,7.4587],[51.57613,7.45966],[51.575909,7.46067],[51.57571,7.46165],[51.57552,7.46265],[51.575329,7.4637],[51.57518,7.46471],[51.575039,7.46575],[51.574928,7.4668],[51.574829,7.46786],[51.57476,7.46891],[51.574718,7.47],[51.574692,7.47104],[51.57468,7.47212],[51.574699,7.47319],[51.574749,7.47434],[51.57481,7.47533],[51.57489,7.4764],[51.57494,7.47691],[51.574989,7.47742],[51.575119,7.47844],[51.57523,7.47924],[51.57539,7.48021],[51.57555,7.48119],[51.57576,7.48235],[51.57608,7.48387],[51.576271,7.48479],[51.576309,7.485],[51.576771,7.48709],[51.577591,7.49089],[51.578011,7.49299],[51.578152,7.49385],[51.57827,7.4947],[51.5784,7.49571],[51.57851,7.49673],[51.57859,7.49762],[51.578651,7.49843],[51.578701,7.49912],[51.578739,7.4999],[51.578751,7.50038],[51.57877,7.50084],[51.578781,7.50189],[51.578781,7.50282],[51.578758,7.50375],[51.578739,7.5045],[51.578701,7.5054],[51.57869,7.50576],[51.578621,7.50705],[51.57859,7.50803],[51.578571,7.50862],[51.578529,7.50941],[51.578499,7.51038],[51.57848,7.5108],[51.57843,7.51217],[51.578381,7.51321],[51.578339,7.51423],[51.5783,7.51529],[51.578281,7.51577],[51.578259,7.51615],[51.578209,7.51752],[51.578171,7.51851],[51.578129,7.5196],[51.578091,7.5207],[51.578091,7.5218],[51.57811,7.52288],[51.578152,7.52394],[51.578201,7.52478],[51.57827,7.52559],[51.578331,7.52628],[51.578369,7.5266],[51.57843,7.52711],[51.578499,7.52769],[51.57864,7.52868],[51.57877,7.5294],[51.578899,7.53008],[51.578991,7.53053],[51.579079,7.53098],[51.579281,7.53187],[51.579441,7.53249],[51.579609,7.53312],[51.57983,7.53392],[51.58007,7.53472],[51.58046,7.53605],[51.580769,7.53709],[51.58123,7.53863],[51.581451,7.53938],[51.581871,7.54081],[51.582241,7.54203],[51.583309,7.54564],[51.58363,7.54673],[51.584259,7.54883],[51.584648,7.55012],[51.584831,7.55076],[51.585011,7.5514],[51.585159,7.55197],[51.585289,7.55252],[51.585411,7.55302],[51.585529,7.55354],[51.585651,7.55411],[51.58577,7.55468],[51.585869,7.55518],[51.58596,7.55569],[51.58606,7.5563],[51.586159,7.55691],[51.5863,7.55789],[51.586411,7.55872],[51.586491,7.55944],[51.586571,7.56016],[51.586861,7.56301],[51.58717,7.56606],[51.587811,7.57225],[51.588902,7.58372],[51.58952,7.5933],[51.59026,7.6039],[51.590408,7.60583],[51.590462,7.60636],[51.590549,7.60696],[51.59111,7.61037],[51.59132,7.61134],[51.591709,7.61331],[51.59182,7.614],[51.592159,7.61592],[51.592571,7.61796],[51.592892,7.61959],[51.59317,7.62098],[51.593712,7.62371],[51.594002,7.62533],[51.594719,7.62911],[51.59486,7.62982],[51.59499,7.63051],[51.597221,7.64195],[51.59819,7.64671],[51.598789,7.6504],[51.59893,7.65125],[51.599091,7.65217],[51.599911,7.65679],[51.60001,7.65743],[51.60043,7.65993],[51.600689,7.66178],[51.600769,7.66243],[51.60088,7.66422],[51.60091,7.66476],[51.60096,7.66599],[51.600948,7.66965],[51.60091,7.67532],[51.600891,7.67944],[51.600899,7.68501],[51.600891,7.6879],[51.60088,7.69047],[51.600891,7.69413],[51.600861,7.69814],[51.600868,7.70294],[51.600868,7.70605],[51.600941,7.70745],[51.60104,7.7089],[51.601219,7.71043],[51.601521,7.71234],[51.601768,7.71369],[51.60215,7.71536],[51.602661,7.71758],[51.603401,7.72063],[51.605679,7.73041],[51.606239,7.73281],[51.60643,7.73365],[51.607349,7.73746],[51.607731,7.73907],[51.60902,7.74463],[51.609558,7.74701],[51.609879,7.74839],[51.610779,7.75216],[51.61095,7.75295],[51.61179,7.75657],[51.612148,7.75829],[51.61359,7.7652],[51.613682,7.76564],[51.614151,7.76791],[51.6143,7.76865],[51.615742,7.77577],[51.616322,7.77862],[51.617611,7.78492],[51.618111,7.78763],[51.618752,7.79107],[51.619671,7.79649],[51.62072,7.8026],[51.621819,7.80895],[51.62244,7.81259],[51.623089,7.81769],[51.623421,7.82074],[51.6236,7.82378],[51.624069,7.83272],[51.624149,7.83382],[51.624611,7.84164],[51.624901,7.8468],[51.62495,7.84767],[51.625149,7.85185],[51.625198,7.85266],[51.625301,7.85381],[51.62553,7.85567],[51.625759,7.8571],[51.62603,7.85854],[51.626621,7.86089],[51.626999,7.86221],[51.627499,7.8637],[51.628529,7.86656],[51.63028,7.87145],[51.632408,7.87746],[51.63369,7.88111],[51.634609,7.88375],[51.635479,7.88627],[51.636829,7.89005],[51.638069,7.89329],[51.63982,7.89801],[51.643669,7.90798],[51.64444,7.90994],[51.64513,7.91146],[51.645748,7.91261],[51.646309,7.91357],[51.647079,7.91479],[51.64782,7.91587],[51.649281,7.91756],[51.650162,7.9185],[51.652962,7.92068],[51.65921,7.92535],[51.66478,7.92948],[51.666481,7.93092],[51.667461,7.93197],[51.668388,7.93306],[51.669121,7.93402],[51.669701,7.93487],[51.670361,7.93596],[51.67128,7.93766],[51.67181,7.9387],[51.672089,7.93925],[51.675251,7.94549],[51.675961,7.9468],[51.676571,7.94784],[51.677509,7.94919],[51.67844,7.9504],[51.679081,7.95118],[51.68021,7.95252],[51.681889,7.95451],[51.68465,7.9577],[51.68486,7.95795],[51.688831,7.96253],[51.68943,7.96323],[51.691681,7.96587],[51.694801,7.96948],[51.694969,7.96969],[51.696449,7.97137],[51.698071,7.97327],[51.699009,7.97433],[51.69981,7.97509],[51.700691,7.97584],[51.70166,7.97653],[51.70285,7.97724],[51.703911,7.97781],[51.704929,7.97819],[51.706108,7.97849],[51.70723,7.97867],[51.709469,7.97887],[51.712429,7.97905],[51.72028,7.97964],[51.72121,7.97971],[51.721931,7.9798],[51.722488,7.97991],[51.723068,7.98007],[51.724079,7.98043],[51.725029,7.98082],[51.725941,7.98132],[51.72683,7.98186],[51.730968,7.98433],[51.735161,7.98683],[51.73597,7.98732],[51.757,7.99996],[51.75713,8.00004],[51.761951,8.00292],[51.76778,8.00644],[51.76865,8.00706],[51.769272,8.00759],[51.769791,8.00808],[51.77037,8.00867],[51.771149,8.00953],[51.771778,8.01032],[51.772381,8.01117],[51.772739,8.01171],[51.773022,8.01213],[51.77364,8.01325],[51.774139,8.01421],[51.7747,8.01539],[51.77486,8.01581],[51.775139,8.01646],[51.775558,8.01758],[51.77586,8.01844],[51.77607,8.01915],[51.776249,8.01978],[51.776482,8.0207],[51.777779,8.02621],[51.779148,8.03231],[51.77919,8.0325],[51.77935,8.03314],[51.78109,8.04068],[51.78199,8.04458],[51.782379,8.04621],[51.782761,8.04768],[51.783119,8.0489],[51.78363,8.0505],[51.785709,8.05654],[51.7859,8.05711],[51.788849,8.0656],[51.790531,8.07057],[51.790661,8.07092],[51.79266,8.07673],[51.79438,8.08179],[51.796059,8.08666],[51.79829,8.09329],[51.798752,8.09476],[51.7994,8.09704],[51.800251,8.10029],[51.801769,8.10654],[51.802818,8.11106],[51.803341,8.11329],[51.803589,8.11438],[51.804901,8.12144],[51.806179,8.12817],[51.806469,8.1297],[51.806881,8.13148],[51.807301,8.133],[51.807522,8.13369],[51.80777,8.13451],[51.8083,8.13594],[51.80957,8.13884],[51.81089,8.14193],[51.81139,8.1432],[51.81179,8.14429],[51.812328,8.14601],[51.812851,8.14795],[51.813831,8.15192],[51.815701,8.15951],[51.819611,8.17346],[51.821659,8.18062],[51.823521,8.1873],[51.824162,8.1898],[51.824612,8.19176],[51.825001,8.19363],[51.825298,8.19525],[51.825661,8.19734],[51.826599,8.20373],[51.828011,8.21375],[51.828949,8.22073],[51.8321,8.2427],[51.833431,8.25189],[51.834709,8.26084],[51.83506,8.26298],[51.835461,8.26496],[51.836048,8.26736],[51.837231,8.27094],[51.840221,8.27917],[51.842819,8.28644],[51.843109,8.28733],[51.843418,8.28839],[51.844082,8.29078],[51.84436,8.29183],[51.8452,8.29493],[51.84552,8.29616],[51.84684,8.30111],[51.847271,8.30268],[51.848518,8.30731],[51.849789,8.31204],[51.850498,8.31436],[51.85062,8.31468],[51.851238,8.31633],[51.851891,8.31787],[51.853531,8.32144],[51.854641,8.32379],[51.855209,8.32498],[51.85619,8.32714],[51.857101,8.32945],[51.857349,8.33024],[51.857601,8.33111],[51.85788,8.33211],[51.85804,8.33269],[51.858318,8.33384],[51.85857,8.33501],[51.85894,8.33723],[51.859798,8.34333],[51.860321,8.34674],[51.860401,8.34727],[51.861069,8.35194],[51.86124,8.35297],[51.86142,8.35408],[51.861752,8.35569],[51.862141,8.35716],[51.862942,8.36004],[51.86388,8.36343],[51.86396,8.36376],[51.864109,8.36425],[51.865002,8.36734],[51.866741,8.37381],[51.867729,8.37732],[51.868149,8.37884],[51.868641,8.38072],[51.869041,8.38247],[51.86937,8.38443],[51.869659,8.38654],[51.871109,8.39815],[51.871651,8.40257],[51.871948,8.40499],[51.872162,8.40643],[51.872631,8.40925],[51.872952,8.41071],[51.873329,8.41213],[51.873749,8.4135],[51.874168,8.41477],[51.874729,8.41609],[51.875431,8.41777],[51.879452,8.42606],[51.88131,8.4298],[51.88176,8.43074],[51.88216,8.43158],[51.882431,8.43212],[51.88261,8.43246],[51.883171,8.43365],[51.88406,8.43552],[51.88525,8.438],[51.886379,8.44002],[51.887032,8.44107],[51.888119,8.4428],[51.889061,8.44421],[51.889858,8.44547],[51.890759,8.44697],[51.891472,8.44826],[51.89222,8.44966],[51.892891,8.45104],[51.893501,8.45238],[51.894169,8.45389],[51.894829,8.45555],[51.89537,8.45697],[51.895889,8.45831],[51.896221,8.45935],[51.896488,8.46014],[51.89698,8.4617],[51.897369,8.46326],[51.897789,8.46489],[51.89819,8.46655],[51.89856,8.46816],[51.898918,8.47006],[51.899799,8.47499],[51.900379,8.47826],[51.901348,8.48375],[51.90192,8.48683],[51.902241,8.48842],[51.903591,8.49471],[51.903889,8.49611],[51.903938,8.49633],[51.90406,8.49683],[51.90443,8.49858],[51.90485,8.50032],[51.90535,8.50198],[51.905899,8.50358],[51.90662,8.50537],[51.907452,8.50714],[51.90823,8.50857],[51.909039,8.50989],[51.909969,8.5112],[51.911041,8.51252],[51.912109,8.5137],[51.913021,8.51467],[51.91333,8.51497],[51.91526,8.51712],[51.916302,8.51825],[51.91737,8.51944],[51.918381,8.5205],[51.91951,8.52178],[51.92281,8.52542],[51.924339,8.52709],[51.92609,8.52888],[51.926949,8.5297],[51.927811,8.53037],[51.92894,8.53128],[51.92989,8.53191],[51.931068,8.53263],[51.93187,8.53305],[51.93512,8.53467],[51.935982,8.53512],[51.93679,8.53563],[51.937489,8.53612],[51.93824,8.5367],[51.93858,8.53698],[51.93906,8.53741],[51.939301,8.53765],[51.939751,8.53815],[51.940151,8.5386],[51.940842,8.53947],[51.941341,8.54009],[51.942139,8.54127],[51.94286,8.54242],[51.94323,8.54305],[51.943459,8.5435],[51.943748,8.54411],[51.944279,8.54521],[51.944771,8.54638],[51.945148,8.54732],[51.945351,8.54789],[51.94632,8.55056],[51.94648,8.55101],[51.946869,8.55216],[51.94733,8.55343],[51.94743,8.55374],[51.950321,8.56168],[51.95089,8.56321],[51.951962,8.56566],[51.95256,8.56682],[51.953461,8.56841],[51.954559,8.57018],[51.954639,8.5703],[51.955059,8.57101],[51.95639,8.57315],[51.957119,8.57434],[51.95779,8.57562],[51.958481,8.57689],[51.959141,8.57828],[51.959751,8.57966],[51.960361,8.58111],[51.96093,8.58259],[51.961929,8.58578],[51.962639,8.58817],[51.964272,8.59382],[51.96476,8.59554],[51.965649,8.59864],[51.966709,8.60208],[51.96719,8.60341],[51.967461,8.60407],[51.969151,8.60787],[51.970402,8.61055],[51.970772,8.6113],[51.971081,8.61183],[51.97139,8.61236],[51.971828,8.6129],[51.972309,8.61345],[51.97282,8.61393],[51.973431,8.61437],[51.973961,8.61469],[51.974499,8.61493],[51.975441,8.61518],[51.97644,8.61538],[51.977409,8.61549],[51.978371,8.61561],[51.979061,8.6157],[51.979389,8.61575],[51.980129,8.61587],[51.980331,8.61591],[51.98135,8.61604],[51.982288,8.61597],[51.98317,8.61576],[51.9841,8.61553],[51.984982,8.6153],[51.985439,8.6152],[51.985882,8.61516],[51.98682,8.6152],[51.98735,8.61529],[51.987831,8.61541],[51.988739,8.61577],[51.9897,8.61619],[51.98988,8.61626],[51.99004,8.61632],[51.9907,8.6166],[51.99086,8.61666],[51.99165,8.61701],[51.992439,8.61736],[51.992611,8.61745],[51.993599,8.61787],[51.994911,8.61845],[51.995369,8.61865],[51.9958,8.61883],[51.997459,8.61953],[51.997799,8.61967],[51.99855,8.61999],[51.999088,8.62024],[51.999481,8.6204],[51.999889,8.62059],[52.00095,8.62121],[52.00148,8.62154],[52.002121,8.62197],[52.002831,8.62255],[52.003342,8.623],[52.003979,8.62353],[52.004601,8.62405],[52.005199,8.62456],[52.00592,8.62518],[52.006649,8.62579],[52.006809,8.62593],[52.007721,8.62671],[52.00893,8.62773],[52.010181,8.62879],[52.011429,8.62977],[52.012291,8.63042],[52.01255,8.63061],[52.013939,8.63147],[52.014462,8.63181],[52.0159,8.63256],[52.01722,8.63319],[52.01857,8.63373],[52.019871,8.63422],[52.021141,8.63468],[52.02203,8.63501],[52.022339,8.63513],[52.023869,8.63568],[52.024651,8.63597],[52.024811,8.63603],[52.025478,8.63629],[52.027969,8.6372],[52.02935,8.63771],[52.030788,8.63828],[52.031471,8.63861],[52.032108,8.63895],[52.032879,8.63944],[52.032982,8.63951],[52.03352,8.63991],[52.034409,8.64064],[52.03516,8.64128],[52.035961,8.64212],[52.036591,8.64282],[52.037182,8.64357],[52.03833,8.64516],[52.039349,8.64674],[52.04047,8.64829],[52.041012,8.64892],[52.041649,8.64968],[52.042881,8.6509],[52.04414,8.65191],[52.04549,8.65281],[52.04697,8.65372],[52.047981,8.65432],[52.048161,8.65444],[52.04858,8.65471],[52.050201,8.65569],[52.052029,8.65683],[52.053902,8.65782],[52.055759,8.65866],[52.056389,8.65888],[52.05896,8.65966],[52.06068,8.66016],[52.063389,8.66092],[52.0644,8.66127],[52.06546,8.66172],[52.06646,8.66223],[52.06741,8.66276],[52.06839,8.6634],[52.06934,8.66409],[52.070309,8.66492],[52.07122,8.66574],[52.072128,8.66665],[52.073071,8.66769],[52.073898,8.6687],[52.074791,8.66986],[52.075588,8.67106],[52.076389,8.67232],[52.07716,8.67369],[52.077351,8.67404],[52.077431,8.67419],[52.077881,8.67505],[52.07856,8.67651],[52.07914,8.67787],[52.079689,8.67926],[52.080231,8.68064],[52.080742,8.68195],[52.081032,8.68267],[52.081261,8.68324],[52.081749,8.68446],[52.082199,8.68568],[52.08271,8.68697],[52.083191,8.68823],[52.083801,8.68973],[52.084461,8.69108],[52.085018,8.69204],[52.08551,8.69285],[52.085701,8.69313],[52.086071,8.69366],[52.086941,8.69476],[52.087109,8.69495],[52.088348,8.69625],[52.08963,8.69755],[52.08987,8.69779],[52.091042,8.69914],[52.091331,8.69947],[52.091862,8.70014],[52.092861,8.70151],[52.093109,8.70187],[52.093811,8.70295],[52.094212,8.70363],[52.094769,8.70458],[52.095451,8.70579],[52.09568,8.70625],[52.09721,8.70946],[52.097439,8.70994],[52.099529,8.71434],[52.101131,8.71777],[52.101261,8.71805],[52.101479,8.71853],[52.102081,8.7198],[52.102921,8.72151],[52.103481,8.72259],[52.10397,8.72343],[52.104481,8.72428],[52.104969,8.72507],[52.105549,8.72595],[52.108551,8.73051],[52.10973,8.73234],[52.110168,8.73303],[52.110771,8.7339],[52.111389,8.73469],[52.111851,8.73522],[52.112289,8.73566],[52.11285,8.73615],[52.11338,8.73657],[52.11377,8.73683],[52.114021,8.73698],[52.11462,8.73728],[52.115231,8.73755],[52.115681,8.73768],[52.116249,8.73781],[52.116859,8.73788],[52.117432,8.7379],[52.118141,8.73783],[52.118759,8.7377],[52.119438,8.73752],[52.120628,8.73726],[52.124889,8.73636],[52.12582,8.73621],[52.126659,8.73614],[52.127281,8.73615],[52.12785,8.73619],[52.128529,8.73633],[52.12936,8.73659],[52.129959,8.73687],[52.130539,8.73717],[52.131649,8.73792],[52.132839,8.739],[52.133789,8.74002],[52.13435,8.74077],[52.13456,8.74107],[52.135368,8.74246],[52.135929,8.74357],[52.136349,8.74463],[52.136742,8.74578],[52.137001,8.74657],[52.13744,8.74827],[52.137718,8.74973],[52.138359,8.75359],[52.13842,8.75398],[52.13879,8.75656],[52.13903,8.75876],[52.139229,8.76081],[52.139389,8.76305],[52.139408,8.76347],[52.13969,8.76717],[52.139919,8.76944],[52.140049,8.77036],[52.14016,8.77109],[52.14027,8.77176],[52.140659,8.77359],[52.1409,8.77464],[52.141029,8.77515],[52.1413,8.77632],[52.14188,8.77859],[52.141918,8.77874],[52.142818,8.7822],[52.143681,8.78554],[52.14452,8.78879],[52.14492,8.79018],[52.145649,8.79237],[52.146839,8.79541],[52.147991,8.7985],[52.148628,8.80016],[52.149361,8.80197],[52.14946,8.80217],[52.149792,8.80289],[52.150139,8.80355],[52.150181,8.80361],[52.150688,8.8044],[52.151588,8.80559],[52.152279,8.80629],[52.15361,8.80748],[52.155849,8.80938],[52.157341,8.81068],[52.15818,8.81133],[52.158909,8.81174],[52.159672,8.81207],[52.160351,8.81231],[52.164749,8.8136],[52.164989,8.81368],[52.16539,8.81381],[52.168892,8.8148],[52.170528,8.81523],[52.171021,8.81539],[52.17152,8.81563],[52.172192,8.816],[52.173,8.81661],[52.178951,8.82136],[52.179169,8.82156],[52.181911,8.82381],[52.18261,8.82431],[52.183281,8.82466],[52.18404,8.82497],[52.184589,8.82513],[52.18552,8.82528],[52.18766,8.82536],[52.18837,8.82545],[52.18885,8.8255],[52.189201,8.82555],[52.189449,8.82561],[52.190498,8.82589],[52.191158,8.82615],[52.191971,8.82656],[52.192581,8.8269],[52.193588,8.82747],[52.195042,8.82846],[52.195419,8.82872],[52.198071,8.83052],[52.198551,8.83085],[52.19976,8.83166],[52.200359,8.83217],[52.201069,8.83284],[52.20174,8.83362],[52.202339,8.83453],[52.202961,8.83556],[52.203571,8.83691],[52.204048,8.83833],[52.20438,8.83961],[52.204609,8.8406],[52.20483,8.84169],[52.20512,8.84355],[52.205269,8.84427],[52.20536,8.84474],[52.205509,8.84547],[52.205669,8.84615],[52.205929,8.84722],[52.20607,8.84783],[52.206478,8.84943],[52.206982,8.85093],[52.2075,8.8524],[52.208408,8.85498],[52.208771,8.85602],[52.209572,8.85826],[52.209862,8.85908],[52.21014,8.85993],[52.210258,8.86032],[52.210461,8.86108],[52.210659,8.86194],[52.210812,8.86277],[52.21093,8.86365],[52.210999,8.8642],[52.211048,8.86475],[52.211102,8.86559],[52.211151,8.86791],[52.21125,8.87073],[52.21125,8.87193],[52.211231,8.87273],[52.211189,8.87377],[52.211128,8.87522],[52.210911,8.88039],[52.210892,8.88137],[52.210911,8.88202],[52.21101,8.88493],[52.211239,8.89031],[52.211189,8.89171],[52.211079,8.89306],[52.210781,8.89507],[52.210609,8.8961],[52.210159,8.89882],[52.209759,8.90154],[52.209518,8.90427],[52.209461,8.90684],[52.209499,8.91353],[52.209549,8.91769],[52.209549,8.9181],[52.20956,8.92176],[52.20961,8.92312],[52.209671,8.92455],[52.209728,8.92545],[52.20982,8.92636],[52.209881,8.92682],[52.210041,8.92827],[52.210369,8.93009],[52.21067,8.93149],[52.2113,8.93413],[52.211449,8.93478],[52.211849,8.93633],[52.212269,8.9384],[52.212502,8.9396],[52.212711,8.94083],[52.212879,8.94212],[52.213051,8.94348],[52.21323,8.94536],[52.213539,8.94827],[52.21368,8.94928],[52.213951,8.9507],[52.214329,8.95231],[52.214691,8.95385],[52.21526,8.95603],[52.215549,8.95712],[52.21579,8.95823],[52.216141,8.96002],[52.21645,8.96171],[52.21664,8.96307],[52.21677,8.96447],[52.216881,8.96608],[52.21693,8.96771],[52.21693,8.96872],[52.21693,8.96993],[52.216831,8.97907],[52.216808,8.98151],[52.216759,8.9851],[52.21674,8.98697],[52.216728,8.98927],[52.21674,8.98993],[52.216789,8.99054],[52.21682,8.9912],[52.2169,8.99186],[52.21706,8.99292],[52.21714,8.99333],[52.217258,8.994],[52.2174,8.99456],[52.2178,8.99593],[52.21825,8.9975],[52.218712,8.99906],[52.218948,9.00004],[52.21912,9.00089],[52.219189,9.00138],[52.219311,9.00233],[52.21941,9.00328],[52.219521,9.00466],[52.219589,9.00562],[52.219669,9.00663],[52.21978,9.00785],[52.219929,9.00907],[52.2201,9.01008],[52.220291,9.01108],[52.220409,9.01157],[52.220791,9.01314],[52.221321,9.01521],[52.22142,9.01562],[52.221661,9.01673],[52.22184,9.01791],[52.22197,9.01901],[52.22205,9.02011],[52.222061,9.02136],[52.222,9.02263],[52.221901,9.02388],[52.221291,9.03157],[52.221218,9.0324],[52.22113,9.03318],[52.22102,9.03388],[52.220772,9.03518],[52.220249,9.03779],[52.220051,9.03881],[52.218788,9.04554],[52.218609,9.04663],[52.218441,9.04758],[52.218288,9.04868],[52.21817,9.04986],[52.218128,9.05084],[52.218151,9.0517],[52.218262,9.05309],[52.218342,9.05377],[52.218441,9.05453],[52.218689,9.056],[52.218891,9.05675],[52.2192,9.05781],[52.219662,9.05924],[52.22028,9.06112],[52.220879,9.06312],[52.221062,9.0639],[52.22123,9.0648],[52.221329,9.06549],[52.221409,9.06617],[52.221458,9.0669],[52.2215,9.06774],[52.2215,9.06863],[52.22147,9.06938],[52.221409,9.07029],[52.221149,9.07354],[52.22068,9.07999],[52.22049,9.08252],[52.220291,9.08523],[52.2202,9.08661],[52.22015,9.08735],[52.220131,9.08799],[52.2201,9.08931],[52.220139,9.09049],[52.220242,9.09183],[52.22039,9.09328],[52.22102,9.09803],[52.221352,9.10071],[52.221519,9.10211],[52.221649,9.10343],[52.221699,9.10437],[52.22171,9.10532],[52.221729,9.10629],[52.221691,9.1071],[52.221649,9.10781],[52.22155,9.10848],[52.221439,9.10903],[52.22131,9.10977],[52.22086,9.11192],[52.220482,9.11371],[52.22023,9.11495],[52.22002,9.11628],[52.21994,9.11706],[52.219879,9.11793],[52.21983,9.11944],[52.21991,9.12097],[52.219971,9.12181],[52.22007,9.12263],[52.22028,9.12413],[52.22049,9.12557],[52.220619,9.12718],[52.22065,9.12849],[52.220619,9.12928],[52.220581,9.13004],[52.22047,9.13138],[52.220119,9.13498],[52.21981,9.13805],[52.21973,9.13917],[52.219669,9.14079],[52.219551,9.14517],[52.219551,9.1457],[52.219479,9.14736],[52.219379,9.14908],[52.21817,9.15879],[52.218029,9.15981],[52.21785,9.16074],[52.217449,9.16232],[52.21669,9.16492],[52.216209,9.16663],[52.216,9.16779],[52.215839,9.16909],[52.215771,9.17014],[52.215752,9.17206],[52.215698,9.17478],[52.21563,9.17699],[52.215611,9.17739],[52.21545,9.18024],[52.215431,9.18139],[52.215511,9.18293],[52.215641,9.18409],[52.215759,9.1848],[52.2159,9.18562],[52.216171,9.18673],[52.216579,9.1883],[52.217991,9.19375],[52.218449,9.19555],[52.219471,9.19907],[52.21983,9.20038],[52.220951,9.20474],[52.221272,9.20601],[52.22147,9.20691],[52.221619,9.20768],[52.221802,9.20891],[52.221901,9.20997],[52.221958,9.21096],[52.22197,9.21188],[52.22187,9.21513],[52.22184,9.21685],[52.221901,9.21811],[52.22197,9.21912],[52.222031,9.21982],[52.222252,9.22108],[52.222549,9.22248],[52.222809,9.22344],[52.223091,9.22428],[52.223412,9.22504],[52.223789,9.2259],[52.224602,9.22741],[52.225891,9.22959],[52.22863,9.23392],[52.228882,9.23433],[52.23019,9.23661],[52.230541,9.23736],[52.230862,9.23816],[52.231152,9.23898],[52.231621,9.24076],[52.232052,9.24308],[52.232349,9.2454],[52.232571,9.24712],[52.23275,9.24839],[52.232841,9.24905],[52.23315,9.25142],[52.233521,9.25422],[52.233898,9.2571],[52.234241,9.25995],[52.234612,9.26276],[52.234951,9.26555],[52.235222,9.26732],[52.23531,9.26785],[52.235649,9.26968],[52.236031,9.27126],[52.236721,9.27361],[52.237251,9.27518],[52.23777,9.2765],[52.23822,9.27756],[52.23859,9.27833],[52.239071,9.27929],[52.23954,9.2801],[52.240299,9.28136],[52.241081,9.2825],[52.24173,9.2833],[52.24263,9.28436],[52.24453,9.28641],[52.24649,9.28847],[52.247452,9.28956],[52.24828,9.29058],[52.248501,9.29089],[52.249249,9.29197],[52.249989,9.29312],[52.250622,9.29429],[52.25116,9.2954],[52.254822,9.30336],[52.256031,9.30584],[52.256618,9.30694],[52.257198,9.3079],[52.25774,9.30869],[52.258369,9.30952],[52.259209,9.31058],[52.26017,9.31164],[52.261101,9.31259],[52.26149,9.31296],[52.26339,9.31468],[52.26498,9.31612],[52.26535,9.31651],[52.26646,9.31788],[52.267059,9.31869],[52.267681,9.31962],[52.268299,9.32062],[52.268822,9.32155],[52.269459,9.32285],[52.273449,9.33127],[52.274132,9.33276],[52.274872,9.3343],[52.275391,9.33547],[52.278141,9.34138],[52.278709,9.34251],[52.279369,9.34372],[52.280022,9.34479],[52.28017,9.34507],[52.28112,9.34654],[52.28614,9.3543],[52.287659,9.35666],[52.288509,9.35787],[52.289421,9.35901],[52.289719,9.35935],[52.291088,9.36072],[52.292488,9.36198],[52.292671,9.36213],[52.302601,9.37094],[52.319118,9.38574],[52.321159,9.38775],[52.322319,9.38908],[52.32336,9.39044],[52.324322,9.39183],[52.325069,9.39299],[52.32523,9.39327],[52.325859,9.39436],[52.326618,9.39575],[52.327579,9.39764],[52.328411,9.39929],[52.32859,9.39964],[52.329109,9.4006],[52.329769,9.40172],[52.330891,9.40352],[52.332241,9.40555],[52.333649,9.4077],[52.333889,9.40806],[52.33432,9.40873],[52.335529,9.41062],[52.335838,9.41112],[52.336159,9.41163],[52.337959,9.41435],[52.338539,9.41519],[52.339409,9.41632],[52.340111,9.41712],[52.34082,9.41784],[52.34166,9.4186],[52.342659,9.41942],[52.343609,9.42004],[52.344292,9.42046],[52.347092,9.42214],[52.34774,9.42256],[52.348728,9.4233],[52.349461,9.42388],[52.350231,9.42454],[52.351101,9.42534],[52.353039,9.42715],[52.357361,9.43114],[52.35881,9.43264],[52.359692,9.43366],[52.367809,9.44407],[52.369389,9.4463],[52.37072,9.44836],[52.370861,9.44859],[52.37278,9.45184],[52.37532,9.45624],[52.377548,9.4601],[52.38052,9.46524],[52.38113,9.46629],[52.381649,9.46712],[52.382561,9.46848],[52.383499,9.4698],[52.388901,9.4772],[52.39045,9.47932],[52.396099,9.48702],[52.39711,9.48859],[52.398029,9.49015],[52.401131,9.49559],[52.406521,9.50506],[52.407982,9.50763],[52.409161,9.50972],[52.410191,9.51151],[52.41164,9.51406],[52.413311,9.51703],[52.41428,9.51884],[52.415138,9.52054],[52.41576,9.52185],[52.416382,9.52326],[52.416969,9.52472],[52.417488,9.52615],[52.41803,9.52775],[52.41877,9.53015],[52.419331,9.53233],[52.419689,9.53391],[52.419991,9.53553],[52.420319,9.53729],[52.42057,9.53902],[52.42078,9.54093],[52.420971,9.54285],[52.421131,9.54533],[52.42131,9.54945],[52.421459,9.55652],[52.421551,9.55856],[52.42165,9.56019],[52.421909,9.56349],[52.422329,9.56859],[52.42276,9.57334],[52.42281,9.57401],[52.423309,9.58008],[52.423458,9.58243],[52.423489,9.58307],[52.423561,9.58555],[52.423592,9.5876],[52.42358,9.58984],[52.423519,9.59303],[52.423229,9.59739],[52.421131,9.61986],[52.42091,9.62265],[52.420811,9.62446],[52.420792,9.62634],[52.420811,9.62772],[52.420872,9.6294],[52.421051,9.63173],[52.421242,9.63346],[52.421619,9.63605],[52.422058,9.6385],[52.424,9.64852],[52.42527,9.6551],[52.42683,9.66314],[52.427429,9.66629],[52.4282,9.67028],[52.428421,9.67169],[52.428612,9.67311],[52.428921,9.67626],[52.429321,9.68156],[52.429611,9.68496],[52.430241,9.69297],[52.430389,9.69674],[52.43042,9.69946],[52.430401,9.70035],[52.430248,9.70318],[52.43,9.70612],[52.42923,9.71208],[52.429001,9.71376],[52.42823,9.72024],[52.427898,9.72294],[52.427872,9.72335],[52.427551,9.72654],[52.427441,9.72852],[52.427441,9.72884],[52.427391,9.73166],[52.427391,9.73378],[52.42738,9.74271],[52.42725,9.74974],[52.427189,9.75209],[52.427189,9.75226],[52.427071,9.75852],[52.427059,9.75878],[52.426979,9.76416],[52.426979,9.76718],[52.42709,9.7718],[52.427219,9.77332],[52.427471,9.77608],[52.42757,9.77697],[52.42802,9.78012],[52.42849,9.78298],[52.42894,9.78534],[52.4296,9.78852],[52.43013,9.7913],[52.430309,9.79236],[52.43084,9.79586],[52.431061,9.79878],[52.43108,9.80093],[52.43108,9.80136],[52.431061,9.80156],[52.431011,9.80331],[52.430851,9.80506],[52.43058,9.80699],[52.429859,9.81081],[52.42926,9.81314],[52.427879,9.81772],[52.42767,9.81826],[52.427589,9.81848],[52.42622,9.82272],[52.42561,9.82427],[52.425179,9.8253],[52.4244,9.82718],[52.42313,9.82991],[52.421791,9.83242],[52.421059,9.83371],[52.420341,9.83493],[52.419991,9.83549],[52.41695,9.84032],[52.41547,9.84266],[52.414028,9.84502],[52.41272,9.84724],[52.412521,9.84753],[52.412201,9.84809],[52.411758,9.84889],[52.410969,9.85049],[52.40963,9.8534],[52.40897,9.85474],[52.4067,9.85982],[52.406231,9.8608],[52.404419,9.8647],[52.402882,9.86814],[52.4021,9.87012],[52.40136,9.87221],[52.40065,9.87454],[52.40015,9.87635],[52.399601,9.87873],[52.39933,9.88],[52.399101,9.8813],[52.398849,9.88279],[52.39864,9.88436],[52.398048,9.88966],[52.39793,9.89076],[52.397449,9.89538],[52.39716,9.89822],[52.396938,9.90041],[52.39613,9.90822],[52.39547,9.91468],[52.39489,9.91989],[52.394291,9.92539],[52.392899,9.93625],[52.392502,9.93943],[52.391991,9.94348],[52.391129,9.95032],[52.390652,9.95501],[52.390388,9.95814],[52.389771,9.96834],[52.38966,9.97063],[52.38961,9.97158],[52.389488,9.97431],[52.38945,9.97521],[52.389271,9.97919],[52.389179,9.98179],[52.388851,9.98807],[52.388741,9.98972],[52.38866,9.99068],[52.38855,9.99183],[52.388371,9.99334],[52.38826,9.9942],[52.388031,9.99557],[52.38776,9.99715],[52.387428,9.99872],[52.38665,10.00213],[52.386589,10.00236],[52.384411,10.01166],[52.384232,10.01243],[52.383591,10.01513],[52.38287,10.01818],[52.38216,10.02108],[52.381931,10.02194],[52.380798,10.02608],[52.37854,10.03394],[52.37793,10.03613],[52.375851,10.0434],[52.36834,10.06986],[52.367668,10.07246],[52.367241,10.07433],[52.366859,10.07654],[52.366489,10.079],[52.366112,10.08264],[52.364349,10.10102],[52.363918,10.10537],[52.363731,10.10793],[52.363621,10.11056],[52.363522,10.11825],[52.363491,10.12034],[52.363461,10.12095],[52.3634,10.12439],[52.36322,10.12821],[52.362869,10.13312],[52.362389,10.13806],[52.361851,10.14326],[52.361752,10.14428],[52.36092,10.15225],[52.36026,10.15861],[52.3587,10.17429],[52.358459,10.17639],[52.35775,10.18056],[52.357601,10.18136],[52.35696,10.18402],[52.356331,10.18616],[52.355492,10.18883],[52.35437,10.19165],[52.34618,10.20908],[52.342449,10.21785],[52.341831,10.21931],[52.340672,10.22211],[52.340179,10.22335],[52.33963,10.2249],[52.339489,10.22534],[52.33881,10.22759],[52.33831,10.2295],[52.337898,10.23125],[52.33733,10.23424],[52.336891,10.23742],[52.336781,10.23822],[52.33654,10.24093],[52.336449,10.2429],[52.336418,10.24385],[52.336399,10.24622],[52.33654,10.25446],[52.33659,10.25766],[52.336559,10.2601],[52.33646,10.2636],[52.336189,10.26843],[52.335072,10.28774],[52.334919,10.29107],[52.334919,10.29154],[52.335011,10.29579],[52.33514,10.29783],[52.33543,10.30059],[52.33551,10.30138],[52.338169,10.32413],[52.339352,10.33431],[52.339642,10.33706],[52.339771,10.33882],[52.339809,10.33951],[52.339931,10.3423],[52.339939,10.34619],[52.339771,10.35151],[52.339378,10.36378],[52.339321,10.36578],[52.339298,10.36685],[52.339039,10.3733],[52.33876,10.37846],[52.338699,10.37918],[52.33749,10.39397],[52.33744,10.39459],[52.337231,10.39709],[52.337078,10.39883],[52.33704,10.39933],[52.33699,10.39991],[52.336658,10.40373],[52.336601,10.40446],[52.335541,10.41656],[52.33511,10.41984],[52.33482,10.42191],[52.33448,10.42399],[52.33408,10.42626],[52.333401,10.43028],[52.331501,10.44129],[52.330391,10.44793],[52.32967,10.4525],[52.32896,10.45634],[52.326759,10.46555],[52.32547,10.47095],[52.324322,10.4756],[52.321678,10.48679],[52.320992,10.48957],[52.320641,10.49099],[52.316238,10.50933],[52.315941,10.51061],[52.314949,10.51487],[52.314602,10.51663],[52.314301,10.51826],[52.31406,10.51997],[52.313622,10.52316],[52.31337,10.52554],[52.313339,10.5259],[52.313229,10.52723],[52.31316,10.52956],[52.313171,10.53276],[52.31321,10.53498],[52.313221,10.53566],[52.313061,10.55503],[52.313049,10.55618],[52.31303,10.55924],[52.31303,10.56007],[52.313,10.56157],[52.312969,10.5638],[52.31292,10.56636],[52.312801,10.57008],[52.312691,10.57225],[52.31237,10.57724],[52.312019,10.58152],[52.310211,10.60278],[52.310032,10.60504],[52.309978,10.60568],[52.309872,10.60751],[52.30978,10.60984],[52.3097,10.61282],[52.309689,10.61409],[52.3097,10.61489],[52.309761,10.61923],[52.309769,10.62277],[52.309761,10.62736],[52.30975,10.62812],[52.30975,10.62927],[52.3097,10.63306],[52.309689,10.63377],[52.309689,10.63433],[52.309471,10.65566],[52.30938,10.66094],[52.308651,10.68318],[52.308578,10.6847],[52.308189,10.6965],[52.30817,10.69703],[52.30814,10.6977],[52.307961,10.70307],[52.307949,10.70368],[52.307869,10.70846],[52.30788,10.7108],[52.307961,10.71448],[52.307968,10.71477],[52.30806,10.71921],[52.30817,10.7233],[52.3083,10.72591],[52.308521,10.72918],[52.309261,10.736],[52.31052,10.74826],[52.31287,10.76876],[52.313519,10.77534],[52.313702,10.77924],[52.313702,10.7817],[52.313629,10.78393],[52.312489,10.79746],[52.312439,10.79808],[52.312309,10.79964],[52.311661,10.80753],[52.31155,10.80886],[52.311489,10.80955],[52.311218,10.81283],[52.310982,10.81575],[52.310928,10.81642],[52.310619,10.82023],[52.310299,10.82408],[52.31007,10.82577],[52.309681,10.82813],[52.30938,10.82972],[52.308922,10.83178],[52.308781,10.8324],[52.308571,10.83322],[52.307831,10.83578],[52.30703,10.83832],[52.306911,10.83871],[52.30648,10.84012],[52.30463,10.84596],[52.29977,10.86152],[52.299469,10.8625],[52.29797,10.86634],[52.29623,10.87042],[52.29607,10.8708],[52.290569,10.88392],[52.290298,10.88454],[52.289761,10.88581],[52.287991,10.89006],[52.286442,10.89384],[52.28561,10.89616],[52.284981,10.89818],[52.28405,10.90174],[52.283741,10.90314],[52.283581,10.90391],[52.283199,10.90601],[52.283039,10.90711],[52.282848,10.90841],[52.2827,10.9098],[52.28249,10.91186],[52.282211,10.91447],[52.28194,10.91689],[52.281818,10.91823],[52.281689,10.91955],[52.281521,10.92115],[52.281342,10.92276],[52.281239,10.92347],[52.281101,10.92451],[52.280941,10.92543],[52.28067,10.92687],[52.280579,10.92729],[52.280411,10.92808],[52.280281,10.92867],[52.27998,10.92985],[52.279621,10.93119],[52.278999,10.93321],[52.278809,10.93376],[52.27845,10.93479],[52.27808,10.93571],[52.277599,10.93683],[52.274021,10.94491],[52.272881,10.94751],[52.272579,10.94815],[52.272388,10.94866],[52.271629,10.95055],[52.271149,10.95184],[52.270691,10.9532],[52.270409,10.95412],[52.269989,10.9559],[52.269711,10.95711],[52.269402,10.95878],[52.269051,10.96101],[52.26873,10.96379],[52.268589,10.96511],[52.268459,10.96648],[52.26825,10.96781],[52.268051,10.96897],[52.267792,10.97028],[52.26746,10.97173],[52.267109,10.97311],[52.266541,10.97495],[52.2659,10.97686],[52.26535,10.97857],[52.264729,10.98044],[52.264431,10.98125],[52.264069,10.98226],[52.263611,10.98342],[52.26334,10.98406],[52.26302,10.9848],[52.26265,10.98559],[52.262428,10.98599],[52.261951,10.98683],[52.261559,10.98751],[52.260738,10.98882],[52.26009,10.98974],[52.25935,10.99068],[52.258259,10.99194],[52.258091,10.99214],[52.25774,10.99256],[52.25737,10.99298],[52.256519,10.99397],[52.25563,10.99497],[52.254391,10.99625],[52.25322,10.99741],[52.25264,10.99793],[52.25235,10.99823],[52.251209,10.99934],[52.250229,11.00027],[52.250031,11.00046],[52.24955,11.00092],[52.247181,11.0032],[52.246609,11.00382],[52.246151,11.00434],[52.245621,11.00498],[52.24514,11.0056],[52.244751,11.00613],[52.244381,11.00663],[52.24419,11.0069],[52.243999,11.00721],[52.24379,11.00755],[52.24321,11.00858],[52.242661,11.00965],[52.242088,11.01079],[52.241951,11.01111],[52.24165,11.01174],[52.240669,11.01376],[52.24049,11.01413],[52.24007,11.01488],[52.239738,11.01546],[52.23951,11.01586],[52.239281,11.01623],[52.238449,11.01743],[52.237862,11.01826],[52.237492,11.01872],[52.23708,11.01926],[52.236061,11.02047],[52.235901,11.02068],[52.235519,11.02112],[52.23484,11.02197],[52.23436,11.02264],[52.233879,11.0233],[52.232819,11.02502],[52.23238,11.02578],[52.232151,11.02621],[52.2318,11.02692],[52.231319,11.02796],[52.23064,11.02948],[52.22974,11.03148],[52.226608,11.03863],[52.224251,11.04442],[52.222542,11.04881],[52.22213,11.04988],[52.221722,11.0509],[52.21994,11.05556],[52.219559,11.05661],[52.219021,11.05819],[52.218639,11.05949],[52.218262,11.06097],[52.217609,11.06406],[52.217312,11.06595],[52.21701,11.06904],[52.216759,11.07434],[52.216389,11.08081],[52.21616,11.08396],[52.21582,11.08679],[52.215549,11.08848],[52.215321,11.08966],[52.215,11.091],[52.21471,11.09206],[52.21439,11.09308],[52.214119,11.09393],[52.213581,11.09541],[52.213032,11.097],[52.212528,11.09842],[52.2122,11.09948],[52.211971,11.10029],[52.211639,11.10148],[52.21032,11.10647],[52.209942,11.10794],[52.209572,11.10945],[52.209259,11.11086],[52.209019,11.11196],[52.208809,11.11301],[52.20853,11.11437],[52.20821,11.11676],[52.208031,11.11851],[52.20726,11.1314],[52.207218,11.13201],[52.20718,11.1333],[52.20715,11.13446],[52.207142,11.13474],[52.207142,11.13663],[52.20723,11.13807],[52.207298,11.1391],[52.208012,11.14741],[52.20826,11.1505],[52.208382,11.15266],[52.208431,11.15428],[52.208389,11.15683],[52.20826,11.15952],[52.20808,11.16168],[52.207748,11.16434],[52.207439,11.16667],[52.207272,11.16756],[52.204609,11.17897],[52.204288,11.18041],[52.20369,11.18307],[52.20295,11.18697],[52.202518,11.19054],[52.202309,11.19309],[52.201889,11.20136],[52.201839,11.20206],[52.200691,11.22617],[52.200531,11.23064],[52.20031,11.23465],[52.20018,11.23625],[52.19997,11.23853],[52.199551,11.24218],[52.199379,11.24359],[52.198601,11.24932],[52.198441,11.2506],[52.196831,11.26289],[52.196758,11.26343],[52.19664,11.26425],[52.19611,11.2682],[52.195919,11.26956],[52.195831,11.27021],[52.192509,11.29526],[52.192451,11.29572],[52.191921,11.2998],[52.191681,11.30193],[52.191631,11.30242],[52.19038,11.31644],[52.188,11.34272],[52.18729,11.35063],[52.18716,11.35227],[52.187069,11.35391],[52.187012,11.35556],[52.186981,11.35735],[52.186951,11.35924],[52.186958,11.36334],[52.187,11.36713],[52.18713,11.38555],[52.18718,11.38968],[52.18718,11.38998],[52.187191,11.39058],[52.187191,11.39091],[52.18721,11.39275],[52.18779,11.41141],[52.187809,11.41185],[52.187962,11.41739],[52.18808,11.42094],[52.188099,11.42154],[52.18819,11.425],[52.18829,11.42803],[52.188339,11.43127],[52.18832,11.43313],[52.18821,11.43495],[52.188049,11.43668],[52.187771,11.43853],[52.18734,11.44089],[52.186981,11.44246],[52.186001,11.44599],[52.185928,11.44622],[52.185829,11.44653],[52.183041,11.45638],[52.181412,11.46197],[52.17691,11.47781],[52.176159,11.4802],[52.175781,11.48138],[52.175251,11.48278],[52.174389,11.48491],[52.173431,11.48724],[52.17202,11.49069],[52.168011,11.50037],[52.16666,11.50414],[52.166458,11.50475],[52.16629,11.50537],[52.16589,11.50676],[52.165611,11.50802],[52.165359,11.50931],[52.165161,11.51038],[52.16502,11.51134],[52.164791,11.51371],[52.1647,11.51587],[52.16468,11.5163],[52.16465,11.51743],[52.164669,11.5184],[52.164742,11.51996],[52.16489,11.52163],[52.165058,11.52326],[52.165119,11.52365],[52.165421,11.52569],[52.166439,11.53267],[52.166611,11.53392],[52.167339,11.53867],[52.167439,11.53937],[52.169441,11.55281],[52.16991,11.55575],[52.170231,11.55711],[52.170559,11.55839],[52.171291,11.56133],[52.17382,11.57087],[52.175751,11.57812],[52.178219,11.58746],[52.182308,11.603],[52.183929,11.60919],[52.185032,11.61315],[52.185822,11.61628],[52.186619,11.61919],[52.187531,11.62238],[52.188011,11.62375],[52.18858,11.62524],[52.18866,11.62546],[52.18959,11.62733],[52.190868,11.62959],[52.192478,11.63237],[52.199959,11.6454],[52.200359,11.64613],[52.20084,11.64695],[52.201038,11.64729],[52.20842,11.66016],[52.208679,11.66065],[52.209332,11.66179],[52.21109,11.66484],[52.21154,11.66565],[52.211788,11.66607],[52.213799,11.66959],[52.215851,11.67339],[52.216461,11.67478],[52.217049,11.67633],[52.217369,11.67731],[52.217579,11.67796],[52.217838,11.67877],[52.218311,11.68052],[52.21854,11.68151],[52.21909,11.6844],[52.219452,11.68751],[52.219749,11.69092],[52.220051,11.69427],[52.221161,11.70682],[52.22168,11.71211],[52.222061,11.71632],[52.223511,11.73166],[52.223629,11.73272],[52.223759,11.73362],[52.225361,11.74258],[52.22699,11.75169],[52.22805,11.75741],[52.228409,11.75924],[52.228741,11.76117],[52.229019,11.76374],[52.229149,11.76571],[52.229179,11.76778],[52.22897,11.77192],[52.227791,11.7904],[52.22768,11.79214],[52.2276,11.79329],[52.227291,11.79804],[52.226688,11.80733],[52.22665,11.80793],[52.226009,11.81791],[52.225689,11.82334],[52.225529,11.82563],[52.22541,11.82819],[52.22543,11.83002],[52.225471,11.83125],[52.225559,11.83267],[52.225651,11.83379],[52.227291,11.84773],[52.232201,11.88916],[52.23251,11.89181],[52.232639,11.89276],[52.232731,11.89358],[52.233051,11.89658],[52.23336,11.89995],[52.233601,11.90274],[52.233768,11.90531],[52.233879,11.90798],[52.234348,11.92429],[52.234779,11.94053],[52.235249,11.95714],[52.235409,11.96376],[52.2356,11.97119],[52.235748,11.97729],[52.23579,11.97894],[52.235771,11.98051],[52.235699,11.98249],[52.235432,11.98812],[52.235081,11.99699],[52.234341,12.01401],[52.233761,12.02773],[52.233421,12.03474],[52.233101,12.04213],[52.232632,12.05301],[52.232609,12.0542],[52.23262,12.05541],[52.23267,12.05675],[52.232841,12.0587],[52.23296,12.06002],[52.233101,12.06113],[52.233459,12.06384],[52.233681,12.06548],[52.233768,12.0661],[52.24308,12.13948],[52.2439,12.14593],[52.249649,12.19065],[52.252121,12.21038],[52.25235,12.21264],[52.252441,12.2143],[52.252491,12.21691],[52.252319,12.2199],[52.249069,12.25665],[52.248631,12.26174],[52.24828,12.2661],[52.24699,12.28226],[52.24678,12.28543],[52.246658,12.2885],[52.24675,12.29159],[52.246891,12.29349],[52.247169,12.29568],[52.24765,12.29831],[52.24847,12.30145],[52.248791,12.30246],[52.249241,12.30368],[52.2495,12.30437],[52.249821,12.30523],[52.253349,12.31351],[52.253639,12.31419],[52.26292,12.33628],[52.263882,12.33891],[52.264481,12.34107],[52.26495,12.34305],[52.265339,12.34523],[52.267719,12.36252],[52.277241,12.4319],[52.27755,12.43401],[52.278061,12.43658],[52.278561,12.43851],[52.279259,12.4407],[52.2799,12.44244],[52.280529,12.44386],[52.281189,12.44522],[52.281849,12.4464],[52.28727,12.45523],[52.289341,12.45825],[52.290829,12.46031],[52.292488,12.46235],[52.295609,12.46595],[52.299759,12.47067],[52.304459,12.47609],[52.30703,12.47905],[52.30975,12.48217],[52.312519,12.48525],[52.314991,12.48782],[52.318409,12.49088],[52.323139,12.49511],[52.326832,12.49837],[52.33028,12.50148],[52.333721,12.50458],[52.335201,12.50586],[52.335838,12.50645],[52.336571,12.50723],[52.337528,12.5084],[52.33836,12.50953],[52.339062,12.51066],[52.340118,12.51264],[52.340401,12.51326],[52.340809,12.51413],[52.341591,12.51603],[52.342892,12.51968],[52.344269,12.52359],[52.347919,12.53389],[52.348782,12.53666],[52.349419,12.53922],[52.349751,12.54055],[52.349819,12.5409],[52.350552,12.54517],[52.35088,12.54797],[52.351059,12.55027],[52.351181,12.55295],[52.351189,12.55519],[52.351158,12.55847],[52.35107,12.56422],[52.350922,12.57661],[52.350681,12.59304],[52.350632,12.59599],[52.35059,12.59717],[52.350498,12.5986],[52.35041,12.59981],[52.350182,12.60171],[52.349911,12.60367],[52.349659,12.60507],[52.34938,12.60644],[52.348999,12.60803],[52.348122,12.61133],[52.344818,12.62296],[52.34457,12.62384],[52.344391,12.62446],[52.34346,12.62779],[52.342911,12.62973],[52.34272,12.63038],[52.33942,12.64209],[52.339191,12.64297],[52.338009,12.64715],[52.33754,12.64889],[52.33662,12.65224],[52.33625,12.6537],[52.335899,12.65536],[52.33567,12.65673],[52.335419,12.65854],[52.3353,12.65974],[52.335209,12.66093],[52.335152,12.66218],[52.335121,12.66309],[52.335129,12.66403],[52.335171,12.6655],[52.33527,12.66721],[52.335411,12.66883],[52.336739,12.68137],[52.336811,12.68207],[52.33744,12.68802],[52.337521,12.68873],[52.338161,12.69472],[52.33852,12.6982],[52.338631,12.69936],[52.338799,12.70087],[52.339081,12.70356],[52.339729,12.70973],[52.339951,12.71174],[52.340092,12.71322],[52.34016,12.7143],[52.34021,12.71555],[52.340221,12.71697],[52.340179,12.71834],[52.340111,12.71968],[52.34005,12.72069],[52.34,12.72143],[52.339859,12.72375],[52.33979,12.72533],[52.339771,12.72611],[52.339729,12.72804],[52.339642,12.73175],[52.339588,12.73409],[52.339611,12.73499],[52.339661,12.73628],[52.339729,12.73744],[52.340691,12.75166],[52.341099,12.7577],[52.341141,12.75848],[52.341209,12.75966],[52.34127,12.76134],[52.341259,12.76291],[52.341171,12.76464],[52.341049,12.76608],[52.340149,12.7758],[52.339111,12.78689],[52.338871,12.78991],[52.338409,12.79716],[52.338299,12.79892],[52.338009,12.80411],[52.33791,12.80584],[52.33783,12.80681],[52.337711,12.80768],[52.337509,12.80871],[52.33728,12.8097],[52.33696,12.8107],[52.33646,12.81194],[52.336109,12.81268],[52.33569,12.81338],[52.33519,12.81405],[52.33503,12.81426],[52.334839,12.81447],[52.334141,12.81513],[52.333599,12.81561],[52.332981,12.81612],[52.332359,12.81673],[52.331921,12.81723],[52.331402,12.81794],[52.330929,12.81869],[52.330479,12.81961],[52.33017,12.8204],[52.32988,12.82124],[52.328949,12.82439],[52.327759,12.82837],[52.324871,12.83843],[52.322739,12.84587],[52.320759,12.85271],[52.320202,12.85459],[52.319859,12.85564],[52.31958,12.85649],[52.31926,12.85738],[52.318802,12.85852],[52.318409,12.85941],[52.317501,12.8613],[52.31609,12.86413],[52.313278,12.86984],[52.31123,12.874],[52.31044,12.87558],[52.310322,12.87582],[52.309509,12.87753],[52.306961,12.8826],[52.305679,12.88513],[52.298168,12.90026],[52.297329,12.90199],[52.29649,12.90364],[52.295471,12.90573],[52.292488,12.9117],[52.291592,12.91353],[52.291409,12.91394],[52.291069,12.91483],[52.29092,12.9154],[52.290779,12.91593],[52.29063,12.91674],[52.29052,12.91769],[52.290482,12.91831],[52.290451,12.91879],[52.290451,12.91924],[52.290482,12.91992],[52.290581,12.92099],[52.290749,12.92183],[52.29097,12.92274],[52.291271,12.92371],[52.291809,12.92508],[52.29211,12.92599],[52.292511,12.92743],[52.292961,12.92949],[52.298199,12.95228],[52.299309,12.95707],[52.301849,12.96836],[52.30249,12.97116],[52.302849,12.97277],[52.30302,12.97345],[52.303169,12.9741],[52.303341,12.97503],[52.303471,12.97595],[52.303539,12.97658],[52.3036,12.97733],[52.303638,12.97817],[52.303379,13.00804],[52.303349,13.00964],[52.303322,13.01115],[52.303261,13.01224],[52.303169,13.01321],[52.30304,13.01414],[52.302879,13.01503],[52.30267,13.01593],[52.30154,13.01991],[52.30014,13.02485],[52.299999,13.02532],[52.299839,13.02589],[52.29945,13.0273],[52.299179,13.02828],[52.298981,13.029],[52.298851,13.02948],[52.298691,13.03007],[52.298599,13.03051],[52.298489,13.031],[52.298409,13.0315],[52.298351,13.03191],[52.298302,13.03235],[52.29826,13.03275],[52.298229,13.03316],[52.298222,13.03357],[52.29821,13.03402],[52.29821,13.03448],[52.29821,13.03477],[52.298229,13.03535],[52.298248,13.03579],[52.298309,13.03639],[52.29837,13.03689],[52.29847,13.0375],[52.29858,13.03805],[52.298691,13.0386],[52.298889,13.0393],[52.299019,13.03977],[52.29924,13.04038],[52.30006,13.04263],[52.300331,13.04338],[52.30048,13.04386],[52.300621,13.04441],[52.300739,13.04491],[52.300819,13.04535],[52.300911,13.04586],[52.30098,13.04634],[52.301041,13.04686],[52.30109,13.04735],[52.301121,13.04784],[52.30114,13.04834],[52.30114,13.04896],[52.300999,13.05311],[52.300701,13.06163],[52.300671,13.06223],[52.300499,13.06709],[52.300159,13.07772],[52.30011,13.07952],[52.300049,13.08123],[52.30003,13.08219],[52.30006,13.08293],[52.300091,13.08362],[52.300129,13.08421],[52.300179,13.08472],[52.300228,13.0852],[52.300331,13.08582],[52.300541,13.08696],[52.30196,13.09434],[52.302139,13.09526],[52.302261,13.09585],[52.302559,13.09734],[52.30267,13.09799],[52.30275,13.09857],[52.30283,13.09933],[52.30286,13.09979],[52.302898,13.10039],[52.302921,13.10091],[52.302929,13.10139],[52.302921,13.10196],[52.302879,13.10399],[52.302631,13.11285],[52.30257,13.11635],[52.30254,13.11712],[52.302391,13.12387],[52.302311,13.12553],[52.301029,13.14169],[52.300968,13.14249],[52.30085,13.14398],[52.300831,13.14447],[52.300812,13.14488],[52.300812,13.14539],[52.3008,13.14592],[52.30085,13.15346],[52.300819,13.15558],[52.3008,13.15612],[52.300781,13.15662],[52.300739,13.15714],[52.300209,13.16418],[52.299351,13.17524],[52.298931,13.18064],[52.29892,13.18097],[52.298908,13.18142],[52.298908,13.1821],[52.29892,13.18257],[52.298931,13.18301],[52.298962,13.18349],[52.299,13.18391],[52.299042,13.18431],[52.299091,13.18475],[52.299149,13.18519],[52.299221,13.18569],[52.299301,13.18608],[52.29937,13.18646],[52.299431,13.18678],[52.299561,13.18732],[52.30003,13.18925],[52.30019,13.18995],[52.30151,13.1953],[52.301579,13.19566],[52.30167,13.19612],[52.301731,13.19652],[52.3018,13.19693],[52.301849,13.1973],[52.301899,13.19773],[52.301929,13.19806],[52.30196,13.19841],[52.301979,13.19887],[52.30201,13.19935],[52.302021,13.19977],[52.302021,13.20011],[52.30201,13.20053],[52.30201,13.20089],[52.301998,13.20135],[52.301891,13.20437],[52.301739,13.20819],[52.30159,13.21251],[52.30143,13.21658],[52.301399,13.21761],[52.30101,13.22814],[52.300629,13.23876],[52.300362,13.24577],[52.300339,13.24618],[52.300331,13.24667],[52.30032,13.24713],[52.30032,13.24761],[52.30032,13.24802],[52.300331,13.24849],[52.30035,13.24896],[52.300369,13.24944],[52.300419,13.24996],[52.300461,13.25048],[52.300529,13.25102],[52.300598,13.25154],[52.300701,13.25207],[52.300812,13.25259],[52.300919,13.25312],[52.301041,13.2536],[52.30117,13.25409],[52.301331,13.25467],[52.302052,13.25682],[52.303631,13.26149],[52.306171,13.26909],[52.306549,13.27018],[52.307129,13.27192],[52.307289,13.27238],[52.30743,13.27285],[52.307571,13.27335],[52.307701,13.27383],[52.307819,13.2743],[52.307941,13.27481],[52.308048,13.27532],[52.30814,13.27581],[52.308239,13.27632],[52.308319,13.2768],[52.308392,13.27732],[52.308449,13.27784],[52.30851,13.27835],[52.308559,13.27889],[52.30859,13.27942],[52.308601,13.27994],[52.308609,13.28048],[52.30862,13.281],[52.308601,13.28153],[52.308571,13.28206],[52.308552,13.28255],[52.308498,13.28311],[52.30801,13.28764],[52.30764,13.2907],[52.307468,13.2923],[52.30743,13.29283],[52.307388,13.29332],[52.307369,13.29385],[52.30735,13.29491],[52.307259,13.2995],[52.307259,13.29988],[52.30722,13.30167],[52.307178,13.30244],[52.306789,13.30749],[52.30616,13.31553],[52.30563,13.32229],[52.305561,13.32336],[52.305519,13.32442],[52.3055,13.32547],[52.3055,13.32656],[52.305531,13.3276],[52.30558,13.32869],[52.30566,13.32976],[52.305771,13.33087],[52.305901,13.33203],[52.305969,13.33278],[52.306438,13.33712],[52.30653,13.33803],[52.307461,13.3466],[52.307571,13.34768],[52.307659,13.34873],[52.307709,13.34979],[52.307739,13.35073],[52.307751,13.35086],[52.307758,13.35191],[52.30769,13.36154],[52.30769,13.36237],[52.30761,13.37333],[52.30759,13.37434],[52.307549,13.37523],[52.307499,13.37612],[52.30743,13.37713],[52.306961,13.38394],[52.3069,13.38485],[52.306709,13.38766],[52.306549,13.38997],[52.30653,13.39038],[52.306259,13.39469],[52.30616,13.39737],[52.30603,13.40509],[52.305882,13.4151],[52.305882,13.41575],[52.305851,13.41721],[52.30584,13.41831],[52.305801,13.42242],[52.305828,13.42609],[52.305851,13.42757],[52.305931,13.43275],[52.30603,13.43915],[52.30608,13.44054],[52.306141,13.44131],[52.30616,13.4416],[52.306229,13.44238],[52.30629,13.4429],[52.306641,13.44551],[52.306839,13.4466],[52.307899,13.45187],[52.308128,13.45298],[52.30838,13.45421],[52.308769,13.45611],[52.30912,13.45786],[52.309681,13.46055],[52.309719,13.46078],[52.310341,13.4639],[52.310459,13.4645],[52.311951,13.47177],[52.312611,13.47496],[52.312679,13.47535],[52.314789,13.48567],[52.315231,13.48783],[52.316971,13.49645],[52.317291,13.49799],[52.317951,13.50123],[52.3186,13.50442],[52.31881,13.50564],[52.318932,13.50642],[52.319031,13.50718],[52.319141,13.50822],[52.31921,13.50916],[52.31926,13.51001],[52.319302,13.51074],[52.319309,13.51155],[52.319321,13.51231],[52.319309,13.51293],[52.31929,13.51368],[52.319229,13.51505],[52.318851,13.52142],[52.318569,13.52585],[52.318359,13.52936],[52.31831,13.53107],[52.318279,13.53268],[52.31834,13.53601],[52.318371,13.53704],[52.318588,13.54471],[52.318771,13.55087],[52.31889,13.55457],[52.31889,13.55478],[52.318951,13.55658],[52.31897,13.55785],[52.319111,13.56125],[52.319141,13.56241],[52.319351,13.56982],[52.319481,13.57375],[52.319611,13.57905],[52.319679,13.58139],[52.319679,13.58179],[52.319672,13.58228],[52.319649,13.58274],[52.31963,13.58324],[52.319592,13.58371],[52.31953,13.58429],[52.319469,13.58477],[52.319401,13.5853],[52.319302,13.58579],[52.319199,13.5863],[52.319111,13.58674],[52.318981,13.58716],[52.318878,13.58758],[52.318771,13.588],[52.3186,13.58854],[52.318409,13.58908],[52.314541,13.59834],[52.313011,13.60187],[52.312778,13.60244],[52.31237,13.60355],[52.312092,13.60442],[52.311699,13.60583],[52.311562,13.60662],[52.31144,13.60741],[52.31134,13.60828],[52.311218,13.60965],[52.311131,13.61102],[52.310959,13.61394],[52.310749,13.61685],[52.310581,13.61942],[52.31041,13.62219],[52.310219,13.62503],[52.310089,13.62699],[52.31007,13.6275],[52.31007,13.62845],[52.31007,13.62939],[52.310169,13.63121],[52.310249,13.63253],[52.31028,13.63349],[52.310299,13.63427],[52.31039,13.63698],[52.31065,13.64389],[52.310699,13.64603],[52.310829,13.64817],[52.31089,13.64904],[52.311039,13.65133],[52.311359,13.65437],[52.311451,13.65497],[52.311939,13.65849],[52.312649,13.66256],[52.312679,13.6627],[52.312778,13.66331],[52.31284,13.66363],[52.313709,13.66821],[52.31422,13.67078],[52.316711,13.68074],[52.318481,13.68853],[52.32093,13.69869],[52.323811,13.71061],[52.324039,13.71157],[52.324181,13.71243],[52.324329,13.71357],[52.324421,13.7144],[52.324478,13.71538],[52.324501,13.7164],[52.32439,13.72013],[52.32423,13.72539],[52.324211,13.72651],[52.324032,13.73115],[52.323959,13.73364],[52.323719,13.73806],[52.323471,13.74205],[52.32333,13.74668],[52.32317,13.75164],[52.323151,13.75306],[52.323158,13.7541],[52.3232,13.75505],[52.323231,13.75592],[52.323261,13.7567],[52.32328,13.75751],[52.32328,13.75826],[52.323261,13.75934],[52.323231,13.76009],[52.32309,13.76171],[52.323009,13.76277],[52.32291,13.76362],[52.322769,13.76464],[52.322479,13.76632],[52.321991,13.76899],[52.321259,13.77266],[52.320969,13.7741],[52.319851,13.77939],[52.31921,13.78262],[52.318939,13.78396],[52.318501,13.78613],[52.317551,13.79078],[52.317509,13.79102],[52.317341,13.79181],[52.317108,13.7929],[52.31657,13.79519],[52.315449,13.79977],[52.315079,13.80129],[52.313332,13.80844],[52.31131,13.81651],[52.310841,13.81912],[52.310638,13.82042],[52.31049,13.8217],[52.310379,13.82292],[52.310299,13.8241],[52.310242,13.82523],[52.310211,13.82659],[52.310211,13.82763],[52.31028,13.82919],[52.31039,13.83102],[52.310612,13.83456],[52.310829,13.83808],[52.311031,13.84117],[52.312199,13.85973],[52.312481,13.86492],[52.31292,13.8716],[52.313129,13.87394],[52.3134,13.87599],[52.31377,13.87848],[52.315659,13.8905],[52.316002,13.89283],[52.316109,13.89382],[52.316139,13.89395],[52.316231,13.89513],[52.316341,13.89711],[52.31636,13.89782],[52.316368,13.89843],[52.316368,13.89941],[52.316368,13.89974],[52.316319,13.9008],[52.316299,13.90126],[52.31628,13.90146],[52.316231,13.90217],[52.3162,13.90265],[52.31612,13.9035],[52.316051,13.90423],[52.315929,13.90506],[52.315769,13.90622],[52.31554,13.90753],[52.315449,13.90808],[52.31525,13.90935],[52.314678,13.91243],[52.313839,13.91717],[52.313591,13.91856],[52.313251,13.9206],[52.313,13.92272],[52.312859,13.92457],[52.312672,13.92828],[52.312469,13.93198],[52.31221,13.93685],[52.31189,13.94362],[52.311821,13.94501],[52.311699,13.94711],[52.3116,13.94925],[52.311531,13.95186],[52.311501,13.95388],[52.31152,13.95569],[52.31155,13.95647],[52.31155,13.95723],[52.31155,13.95759],[52.3116,13.95848],[52.311649,13.95939],[52.31171,13.96051],[52.31189,13.9633],[52.311958,13.96403],[52.312031,13.96476],[52.312111,13.96553],[52.312309,13.9676],[52.312679,13.97042],[52.313519,13.97695],[52.31419,13.98221],[52.315079,13.98901],[52.31559,13.99114],[52.316631,13.99535],[52.320641,14.01003],[52.321388,14.01278],[52.32254,14.01699],[52.327091,14.03302],[52.327888,14.03549],[52.32877,14.03817],[52.329361,14.03994],[52.329639,14.04085],[52.329868,14.04185],[52.330509,14.0449],[52.331181,14.04833],[52.332371,14.05431],[52.333389,14.0594],[52.33419,14.0635],[52.334278,14.06416],[52.334389,14.06499],[52.33445,14.06608],[52.33448,14.06779],[52.334492,14.06882],[52.334499,14.06961],[52.33453,14.0718],[52.33461,14.07611],[52.334621,14.07673],[52.334629,14.07948],[52.334641,14.0799],[52.33469,14.08319],[52.334709,14.08396],[52.33493,14.09404],[52.335129,14.10164],[52.335171,14.10379],[52.3353,14.10977],[52.33532,14.11047],[52.335442,14.1153],[52.335579,14.12059],[52.335781,14.12908],[52.335941,14.13594],[52.336109,14.14278],[52.336159,14.14419],[52.336269,14.14563],[52.336399,14.14698],[52.33659,14.14847],[52.336849,14.15005],[52.33704,14.15106],[52.337559,14.15323],[52.33905,14.15899],[52.33989,14.16224],[52.340832,14.16591],[52.342758,14.17332],[52.343319,14.17564],[52.343731,14.17809],[52.34388,14.18072],[52.343811,14.18341],[52.34338,14.18688],[52.342838,14.18988],[52.341709,14.19427],[52.340618,14.19713],[52.338531,14.20352],[52.337429,14.20914],[52.337021,14.2144],[52.336578,14.22596],[52.335991,14.24164],[52.33585,14.24464],[52.335499,14.24766],[52.334919,14.2509],[52.334171,14.25369],[52.333778,14.25489],[52.333649,14.25527],[52.332611,14.25821],[52.330059,14.2653],[52.328659,14.26944],[52.328289,14.27081],[52.32753,14.27394],[52.327179,14.27573],[52.326401,14.27954],[52.325371,14.28448],[52.324718,14.2877],[52.324291,14.29105],[52.32399,14.29796],[52.323471,14.31189],[52.32296,14.32586],[52.322208,14.34336],[52.322159,14.3474],[52.322029,14.35058],[52.321739,14.359],[52.321239,14.37253],[52.32095,14.37974],[52.320938,14.38024],[52.320881,14.38183],[52.32056,14.39143],[52.32029,14.39804],[52.32019,14.40253],[52.320221,14.41164],[52.32032,14.42128],[52.3204,14.43098],[52.320591,14.44889],[52.32069,14.45717],[52.320679,14.46126],[52.320641,14.46375],[52.320591,14.46598],[52.32053,14.46934],[52.320431,14.47422],[52.320419,14.475],[52.320358,14.47841],[52.32019,14.48646],[52.320011,14.49741],[52.31992,14.50324],[52.319832,14.50629],[52.319721,14.50929],[52.319519,14.51284],[52.319302,14.51651],[52.319069,14.51992],[52.318989,14.5207],[52.31889,14.52167],[52.318729,14.52265],[52.318451,14.52381],[52.318111,14.52488],[52.317699,14.52601],[52.316898,14.52836],[52.316601,14.52915],[52.316311,14.52992],[52.31617,14.53036],[52.315948,14.53115],[52.315681,14.53209],[52.315552,14.53266],[52.315231,14.53412],[52.314899,14.53588],[52.31472,14.53705],[52.314548,14.53846],[52.314442,14.53961],[52.31435,14.54102],[52.314289,14.54354],[52.31432,14.54571],[52.314381,14.54728],[52.314388,14.54786],[52.31451,14.55143],[52.314579,14.55382],[52.31461,14.55563],[52.314621,14.55709],[52.31459,14.56008],[52.314548,14.56303],[52.314499,14.56659],[52.314579,14.56822],[52.314789,14.57063],[52.314919,14.57244],[52.315189,14.57603],[52.31538,14.57823],[52.31575,14.582],[52.316051,14.5845],[52.316212,14.58597],[52.316299,14.58661],[52.316368,14.58724],[52.316441,14.58844],[52.316521,14.58954],[52.316681,14.59023],[52.316879,14.59181],[52.31699,14.59264],[52.31889,14.59981],[52.320629,14.60601],[52.322411,14.61267],[52.323078,14.6152],[52.32394,14.61827],[52.32452,14.62057],[52.324692,14.62123],[52.325001,14.62245],[52.325611,14.62534],[52.32589,14.6274],[52.326092,14.6291],[52.326199,14.63064],[52.326248,14.63312],[52.32616,14.63536],[52.325989,14.63746],[52.325851,14.63898],[52.325691,14.64077],[52.325489,14.64297],[52.325272,14.64536],[52.324631,14.65187],[52.324131,14.65751],[52.323959,14.66148],[52.32394,14.66456],[52.324268,14.66852],[52.324959,14.67386],[52.325951,14.68193],[52.32679,14.68798],[52.32782,14.69577],[52.328308,14.69948],[52.3284,14.69984],[52.3288,14.70276],[52.32935,14.70716],[52.329762,14.71018],[52.33012,14.71311],[52.33057,14.71611],[52.330719,14.71743],[52.33099,14.71987],[52.331348,14.72298],[52.331509,14.72419],[52.332329,14.73033],[52.33297,14.7351],[52.333672,14.73998],[52.334278,14.74597],[52.334839,14.74961],[52.335121,14.75285],[52.33532,14.75599],[52.335251,14.76015],[52.335251,14.76259],[52.335251,14.76802],[52.335281,14.77738],[52.335312,14.78783],[52.335312,14.79524],[52.335312,14.8001],[52.335121,14.80287],[52.33474,14.80595],[52.334,14.80992],[52.3326,14.81719],[52.331188,14.82469],[52.33181,14.82495],[52.332211,14.82512],[52.336479,14.82671],[52.33667,14.82695],[52.3367,14.82708],[52.336899,14.82746],[52.337959,14.83174],[52.33971,14.84149],[52.339722,14.8423],[52.339249,14.84258],[52.337952,14.84265],[52.33688,14.84286],[52.33585,14.8435],[52.334579,14.84484],[52.332611,14.84689],[52.33099,14.84875],[52.329708,14.84906],[52.329891,14.85048],[52.32983,14.85069],[52.329731,14.85084],[52.329269,14.85094],[52.32988,14.85503],[52.331451,14.8649],[52.332531,14.87174],[52.333229,14.87593],[52.333488,14.87793],[52.333511,14.87955],[52.333382,14.88108],[52.33308,14.8827],[52.33213,14.88645],[52.329849,14.89468],[52.327461,14.90341],[52.32626,14.90796],[52.325859,14.90951],[52.324551,14.91448],[52.323891,14.91709],[52.32333,14.92519],[52.322842,14.93262],[52.32272,14.93431],[52.32272,14.93545],[52.322701,14.93746],[52.322601,14.94129],[52.322571,14.94231],[52.322529,14.94388],[52.322491,14.94485],[52.3223,14.94668],[52.322048,14.94901],[52.322102,14.95146],[52.32214,14.95324],[52.323261,14.96119],[52.323551,14.96432],[52.32428,14.96949],[52.324532,14.97133],[52.325459,14.97816],[52.325851,14.98161],[52.326069,14.98478],[52.326172,14.9859],[52.326431,14.99044],[52.32671,14.9952],[52.327068,15.00165],[52.327141,15.00297],[52.32748,15.00926],[52.327492,15.01057],[52.3274,15.01196],[52.327202,15.0133],[52.326889,15.01427],[52.32626,15.01541],[52.326038,15.01612],[52.325581,15.01866],[52.325211,15.01991],[52.323639,15.02362],[52.321442,15.02881],[52.319618,15.03303],[52.31826,15.03632],[52.317959,15.03744],[52.317749,15.03856],[52.317539,15.03964],[52.317451,15.04015],[52.317299,15.04102],[52.3172,15.04158],[52.31712,15.04197],[52.31575,15.05026],[52.314671,15.05675],[52.31459,15.05757],[52.314362,15.0613],[52.314308,15.06239],[52.314129,15.06768],[52.314129,15.06804],[52.314018,15.07221],[52.314011,15.07287],[52.314011,15.07321],[52.31406,15.07634],[52.31406,15.07645],[52.31403,15.07699],[52.313969,15.07741],[52.313759,15.07815],[52.31358,15.07869],[52.313381,15.07915],[52.313061,15.07986],[52.31271,15.08079],[52.312401,15.08214],[52.312351,15.08315],[52.312359,15.0838],[52.3125,15.0857],[52.312778,15.08879],[52.313099,15.09145],[52.313129,15.09244],[52.313122,15.09307],[52.312889,15.09459],[52.312592,15.09667],[52.31163,15.10237],[52.311291,15.10456],[52.311131,15.10562],[52.3102,15.11167],[52.309429,15.1158],[52.309212,15.11783],[52.307449,15.12917],[52.305851,15.13853],[52.305531,15.14046],[52.305679,15.1434],[52.30682,15.15571],[52.307621,15.16481],[52.30814,15.16976],[52.308449,15.17354],[52.308491,15.17476],[52.30835,15.17634],[52.307598,15.18076],[52.30743,15.18192],[52.30706,15.18441],[52.306221,15.19006],[52.305679,15.19367],[52.305141,15.19727],[52.304531,15.20115],[52.304321,15.20249],[52.30415,15.20363],[52.304161,15.20518],[52.304138,15.2125],[52.304081,15.21744],[52.30415,15.22173],[52.304062,15.22459],[52.30323,15.22903],[52.302021,15.23598],[52.300991,15.24142],[52.300159,15.24576],[52.299431,15.24963],[52.299141,15.25119],[52.298908,15.25245],[52.298779,15.25318],[52.297981,15.25758],[52.296871,15.26387],[52.296539,15.26546],[52.296162,15.26735],[52.29599,15.26859],[52.296009,15.27042],[52.296291,15.27157],[52.296638,15.27262],[52.297279,15.27445],[52.29789,15.27607],[52.29921,15.27976],[52.299759,15.28133],[52.300079,15.28318],[52.300201,15.28427],[52.300282,15.28585],[52.30032,15.28881],[52.30032,15.29367],[52.300098,15.30026],[52.29995,15.30136],[52.29969,15.30273],[52.29908,15.30553],[52.296902,15.31165],[52.29541,15.31585],[52.293541,15.32154],[52.29134,15.32788],[52.290749,15.32981],[52.290359,15.33222],[52.290199,15.33807],[52.28923,15.34195],[52.286598,15.34702],[52.282909,15.35303],[52.28138,15.35526],[52.28064,15.35622],[52.279541,15.35927],[52.278992,15.36026],[52.278389,15.36093],[52.277431,15.36179],[52.276669,15.36254],[52.276081,15.36362],[52.274551,15.36875],[52.272739,15.37466],[52.2714,15.37907],[52.270931,15.38053],[52.270679,15.38137],[52.269402,15.38597],[52.268921,15.38743],[52.26889,15.38753],[52.268349,15.38872],[52.267929,15.38954],[52.266949,15.39075],[52.265129,15.39281],[52.263699,15.39487],[52.262249,15.39781],[52.26144,15.39949],[52.260139,15.4022],[52.258701,15.40485],[52.257919,15.40721],[52.257301,15.41013],[52.257069,15.41427],[52.25671,15.41949],[52.256142,15.42734],[52.255051,15.44218],[52.254669,15.44881],[52.253799,15.45979],[52.253811,15.46035],[52.253769,15.4612],[52.25412,15.46642],[52.254219,15.46799],[52.254169,15.469],[52.254028,15.47212],[52.25436,15.47424],[52.254292,15.47588],[52.25423,15.47617],[52.253578,15.47933],[52.25301,15.48252],[52.25317,15.4857],[52.253681,15.488],[52.255531,15.49359],[52.256592,15.49689],[52.25745,15.49939],[52.258282,15.50201],[52.25943,15.50561],[52.259819,15.50713],[52.260269,15.51073],[52.26046,15.51246],[52.26078,15.51575],[52.26115,15.5193],[52.261292,15.52025],[52.261452,15.52155],[52.262089,15.5273],[52.262291,15.52977],[52.262249,15.53163],[52.26223,15.53312],[52.26202,15.5332],[52.261929,15.53345],[52.261971,15.53376],[52.26215,15.53395],[52.261848,15.5347],[52.260761,15.53751],[52.260719,15.53759],[52.260151,15.53888],[52.256161,15.5487],[52.255932,15.54923],[52.255569,15.5501],[52.252998,15.55644],[52.252178,15.55843],[52.251789,15.56074],[52.2519,15.56195],[52.25211,15.56461],[52.253609,15.57056],[52.2556,15.57819],[52.256821,15.58265],[52.256802,15.5835],[52.257481,15.5857],[52.25787,15.58713],[52.25988,15.59026],[52.26302,15.5945],[52.266281,15.5992],[52.268742,15.60275],[52.271172,15.6061],[52.272129,15.60787],[52.272579,15.60917],[52.273281,15.61221],[52.274811,15.61984],[52.275711,15.62407],[52.277569,15.63269],[52.278252,15.63792],[52.27877,15.64118],[52.279442,15.64462],[52.280972,15.64746],[52.283218,15.64905],[52.285912,15.65071],[52.287239,15.65119],[52.289459,15.6513],[52.293442,15.6511],[52.295109,15.65142],[52.297279,15.65219],[52.299271,15.65359],[52.30196,15.65767],[52.303341,15.65965],[52.305401,15.66148],[52.308849,15.66356],[52.31028,15.66424],[52.311329,15.66496],[52.312618,15.66619],[52.31633,15.66969],[52.31855,15.67166],[52.319462,15.67272],[52.320271,15.67374],[52.320709,15.67491],[52.321201,15.67633],[52.32132,15.67753],[52.321419,15.67846],[52.321331,15.68024],[52.32106,15.68229],[52.32103,15.68387],[52.321301,15.68584],[52.321831,15.68795],[52.322472,15.69054],[52.322781,15.69181],[52.32394,15.69626],[52.3269,15.70543],[52.32933,15.71288],[52.33041,15.71597],[52.33242,15.72132],[52.332859,15.72245],[52.332901,15.72256],[52.332939,15.72267],[52.333858,15.72466],[52.33744,15.73182],[52.33881,15.73474],[52.33939,15.73652],[52.339828,15.73898],[52.341141,15.74844],[52.341801,15.75126],[52.342041,15.75225],[52.342319,15.75323],[52.342739,15.75468],[52.34322,15.75633],[52.34446,15.76096],[52.344971,15.76281],[52.345161,15.7647],[52.34523,15.76731],[52.344761,15.77811],[52.344379,15.78276],[52.34428,15.78559],[52.344429,15.78784],[52.344711,15.78962],[52.3451,15.79201],[52.345829,15.7957],[52.346882,15.7995],[52.347641,15.8022],[52.3503,15.81156],[52.3531,15.82158],[52.353291,15.82229],[52.353619,15.82347],[52.356079,15.83324],[52.35796,15.84103],[52.358109,15.84228],[52.35828,15.84537],[52.358429,15.84972],[52.35873,15.85273],[52.358829,15.85334],[52.358891,15.85361],[52.359669,15.85557],[52.36055,15.85676],[52.36179,15.85789],[52.36377,15.8595],[52.36541,15.86088],[52.366211,15.86172],[52.36718,15.86298],[52.36763,15.86378],[52.36797,15.86447],[52.368431,15.86563],[52.368519,15.86592],[52.36887,15.86689],[52.370312,15.87259],[52.37077,15.87381],[52.37096,15.87428],[52.37191,15.87661],[52.372532,15.87872],[52.372829,15.88037],[52.37294,15.88168],[52.372929,15.88325],[52.372398,15.88678],[52.37236,15.88699],[52.371841,15.89046],[52.371609,15.89246],[52.371269,15.89542],[52.371078,15.89704],[52.371719,15.903],[52.37233,15.9084],[52.372551,15.90929],[52.373058,15.91025],[52.373959,15.91201],[52.37439,15.9134],[52.37508,15.91632],[52.375851,15.91963],[52.376381,15.92256],[52.377209,15.92803],[52.37722,15.92961],[52.376469,15.93341],[52.37648,15.93775],[52.3764,15.93848],[52.375511,15.94449],[52.375252,15.94754],[52.375278,15.94982],[52.375629,15.95385],[52.375751,15.95709],[52.375839,15.95888],[52.375851,15.9591],[52.375912,15.96079],[52.37608,15.96312],[52.37645,15.96516],[52.377838,15.97023],[52.379761,15.97643],[52.379902,15.97828],[52.37991,15.97955],[52.379452,15.98388],[52.380009,15.99173],[52.380421,15.99552],[52.380459,15.99832],[52.38055,16.001459],[52.380169,16.00466],[52.379589,16.007641],[52.378349,16.01523],[52.376911,16.02301],[52.376369,16.02775],[52.376301,16.02907],[52.376301,16.03022],[52.376331,16.032221],[52.376431,16.035379],[52.376789,16.04607],[52.377239,16.057249],[52.377392,16.06572],[52.377522,16.07852],[52.37772,16.09374],[52.37756,16.09358],[52.377369,16.093679],[52.377289,16.09392],[52.3773,16.09408],[52.375912,16.09433],[52.374691,16.094549],[52.3713,16.09503],[52.37112,16.09507],[52.366039,16.096029],[52.36264,16.096661],[52.36253,16.097219],[52.362289,16.09865],[52.36216,16.099291],[52.361931,16.099661],[52.36129,16.09997],[52.360569,16.100269],[52.360031,16.10107],[52.359779,16.102039],[52.359699,16.10269],[52.3596,16.103861],[52.359631,16.104851],[52.36039,16.10857],[52.36195,16.117229],[52.362999,16.123461],[52.36385,16.130489],[52.364521,16.136801],[52.365608,16.147249],[52.367062,16.161501],[52.367298,16.16527],[52.36742,16.168301],[52.367451,16.172119],[52.367611,16.185591],[52.36763,16.187149],[52.367821,16.19273],[52.368038,16.19655],[52.368622,16.20146],[52.36945,16.20701],[52.372471,16.222179],[52.375481,16.238211],[52.375839,16.24123],[52.376221,16.244749],[52.376629,16.249599],[52.37714,16.26313],[52.37738,16.270679],[52.377781,16.279659],[52.37822,16.288481],[52.379379,16.309139],[52.380039,16.32155],[52.38118,16.34289],[52.381981,16.356291],[52.38266,16.36916],[52.38324,16.37723],[52.383869,16.383631],[52.38559,16.396589],[52.38728,16.408449],[52.388142,16.41563],[52.388851,16.42271],[52.389351,16.428341],[52.38969,16.434139],[52.39006,16.44529],[52.390018,16.448879],[52.389881,16.453251],[52.389729,16.45645],[52.3895,16.459141],[52.38924,16.46138],[52.388569,16.46607],[52.387341,16.47382],[52.38707,16.47554],[52.386841,16.477989],[52.386749,16.479481],[52.3867,16.48031],[52.386551,16.483351],[52.386478,16.486731],[52.38657,16.491039],[52.386761,16.494961],[52.387081,16.49999],[52.387459,16.50783],[52.387501,16.511551],[52.387451,16.514919],[52.387249,16.520399],[52.3867,16.52607],[52.38604,16.531031],[52.385269,16.5352],[52.384708,16.53763],[52.383999,16.540649],[52.38084,16.55183],[52.37812,16.56093],[52.3773,16.563681],[52.376591,16.56605],[52.373539,16.575661],[52.370152,16.584909],[52.3647,16.59923],[52.360741,16.60952],[52.357101,16.61961],[52.35582,16.62454],[52.355042,16.628139],[52.353432,16.638],[52.35215,16.64694],[52.350979,16.654249],[52.35059,16.656679],[52.349979,16.660419],[52.349369,16.664169],[52.34903,16.66687],[52.348579,16.67141],[52.348389,16.67975],[52.34893,16.691719],[52.349468,16.70499],[52.349819,16.713869],[52.349899,16.715731],[52.35001,16.718731],[52.350319,16.726601],[52.350422,16.729759],[52.350491,16.73181],[52.350491,16.73185],[52.350491,16.731979],[52.350491,16.736811],[52.350491,16.74202],[52.350479,16.75079],[52.350521,16.761419],[52.350479,16.77059],[52.35043,16.778931],[52.35046,16.795071],[52.35033,16.81012],[52.3503,16.826269],[52.350319,16.83869],[52.35041,16.841261],[52.350609,16.84532],[52.350651,16.846121],[52.35088,16.849079],[52.35112,16.85165],[52.35257,16.863581],[52.354179,16.876539],[52.3545,16.879709],[52.354691,16.88483],[52.354698,16.88644],[52.354641,16.888269],[52.354519,16.89225],[52.354389,16.89537],[52.354179,16.897949],[52.35379,16.901699],[52.353741,16.90243],[52.353352,16.90744],[52.35313,16.91028],[52.35281,16.914261],[52.352631,16.916651],[52.352428,16.91897],[52.3521,16.923109],[52.350979,16.937201],[52.349918,16.94964],[52.3494,16.956039],[52.348999,16.961029],[52.348652,16.9655],[52.348,16.973419],[52.347019,16.98617],[52.346531,16.99177],[52.345741,17.0009],[52.345322,17.004881],[52.345009,17.007601],[52.344269,17.01376],[52.34333,17.0207],[52.342529,17.0254],[52.34095,17.034031],[52.337791,17.049919],[52.334721,17.0646],[52.331821,17.078711],[52.329639,17.087839],[52.32906,17.090099],[52.32856,17.09207],[52.327869,17.094801],[52.326542,17.099489],[52.324188,17.107441],[52.32201,17.114479],[52.318722,17.12499],[52.31752,17.12882],[52.31514,17.136431],[52.312561,17.144501],[52.311531,17.1478],[52.311031,17.14967],[52.310692,17.150949],[52.310612,17.1513],[52.310101,17.15361],[52.309872,17.15439],[52.309158,17.157721],[52.308281,17.163059],[52.307789,17.166821],[52.307411,17.170919],[52.307159,17.17539],[52.307072,17.179951],[52.307159,17.18524],[52.30761,17.190941],[52.307919,17.19392],[52.30904,17.201851],[52.309639,17.20735],[52.310059,17.212879],[52.310219,17.223009],[52.310131,17.24172],[52.310131,17.25379],[52.310059,17.265499],[52.310009,17.2722],[52.31004,17.278469],[52.310001,17.296169],[52.309929,17.305731],[52.309929,17.32172],[52.309841,17.34235],[52.309818,17.35442],[52.30991,17.357189],[52.310108,17.362419],[52.311218,17.376181],[52.311531,17.37855],[52.312019,17.38233],[52.312881,17.38825],[52.314861,17.399639],[52.317001,17.41197],[52.317711,17.417191],[52.318211,17.421301],[52.318691,17.42766],[52.31892,17.4317],[52.319038,17.436029],[52.31905,17.440769],[52.318821,17.454201],[52.31863,17.468769],[52.318409,17.48267],[52.31818,17.49605],[52.317921,17.50906],[52.317699,17.51322],[52.316971,17.521919],[52.316311,17.526711],[52.31567,17.530861],[52.315208,17.53367],[52.31498,17.53483],[52.314461,17.53759],[52.31406,17.539631],[52.313801,17.540899],[52.31295,17.54521],[52.312279,17.548889],[52.31216,17.549549],[52.311619,17.55254],[52.31144,17.553499],[52.310799,17.55788],[52.31052,17.56024],[52.3102,17.563971],[52.30999,17.56748],[52.30975,17.57126],[52.30954,17.574511],[52.30933,17.57836],[52.309101,17.58201],[52.30883,17.58531],[52.308441,17.588831],[52.307899,17.592569],[52.30722,17.596371],[52.306309,17.600479],[52.305389,17.6045],[52.304482,17.60854],[52.303532,17.612631],[52.302601,17.61665],[52.301689,17.620621],[52.300812,17.624559],[52.299938,17.628269],[52.299042,17.63216],[52.298119,17.6362],[52.297241,17.639971],[52.29636,17.64382],[52.295509,17.64756],[52.294621,17.65148],[52.293709,17.65538],[52.29277,17.659121],[52.29174,17.662821],[52.290619,17.666571],[52.289539,17.66995],[52.288361,17.673321],[52.287079,17.67683],[52.285419,17.68096],[52.284302,17.683741],[52.282619,17.687811],[52.281368,17.690929],[52.279861,17.694639],[52.27853,17.697969],[52.27705,17.70166],[52.275711,17.70507],[52.274361,17.70862],[52.272991,17.712521],[52.271801,17.716221],[52.270828,17.719391],[52.26992,17.72262],[52.269112,17.72566],[52.268009,17.73033],[52.267029,17.73484],[52.266171,17.739389],[52.26545,17.74361],[52.264851,17.74773],[52.264339,17.75156],[52.26395,17.755159],[52.263531,17.75952],[52.2631,17.764071],[52.262661,17.76853],[52.262291,17.77253],[52.261848,17.776291],[52.261261,17.780161],[52.260521,17.78458],[52.259731,17.78904],[52.25893,17.7936],[52.258129,17.79822],[52.25724,17.80298],[52.256351,17.80759],[52.25547,17.81222],[52.254551,17.81682],[52.25354,17.82229],[52.25312,17.824261],[52.252941,17.82514],[52.25259,17.82683],[52.252419,17.827629],[52.251381,17.83252],[52.2509,17.83478],[52.249779,17.83993],[52.248749,17.84458],[52.247639,17.84947],[52.246498,17.85438],[52.245319,17.8594],[52.24419,17.86404],[52.24305,17.868641],[52.24176,17.8738],[52.240639,17.87789],[52.239029,17.88295],[52.23682,17.889059],[52.235039,17.894119],[52.23349,17.898911],[52.23222,17.903549],[52.23119,17.90774],[52.23016,17.91255],[52.229259,17.91707],[52.228359,17.921789],[52.22744,17.92672],[52.226559,17.931179],[52.225601,17.935749],[52.224491,17.940611],[52.223751,17.943661],[52.22287,17.946989],[52.222279,17.949011],[52.221851,17.95014],[52.221439,17.951441],[52.221069,17.953329],[52.22031,17.956221],[52.218899,17.96109],[52.2174,17.966471],[52.216011,17.97163],[52.21492,17.97599],[52.21381,17.980471],[52.212631,17.98546],[52.21167,17.98987],[52.210781,17.99387],[52.20961,17.99971],[52.20866,18.004471],[52.20779,18.008881],[52.206749,18.013941],[52.20602,18.017241],[52.205151,18.02088],[52.204651,18.02261],[52.204361,18.023609],[52.203629,18.026171],[52.20158,18.032551],[52.199871,18.03726],[52.198181,18.04203],[52.196732,18.046591],[52.19548,18.051359],[52.19442,18.056259],[52.19352,18.06118],[52.19257,18.06632],[52.19146,18.07118],[52.190239,18.075649],[52.18866,18.080429],[52.187099,18.085381],[52.18586,18.09009],[52.1847,18.094481],[52.183529,18.099291],[52.182571,18.10388],[52.181751,18.108379],[52.180939,18.11359],[52.180149,18.11895],[52.17931,18.124451],[52.178391,18.12904],[52.177391,18.133511],[52.176289,18.13798],[52.175289,18.142071],[52.174252,18.146379],[52.173119,18.15097],[52.172169,18.15522],[52.171021,18.160151],[52.17004,18.164909],[52.169079,18.1696],[52.168129,18.17441],[52.16724,18.179291],[52.166359,18.18424],[52.165501,18.18927],[52.164799,18.193991],[52.164261,18.19729],[52.163601,18.201611],[52.163479,18.202221],[52.163288,18.203501],[52.162941,18.205879],[52.162628,18.20842],[52.162441,18.210489],[52.162209,18.212669],[52.162029,18.21505],[52.161758,18.218439],[52.161381,18.223881],[52.161018,18.229349],[52.160629,18.234871],[52.160221,18.24069],[52.15979,18.24567],[52.15921,18.250759],[52.158298,18.256281],[52.157089,18.26198],[52.15686,18.262859],[52.156521,18.264111],[52.156021,18.26605],[52.155621,18.26754],[52.155529,18.267851],[52.153629,18.273861],[52.151821,18.279779],[52.151131,18.28227],[52.150261,18.28594],[52.149189,18.29163],[52.14827,18.299],[52.147739,18.303749],[52.147419,18.307131],[52.146671,18.31233],[52.145721,18.31716],[52.14344,18.32645],[52.1422,18.33209],[52.141201,18.3377],[52.14061,18.342541],[52.140171,18.348499],[52.14003,18.353571],[52.140141,18.359501],[52.140388,18.36388],[52.14098,18.369869],[52.141541,18.37516],[52.141998,18.381081],[52.142281,18.386061],[52.142429,18.390619],[52.142551,18.39543],[52.142719,18.40027],[52.14312,18.40498],[52.143608,18.409361],[52.144421,18.414459],[52.145329,18.419029],[52.1464,18.42411],[52.14727,18.42831],[52.148239,18.432989],[52.14922,18.437771],[52.15012,18.4422],[52.150902,18.446541],[52.151581,18.450729],[52.1521,18.4548],[52.152512,18.46007],[52.152641,18.46566],[52.152561,18.470949],[52.152241,18.476339],[52.15163,18.48201],[52.150822,18.487101],[52.149769,18.492439],[52.148651,18.497259],[52.147419,18.502279],[52.1464,18.50639],[52.145149,18.511869],[52.144218,18.516371],[52.14336,18.521139],[52.142601,18.526649],[52.14204,18.531811],[52.14164,18.5376],[52.141411,18.54336],[52.141399,18.54904],[52.141472,18.55442],[52.141609,18.55991],[52.141731,18.565041],[52.141842,18.569691],[52.141979,18.57476],[52.142101,18.57938],[52.14212,18.584629],[52.14204,18.589439],[52.141811,18.594589],[52.141441,18.59964],[52.141029,18.603769],[52.140869,18.60504],[52.140541,18.607731],[52.140091,18.610941],[52.140011,18.61146],[52.139519,18.614491],[52.138969,18.617519],[52.13818,18.62149],[52.13723,18.62561],[52.135731,18.631559],[52.135681,18.63175],[52.134151,18.63732],[52.13364,18.63928],[52.13271,18.64283],[52.13187,18.6465],[52.13039,18.654449],[52.129341,18.660379],[52.128231,18.66544],[52.127201,18.669399],[52.12553,18.674879],[52.123859,18.680531],[52.12262,18.685539],[52.121559,18.691231],[52.121071,18.694349],[52.120071,18.702909],[52.1194,18.708441],[52.118649,18.71439],[52.118198,18.71767],[52.1171,18.723419],[52.116119,18.727289],[52.115021,18.731091],[52.114159,18.733749],[52.112358,18.73856],[52.110241,18.74337],[52.10701,18.74958],[52.104431,18.75449],[52.102268,18.75923],[52.1003,18.76413],[52.09827,18.769489],[52.096371,18.7742],[52.09589,18.775391],[52.094379,18.77862],[52.093109,18.781071],[52.091259,18.78434],[52.089241,18.7875],[52.08601,18.791849],[52.082939,18.79541],[52.080631,18.79825],[52.077099,18.80315],[52.07399,18.80831],[52.072338,18.811621],[52.071739,18.81282],[52.070518,18.81525],[52.0704,18.8155],[52.068199,18.82025],[52.06596,18.82456],[52.063099,18.82938],[52.0588,18.835791],[52.055489,18.840611],[52.052441,18.845091],[52.049061,18.850071],[52.045551,18.85527],[52.042881,18.859631],[52.04081,18.8634],[52.03949,18.8661],[52.038158,18.86907],[52.03714,18.8715],[52.035439,18.8759],[52.034222,18.879629],[52.033932,18.880529],[52.0327,18.88485],[52.031189,18.89113],[52.029381,18.899929],[52.02813,18.906179],[52.026958,18.911909],[52.025688,18.916809],[52.024479,18.92082],[52.02261,18.926399],[52.019821,18.93458],[52.017609,18.941151],[52.015862,18.94672],[52.014771,18.950951],[52.013149,18.95867],[52.011902,18.96446],[52.01046,18.969851],[52.008881,18.974689],[52.006538,18.98114],[52.00449,18.987221],[52.003071,18.991859],[52.001549,18.997669],[52.00045,19.002541],[51.999458,19.00773],[51.998039,19.01741],[51.99765,19.02055],[51.997459,19.02207],[51.99728,19.02351],[51.996399,19.0298],[51.995399,19.035801],[51.995022,19.03763],[51.994659,19.039221],[51.994148,19.04134],[51.99337,19.04438],[51.992531,19.047159],[51.991379,19.050579],[51.989731,19.054779],[51.98848,19.05761],[51.987129,19.0604],[51.985611,19.06324],[51.984531,19.06517],[51.97858,19.075291],[51.975769,19.08061],[51.973869,19.08461],[51.971889,19.08955],[51.970181,19.0944],[51.96793,19.10198],[51.966339,19.10762],[51.964859,19.112471],[51.96376,19.11552],[51.96101,19.12225],[51.95937,19.12607],[51.957458,19.13121],[51.95565,19.137289],[51.954498,19.142019],[51.952572,19.151661],[51.951248,19.15736],[51.94973,19.162621],[51.946812,19.171141],[51.94466,19.177509],[51.94305,19.183149],[51.941799,19.188761],[51.94101,19.193199],[51.940472,19.19698],[51.939911,19.20273],[51.93969,19.20854],[51.93964,19.214411],[51.93972,19.222719],[51.93969,19.22901],[51.93951,19.23262],[51.939289,19.235571],[51.93895,19.239189],[51.938301,19.244301],[51.937191,19.25193],[51.93644,19.25717],[51.935619,19.262699],[51.935001,19.266729],[51.934132,19.271299],[51.932522,19.278561],[51.931179,19.284679],[51.930161,19.289539],[51.92918,19.29582],[51.928619,19.301411],[51.928188,19.309851],[51.92783,19.31459],[51.927368,19.31875],[51.92696,19.321699],[51.92617,19.32612],[51.925098,19.33124],[51.924011,19.336901],[51.92337,19.34087],[51.922699,19.345881],[51.922249,19.349649],[51.922031,19.351789],[51.922001,19.35211],[51.921799,19.354139],[51.9217,19.35556],[51.921539,19.35808],[51.921391,19.360901],[51.921329,19.36195],[51.9212,19.36455],[51.921082,19.37055],[51.921101,19.375401],[51.921139,19.383471],[51.921082,19.38681],[51.920979,19.390619],[51.92075,19.393961],[51.920269,19.39966],[51.91922,19.40678],[51.918449,19.4112],[51.917461,19.41625],[51.91684,19.41865],[51.916069,19.42169],[51.912361,19.432541],[51.910278,19.43788],[51.90992,19.438749],[51.909222,19.44047],[51.90802,19.44343],[51.905972,19.44853],[51.90398,19.45363],[51.902161,19.45896],[51.901321,19.46212],[51.90086,19.464001],[51.900398,19.46608],[51.899971,19.46797],[51.89933,19.4711],[51.898151,19.47998],[51.89793,19.483231],[51.897812,19.48616],[51.89777,19.49305],[51.898151,19.51585],[51.898129,19.516371],[51.898041,19.5182],[51.897861,19.522011],[51.896622,19.536489],[51.889702,19.57382],[51.888969,19.57979],[51.88868,19.58357],[51.888618,19.585079],[51.888519,19.58819],[51.88858,19.591181],[51.888599,19.591881],[51.888729,19.594959],[51.888889,19.598301],[51.889099,19.601311],[51.88942,19.60549],[51.889549,19.60721],[51.88998,19.612881],[51.890079,19.614189],[51.890732,19.623899],[51.89077,19.62446],[51.891209,19.626949],[51.891251,19.627399],[51.891319,19.627939],[51.891418,19.62862],[51.891602,19.62936],[51.89183,19.630011],[51.89201,19.63035],[51.892159,19.63055],[51.892429,19.63093],[51.892792,19.63135],[51.893051,19.631559],[51.893471,19.6318],[51.89389,19.631929],[51.894218,19.631941],[51.894482,19.63191],[51.894711,19.63187],[51.894878,19.631781],[51.895161,19.631651],[51.89534,19.631531],[51.89547,19.631451],[51.895649,19.6313],[51.896198,19.630911],[51.89645,19.63073],[51.896679,19.63059],[51.896992,19.630381],[51.89743,19.630079],[51.898602,19.629339],[51.899212,19.628929],[51.900139,19.628349],[51.901081,19.62775],[51.90221,19.627171],[51.904461,19.62602],[51.90659,19.625019],[51.90855,19.624161],[51.910789,19.62328],[51.911888,19.62302],[51.912621,19.62285],[51.912819,19.62285],[51.913059,19.623051],[51.914322,19.625601],[51.914452,19.62591],[51.914661,19.626341],[51.9161,19.628691],[51.925201,19.644131],[51.925949,19.64506],[51.92897,19.647631],[51.93063,19.64908],[51.931019,19.649509],[51.931149,19.6497],[51.932259,19.652],[51.932751,19.65308],[51.943272,19.676041],[51.94331,19.676121],[51.94688,19.68264],[51.949989,19.68832],[51.95681,19.700911],[51.958549,19.704069],[51.9589,19.70484],[51.959049,19.705549],[51.95969,19.71069],[51.960819,19.723619],[51.96109,19.726681],[51.961231,19.728161],[51.961239,19.728291],[51.961361,19.7293],[51.961571,19.7299],[51.961811,19.7304],[51.962719,19.731529],[51.96312,19.732019],[51.963539,19.73242],[51.964809,19.733271],[51.965191,19.733509],[51.965439,19.73369],[51.965641,19.7339],[51.96574,19.73403],[51.9664,19.735121],[51.970589,19.742229],[51.973179,19.74663],[51.979118,19.75663],[51.993279,19.7805],[51.99371,19.781219],[52.001862,19.79495],[52.002369,19.79583],[52.0056,19.80126],[52.005829,19.8018],[52.006008,19.802219],[52.006229,19.802891],[52.006248,19.802971],[52.006939,19.8053],[52.00761,19.8076],[52.008629,19.811211],[52.008709,19.811489],[52.008808,19.811819],[52.0089,19.812111],[52.00927,19.81325],[52.009628,19.81402],[52.01593,19.82633],[52.023281,19.84086],[52.02507,19.84432],[52.026192,19.846519],[52.039162,19.87204],[52.039261,19.87224],[52.040749,19.87517],[52.041199,19.87606],[52.041538,19.87673],[52.042561,19.878771],[52.042839,19.87924],[52.044312,19.88221],[52.048222,19.88994],[52.04845,19.890381],[52.048969,19.89139],[52.04916,19.891769],[52.049259,19.89193],[52.04937,19.89213],[52.049419,19.892179],[52.04969,19.89249],[52.050049,19.892771],[52.050961,19.893471],[52.05225,19.89448],[52.05455,19.89625],[52.05455,19.896259],[52.059502,19.900061],[52.060539,19.90085],[52.06316,19.90287],[52.068199,19.90674],[52.068508,19.906981],[52.069099,19.907419],[52.07645,19.91301],[52.076649,19.91317],[52.0769,19.91337],[52.076969,19.913429],[52.077579,19.9139],[52.07782,19.91408],[52.07843,19.91453],[52.079029,19.91498],[52.080231,19.915899],[52.08263,19.917749],[52.083,19.91802],[52.08308,19.918079],[52.084671,19.919279],[52.08535,19.9198],[52.085579,19.919941],[52.085819,19.920059],[52.08609,19.920179],[52.086391,19.92024],[52.086731,19.920271],[52.087021,19.920231],[52.087231,19.920231],[52.087421,19.920259],[52.087471,19.920349],[52.087521,19.920389],[52.087582,19.920401],[52.08765,19.92037],[52.087688,19.920309],[52.08773,19.920231],[52.08786,19.92013],[52.088089,19.920059],[52.088181,19.92005],[52.09103,19.91968],[52.091709,19.91959],[52.092682,19.91946],[52.094219,19.919241],[52.095741,19.919029],[52.096741,19.9189],[52.09774,19.91877],[52.09972,19.918501],[52.10078,19.91835],[52.101028,19.91835],[52.101631,19.918409],[52.10215,19.91857],[52.1026,19.918779],[52.10284,19.91894],[52.103149,19.919161],[52.103401,19.91938],[52.103729,19.919701],[52.10397,19.919991],[52.104198,19.92029],[52.10445,19.920679],[52.104691,19.921129],[52.104961,19.92174],[52.105209,19.92234],[52.105961,19.924509],[52.106411,19.92577],[52.107052,19.92757],[52.107109,19.927719],[52.107231,19.928011],[52.107349,19.928221],[52.10754,19.928579],[52.107731,19.92885],[52.107929,19.929119],[52.108089,19.929279],[52.108452,19.929609],[52.10873,19.929819],[52.109039,19.929991],[52.109371,19.93012],[52.109699,19.930189],[52.111229,19.93025],[52.111641,19.930269],[52.11277,19.930321],[52.112801,19.930321],[52.114609,19.930401],[52.116451,19.93051],[52.116501,19.930519],[52.117069,19.93054],[52.11721,19.930559],[52.117699,19.930639],[52.117962,19.93071],[52.118198,19.93082],[52.118259,19.930849],[52.118629,19.931061],[52.1189,19.93124],[52.119511,19.93181],[52.119598,19.93195],[52.11964,19.93211],[52.119652,19.93228],[52.11964,19.932501],[52.11948,19.93355],[52.1194,19.934561],[52.11937,19.934799],[52.119209,19.9359],[52.11879,19.938721],[52.11866,19.939581],[52.118591,19.94043],[52.118462,19.943199],[52.11832,19.94618],[52.118279,19.947439],[52.118191,19.94982],[52.118069,19.952339],[52.118,19.95396],[52.117882,19.95689],[52.11755,19.96439],[52.117512,19.965401],[52.117512,19.96545],[52.117512,19.9655],[52.117458,19.966459],[52.11742,19.967331],[52.117371,19.968451],[52.117241,19.971201],[52.11721,19.97176],[52.11705,19.974291],[52.11705,19.974951],[52.117062,19.97537],[52.117069,19.97596],[52.11718,19.976419],[52.118179,19.980631],[52.12101,19.99221],[52.12315,20.00086],[52.124432,20.006109],[52.125622,20.010969],[52.125771,20.0116],[52.128719,20.02354],[52.13121,20.03376],[52.137619,20.05954],[52.137859,20.06052],[52.140442,20.07085],[52.14724,20.097931],[52.14912,20.105459],[52.150661,20.111549],[52.151909,20.11652],[52.15295,20.120399],[52.153191,20.12104],[52.153542,20.121799],[52.154518,20.12351],[52.155048,20.12418],[52.15556,20.12472],[52.156071,20.125191],[52.163651,20.130739],[52.16431,20.131229],[52.169559,20.13509],[52.17205,20.136921],[52.18475,20.14629],[52.185478,20.146959],[52.18557,20.147079],[52.186081,20.147791],[52.190811,20.155861],[52.195271,20.163349],[52.199051,20.169781],[52.20237,20.17544],[52.203159,20.176781],[52.21146,20.19092],[52.215248,20.197371],[52.217178,20.20079],[52.2178,20.20186],[52.218819,20.203791],[52.21891,20.204121],[52.218868,20.20435],[52.218529,20.2052],[52.21241,20.216709],[52.21188,20.21773],[52.211472,20.218559],[52.211281,20.21888],[52.210812,20.2201],[52.210548,20.22089],[52.210312,20.221519],[52.20911,20.22497],[52.20903,20.22521],[52.207981,20.228109],[52.206749,20.23156],[52.20615,20.23431],[52.206039,20.235769],[52.20602,20.237249],[52.206169,20.23875],[52.206409,20.240061],[52.20697,20.2428],[52.207569,20.24559],[52.207909,20.246861],[52.20834,20.248211],[52.20892,20.249411],[52.209549,20.250441],[52.20974,20.250799],[52.209721,20.250919],[52.20974,20.25104],[52.209789,20.251129],[52.209862,20.251181],[52.20993,20.251181],[52.209969,20.25116],[52.21006,20.2512],[52.210258,20.25141],[52.210758,20.251921],[52.210999,20.252069],[52.212631,20.253281],[52.214298,20.254391],[52.223068,20.26042],[52.22393,20.26133],[52.224411,20.26195],[52.224731,20.26248],[52.225361,20.2637],[52.22538,20.263929],[52.225479,20.264299],[52.225689,20.26482],[52.226009,20.265989],[52.226021,20.26605],[52.226261,20.267429],[52.226398,20.267891],[52.226471,20.26993],[52.226421,20.270821],[52.225651,20.27956],[52.22266,20.312559],[52.220852,20.33256],[52.220421,20.33741],[52.220032,20.34166],[52.219318,20.349609],[52.218319,20.36063],[52.217331,20.371441],[52.21656,20.37977],[52.215939,20.38644],[52.21373,20.41028],[52.2132,20.416161],[52.21209,20.42832],[52.211891,20.430229],[52.2117,20.432301],[52.209419,20.45714],[52.208721,20.46471],[52.206589,20.488091],[52.205059,20.50466],[52.20435,20.512369],[52.204269,20.51329],[52.202881,20.52837],[52.201641,20.54178],[52.201469,20.54582],[52.20039,20.571939],[52.199059,20.60359],[52.19899,20.60586],[52.19899,20.605989],[52.198978,20.60627],[52.198841,20.60903],[52.198799,20.610081],[52.198711,20.612419],[52.198582,20.61577],[52.198528,20.616989],[52.198528,20.61718],[52.198502,20.6178],[52.199001,20.61994],[52.19936,20.62149],[52.19968,20.62286],[52.199902,20.62373],[52.199982,20.62405],[52.200249,20.62512],[52.20163,20.6308],[52.20644,20.650591],[52.207199,20.653879],[52.207699,20.656031],[52.207859,20.656719],[52.208321,20.659109],[52.208889,20.66353],[52.208988,20.66445],[52.21006,20.673531],[52.2113,20.68404],[52.21133,20.684271],[52.211842,20.688919],[52.212139,20.691401],[52.21273,20.69622],[52.212811,20.701071],[52.2118,20.74048],[52.21143,20.75633],[52.211239,20.7649],[52.211151,20.76845],[52.211121,20.769911],[52.21088,20.778219],[52.210678,20.78578],[52.210579,20.788231],[52.21056,20.788971],[52.21051,20.791401],[52.210468,20.793091],[52.210419,20.794769],[52.210381,20.79623],[52.210331,20.797279],[52.210232,20.801121],[52.21014,20.804319],[52.210041,20.80776],[52.209999,20.809271],[52.209999,20.80971],[52.21003,20.81019],[52.210091,20.81061],[52.210178,20.81123],[52.211182,20.817699],[52.21244,20.82584],[52.212551,20.826891],[52.2131,20.83094],[52.213821,20.835529],[52.214272,20.83843],[52.214321,20.838869],[52.214359,20.839069],[52.214451,20.83972],[52.214741,20.841749],[52.21489,20.843809],[52.21524,20.84981],[52.215832,20.859699],[52.215839,20.85993],[52.2159,20.861],[52.215961,20.861971],[52.216,20.8626],[52.216141,20.86487],[52.216148,20.86503],[52.21632,20.86783],[52.216351,20.86927],[52.21637,20.871429],[52.216381,20.873899],[52.216389,20.874929],[52.216381,20.877769],[52.216381,20.880011],[52.21637,20.88043],[52.216381,20.885969],[52.216389,20.8887],[52.216381,20.89061],[52.216358,20.89253],[52.21637,20.89607],[52.216389,20.896629],[52.216431,20.89715],[52.21648,20.89769],[52.216572,20.89847],[52.21677,20.90044],[52.216808,20.90089],[52.216869,20.90147],[52.21693,20.90193],[52.217159,20.904011],[52.217209,20.90428],[52.217579,20.906019],[52.218021,20.90799],[52.218342,20.90933],[52.218399,20.90958],[52.218559,20.910271],[52.219501,20.914419],[52.219879,20.91584],[52.219921,20.91605],[52.219971,20.91625],[52.220039,20.91663],[52.220539,20.91868],[52.221008,20.92062],[52.221161,20.921289],[52.22171,20.92355],[52.221939,20.92453],[52.22208,20.925131],[52.2225,20.926991],[52.222778,20.9282],[52.22319,20.929831],[52.22324,20.930031],[52.223289,20.93021],[52.223671,20.93152],[52.223881,20.93219],[52.224041,20.932739],[52.224998,20.93623],[52.22514,20.93675],[52.225189,20.93696],[52.22562,20.93853],[52.225719,20.939369],[52.225761,20.939659],[52.225788,20.940701],[52.225868,20.941589],[52.22588,20.94166],[52.225929,20.94198],[52.226311,20.94463],[52.226921,20.948071],[52.22739,20.951281],[52.227451,20.95166],[52.227482,20.95199],[52.227638,20.95425],[52.22773,20.95582],[52.22773,20.956141],[52.227692,20.956659],[52.227692,20.95694],[52.227539,20.95694],[52.226009,20.95731],[52.225349,20.957581],[52.2243,20.957781],[52.22422,20.957821],[52.22353,20.957991],[52.22324,20.95809],[52.22245,20.95833],[52.222252,20.95842],[52.222012,20.95859],[52.22086,20.95952],[52.220581,20.95965],[52.22002,20.95978],[52.21814,20.959909],[52.217659,20.95998],[52.216461,20.9606],[52.216331,20.96073],[52.21619,20.96109],[52.216179,20.961399],[52.216221,20.96166],[52.216572,20.962601],[52.21703,20.963711],[52.21759,20.96524],[52.219391,20.970369],[52.219479,20.97084],[52.219479,20.971251],[52.219471,20.971371],[52.21946,20.97147],[52.218948,20.972969],[52.218861,20.973249],[52.21875,20.973551],[52.217621,20.976971],[52.217541,20.977221],[52.217461,20.977461],[52.2164,20.980619],[52.216301,20.980909],[52.21624,20.98107],[52.216228,20.9811],[52.216179,20.981239],[52.21611,20.981449],[52.216042,20.981649],[52.215981,20.981911],[52.215961,20.982149],[52.215969,20.98246],[52.215981,20.982679],[52.216042,20.983801],[52.216061,20.9842],[52.216091,20.98497],[52.216221,20.987],[52.216228,20.98728],[52.216221,20.987591],[52.216209,20.98782],[52.21619,20.98806],[52.216179,20.98838],[52.216179,20.98884],[52.216259,20.989929],[52.21627,20.990259],[52.21632,20.99095],[52.216511,20.99444],[52.216801,20.999901],[52.21682,21.000429],[52.217121,21.004539],[52.21719,21.00563],[52.21727,21.00716],[52.217281,21.00845],[52.217209,21.01022],[52.217159,21.01169],[52.216999,21.01438],[52.216999,21.0149],[52.21703,21.015421],[52.217079,21.01594],[52.217171,21.01647],[52.217449,21.0177],[52.21759,21.01844],[52.21767,21.018801],[52.217861,21.019581],[52.21793,21.01984],[52.218399,21.021761],[52.219059,21.024469],[52.219372,21.02578],[52.219742,21.027309],[52.21994,21.0282],[52.220669,21.03112],[52.221458,21.034109],[52.222229,21.037251],[52.22266,21.03857],[52.223,21.03944],[52.223148,21.039841],[52.223301,21.040211],[52.223511,21.040739],[52.223701,21.04143],[52.223789,21.04184],[52.22403,21.0431],[52.22443,21.045059],[52.225712,21.05121],[52.22612,21.053249],[52.226509,21.055201],[52.22686,21.056789],[52.2271,21.057699],[52.228149,21.061621],[52.228378,21.06255],[52.228901,21.06455],[52.229111,21.065319],[52.229401,21.0665],[52.229889,21.06831],[52.23035,21.07052],[52.230652,21.07151],[52.230831,21.07196],[52.23233,21.074381],[52.233021,21.07556],[52.235081,21.078911],[52.235271,21.079479],[52.235401,21.0802],[52.23547,21.080629],[52.235531,21.081091],[52.235661,21.08217],[52.235889,21.08399],[52.236061,21.08552],[52.236099,21.08663],[52.236099,21.08683],[52.236038,21.087641],[52.235958,21.088421],[52.235771,21.089439],[52.2351,21.093491],[52.234951,21.09482],[52.234871,21.095501],[52.23468,21.097151],[52.234661,21.09741],[52.234631,21.097679],[52.23444,21.099489],[52.23436,21.10021],[52.2342,21.101629],[52.233971,21.10355],[52.23386,21.10463],[52.233768,21.10532],[52.233459,21.10816],[52.233349,21.109051],[52.233059,21.111691],[52.232899,21.113239],[52.232861,21.11352],[52.232681,21.115021],[52.232571,21.116529],[52.232521,21.118191],[52.232521,21.11837],[52.23251,21.118799],[52.232571,21.12027],[52.23259,21.121389],[52.232601,21.12254],[52.23262,21.12421],[52.232639,21.125429],[52.232639,21.126711],[52.232658,21.12788],[52.232651,21.12854],[52.232639,21.129089],[52.232559,21.12974],[52.23243,21.130461],[52.23225,21.131069],[52.23201,21.13171],[52.231602,21.13269],[52.230782,21.134729],[52.23003,21.136499],[52.22971,21.137251],[52.22934,21.138109],[52.22908,21.138691],[52.228691,21.13958],[52.2286,21.139799],[52.228352,21.140369],[52.228039,21.14101],[52.22784,21.14147],[52.227188,21.142929],[52.226871,21.143669],[52.226669,21.14419],[52.226551,21.144661],[52.22644,21.145149],[52.226372,21.14566],[52.226341,21.146231],[52.22628,21.148359],[52.22628,21.14887],[52.226231,21.14978],[52.226181,21.15131],[52.226158,21.152491],[52.22612,21.15346],[52.226101,21.153851],[52.226059,21.15535],[52.225922,21.158939],[52.225891,21.15937],[52.225819,21.161421],[52.225689,21.165609],[52.22551,21.17029],[52.225189,21.17864],[52.224819,21.18928],[52.224529,21.196859],[52.224491,21.198009],[52.22427,21.20554],[52.224072,21.21101],[52.223911,21.21578],[52.223782,21.219891],[52.22369,21.22279],[52.223679,21.22303],[52.223671,21.223289],[52.223629,21.22451],[52.223469,21.229271],[52.223381,21.230721],[52.223301,21.23295],[52.223259,21.23402],[52.22324,21.235041],[52.223179,21.23679],[52.22316,21.237249],[52.223049,21.23951],[52.22303,21.240021],[52.22295,21.243151],[52.222832,21.24703],[52.22274,21.24946],[52.22271,21.24983],[52.222691,21.249929],[52.222679,21.25062],[52.222511,21.255859],[52.222351,21.26104],[52.222309,21.26218],[52.22221,21.26466],[52.222179,21.26539],[52.222149,21.266211],[52.22208,21.267851],[52.22205,21.26918],[52.222038,21.26963],[52.222031,21.26977],[52.222,21.27087],[52.221771,21.277281],[52.2215,21.284731],[52.221481,21.28517],[52.221371,21.287571],[52.221321,21.288719],[52.22113,21.2906],[52.220459,21.293631],[52.219471,21.298019],[52.218601,21.301941],[52.21851,21.302389],[52.21767,21.306379],[52.216961,21.30962],[52.216648,21.311029],[52.215851,21.314739],[52.215611,21.315929],[52.215149,21.3183],[52.213772,21.32457],[52.21249,21.33049],[52.21233,21.331261],[52.211109,21.337],[52.210251,21.34096],[52.209511,21.34437],[52.207809,21.35216],[52.206211,21.35932],[52.20467,21.366529],[52.203072,21.374001],[52.202629,21.377239],[52.202209,21.380011],[52.202202,21.380091],[52.201889,21.38555],[52.201691,21.389219],[52.201439,21.3937],[52.201118,21.401541],[52.200611,21.410839],[52.200291,21.41663],[52.200119,21.42065],[52.199989,21.42417],[52.19978,21.427259],[52.199459,21.43342],[52.19923,21.43766],[52.199169,21.439381],[52.1992,21.44058],[52.1992,21.44236],[52.19923,21.443769],[52.199299,21.446381],[52.199429,21.44973],[52.199451,21.450439],[52.19952,21.452971],[52.19965,21.45809],[52.199871,21.46624],[52.20023,21.475121],[52.20052,21.484421],[52.20063,21.48831],[52.200581,21.490219],[52.200359,21.492001],[52.19994,21.49367],[52.198551,21.49864],[52.19664,21.505899],[52.194981,21.51228],[52.193371,21.51828],[52.192188,21.522989],[52.19175,21.52454],[52.190979,21.527349],[52.190819,21.527321],[52.190689,21.52746],[52.19062,21.527731],[52.19067,21.527941],[52.1908,21.528099],[52.190659,21.52861],[52.190048,21.530781],[52.18895,21.534809],[52.188709,21.53578],[52.188171,21.537849],[52.187778,21.539431],[52.18734,21.540939],[52.187061,21.54196],[52.18692,21.54249],[52.186329,21.544649],[52.18631,21.54475],[52.185612,21.54744],[52.185341,21.54867],[52.18454,21.55163],[52.184219,21.55286],[52.18388,21.55415],[52.183281,21.556311],[52.182911,21.55773],[52.182652,21.55871],[52.18248,21.55938],[52.181751,21.56234],[52.181149,21.564791],[52.18074,21.566441],[52.180698,21.56658],[52.180592,21.566999],[52.18029,21.568159],[52.179909,21.5697],[52.179588,21.571011],[52.179539,21.571159],[52.179329,21.57198],[52.179031,21.57312],[52.17873,21.574301],[52.178398,21.575541],[52.178059,21.57678],[52.178082,21.577339],[52.178169,21.580919],[52.178242,21.58276],[52.178291,21.58411],[52.178299,21.58423],[52.178421,21.589001],[52.178619,21.59437],[52.178791,21.59881],[52.17915,21.609301],[52.17923,21.611561],[52.179581,21.62187],[52.17976,21.626841],[52.18013,21.629681],[52.180229,21.630461],[52.182049,21.644159],[52.183769,21.64847],[52.184509,21.65386],[52.188019,21.68083],[52.192032,21.710409],[52.192532,21.723101],[52.195358,21.743959],[52.20295,21.80003],[52.203152,21.80052],[52.20396,21.802349],[52.206169,21.80718],[52.206692,21.808411],[52.208061,21.81164],[52.208801,21.813181],[52.209278,21.81419],[52.209461,21.81456],[52.210251,21.816771],[52.2104,21.81769],[52.210442,21.820499],[52.210419,21.82181],[52.210251,21.832239],[52.209831,21.861191],[52.209389,21.886351],[52.20929,21.89757],[52.208271,21.907749],[52.20443,21.94763],[52.203869,21.953699],[52.20055,21.98842],[52.197842,22.01725],[52.196651,22.0296],[52.196602,22.0301],[52.195881,22.03702],[52.19558,22.04031],[52.195709,22.042641],[52.197639,22.05447],[52.197762,22.055639],[52.197701,22.05674],[52.197571,22.057659],[52.196949,22.06188],[52.196949,22.061899],[52.19656,22.06428],[52.195641,22.069839],[52.19046,22.100559],[52.18803,22.11499],[52.187031,22.12093],[52.186642,22.123289],[52.184971,22.13299],[52.183868,22.140181],[52.18354,22.14233],[52.18045,22.16251],[52.18042,22.16272],[52.179218,22.170521],[52.178082,22.17807],[52.177551,22.18157],[52.17654,22.188499],[52.176029,22.191971],[52.175301,22.19693],[52.1745,22.202379],[52.173512,22.20912],[52.173241,22.21105],[52.172321,22.217211],[52.172031,22.21862],[52.171841,22.219561],[52.171371,22.221001],[52.171101,22.221569],[52.1707,22.2222],[52.170269,22.222759],[52.169971,22.223061],[52.169651,22.22337],[52.168919,22.223761],[52.16806,22.22397],[52.157452,22.223801],[52.149818,22.223669],[52.149181,22.223841],[52.148411,22.22414],[52.14703,22.225031],[52.145828,22.22603],[52.145191,22.226721],[52.14463,22.22753],[52.14407,22.228821],[52.143768,22.22994],[52.143559,22.23114],[52.143471,22.232981],[52.14365,22.236931],[52.14365,22.24024],[52.14352,22.242979],[52.143341,22.245081],[52.1427,22.24972],[52.14188,22.254181],[52.14146,22.256161],[52.141121,22.25769],[52.1409,22.25869],[52.14072,22.259331],[52.140381,22.26058],[52.13974,22.26259],[52.138321,22.266199],[52.137569,22.26819],[52.137032,22.26984],[52.136089,22.273109],[52.13562,22.275169],[52.13472,22.28014],[52.1339,22.284821],[52.133598,22.28676],[52.132912,22.29147],[52.13261,22.29401],[52.132191,22.29804],[52.131882,22.302031],[52.13163,22.307911],[52.13158,22.309839],[52.13158,22.315981],[52.131672,22.318979],[52.131882,22.323021],[52.132011,22.325979],[52.132011,22.327101],[52.131931,22.328251],[52.131882,22.328659],[52.131802,22.329201],[52.131672,22.32984],[52.131241,22.331301],[52.130268,22.33366],[52.1297,22.335079],[52.128479,22.338051],[52.1273,22.34091],[52.12524,22.34581],[52.124432,22.34767],[52.122318,22.35253],[52.122181,22.352859],[52.120171,22.35787],[52.11734,22.364731],[52.114368,22.371731],[52.112019,22.377439],[52.108501,22.385799],[52.105831,22.3922],[52.103809,22.39706],[52.102531,22.400141],[52.09618,22.415409],[52.0909,22.42794],[52.090092,22.43022],[52.08979,22.432711],[52.089741,22.43593],[52.089531,22.43782],[52.08934,22.4384],[52.08786,22.44297],[52.086208,22.45097],[52.08498,22.457041],[52.08387,22.46246],[52.083172,22.466141],[52.08202,22.476231],[52.081631,22.479191],[52.08065,22.482149],[52.0779,22.48863],[52.076649,22.49193],[52.074421,22.5],[52.072891,22.505619],[52.071678,22.51009],[52.06942,22.51827],[52.069012,22.51996],[52.06884,22.5236],[52.068878,22.526569],[52.068501,22.5291],[52.066872,22.534929],[52.06464,22.5427],[52.06356,22.54652],[52.063011,22.550079],[52.062531,22.55407],[52.061378,22.563471],[52.059921,22.57184],[52.059441,22.574579],[52.057259,22.58708],[52.057041,22.589569],[52.056999,22.591801],[52.057301,22.59729],[52.057678,22.608959],[52.05785,22.614059],[52.057991,22.618019],[52.058109,22.622311],[52.05743,22.62789],[52.055672,22.63789],[52.053139,22.652349],[52.050991,22.664709],[52.050049,22.67042],[52.049622,22.67214],[52.048592,22.67454],[52.045151,22.68055],[52.039101,22.691231],[52.03442,22.699511],[52.029881,22.707371],[52.02383,22.71763],[52.019051,22.72547],[52.015331,22.73226],[52.007431,22.74612],[52.0047,22.75083],[52.00449,22.75119],[52.004169,22.75172],[52.003368,22.753139],[52.002972,22.75382],[52.00243,22.75474],[52.001228,22.756901],[52.00069,22.75861],[52.000469,22.759689],[52.000408,22.76021],[52.000332,22.76083],[52.000301,22.763399],[52.00029,22.764009],[52.00029,22.76417],[52.00029,22.76475],[52.000259,22.766911],[52.000271,22.767811],[52.00029,22.7693],[52.000271,22.77309],[52.000092,22.78389],[51.999699,22.81146],[51.999771,22.813219],[51.999809,22.813709],[51.999969,22.814501],[52.000389,22.815821],[52.001049,22.817221],[52.002491,22.819941],[52.019131,22.850771],[52.02018,22.85272],[52.026829,22.86499],[52.027561,22.86714],[52.027748,22.86878],[52.02803,22.87328],[52.02816,22.876579],[52.028591,22.880751],[52.034531,22.91885],[52.036671,22.9328],[52.038502,22.94478],[52.038651,22.94701],[52.03661,22.99505],[52.034679,23.03936],[52.034382,23.04616],[52.033852,23.060539],[52.033821,23.06105],[52.033779,23.061331],[52.033741,23.06406],[52.033779,23.06502],[52.033932,23.066481],[52.03397,23.06702],[52.034039,23.06745],[52.03413,23.068199],[52.034382,23.069441],[52.034851,23.07103],[52.035332,23.072411],[52.035728,23.073481],[52.035858,23.07374],[52.035912,23.07374],[52.037621,23.077749],[52.038502,23.07987],[52.042339,23.08906],[52.045219,23.09586],[52.047531,23.10133],[52.049171,23.10528],[52.049759,23.107201],[52.05061,23.10993],[52.05101,23.11146],[52.05143,23.1134],[52.051769,23.115351],[52.052139,23.118019],[52.05233,23.120081],[52.052441,23.12163],[52.05254,23.1243],[52.05249,23.126431],[52.05241,23.128111],[52.05225,23.13044],[52.052052,23.132139],[52.051689,23.134399],[52.05138,23.136129],[52.051079,23.137541],[52.05014,23.14085],[52.049431,23.14304],[52.046921,23.149401],[52.046329,23.150881],[52.046249,23.151091],[52.041649,23.16205],[52.04108,23.16349],[52.040989,23.163771],[52.040878,23.16407],[52.040722,23.16494],[52.040668,23.165991],[52.040699,23.166901],[52.040852,23.16884],[52.04092,23.17067],[52.040909,23.170799],[52.040352,23.17984],[52.040001,23.184799],[52.039848,23.18705],[52.03894,23.19945],[52.038151,23.211281],[52.037041,23.226919],[52.036201,23.23984],[52.035629,23.247259],[52.035198,23.254669],[52.034111,23.268709],[52.034019,23.270809],[52.0341,23.278021],[52.034279,23.285179],[52.03437,23.289591],[52.034679,23.30765],[52.03487,23.319969],[52.03503,23.33103],[52.035431,23.352261],[52.035568,23.36269],[52.035751,23.37554],[52.036121,23.39966],[52.03648,23.423731],[52.03669,23.44198],[52.037102,23.471069],[52.056198,23.47821],[52.057281,23.479031],[52.062019,23.48612],[52.06966,23.497549],[52.07505,23.50531],[52.074341,23.506451],[52.074478,23.507071],[52.075321,23.508471],[52.076199,23.51207],[52.077019,23.517269],[52.078541,23.523121],[52.079208,23.52372],[52.080021,23.527479],[52.080372,23.52845],[52.080971,23.52993],[52.08247,23.531771],[52.097488,23.550831],[52.100391,23.55324],[52.115749,23.565399],[52.116249,23.565861],[52.116879,23.566429],[52.119869,23.56897],[52.12009,23.569189],[52.121159,23.570431],[52.1236,23.573311],[52.123859,23.57374],[52.124371,23.57469],[52.124889,23.57572],[52.125641,23.577629],[52.12632,23.580099],[52.128811,23.59057],[52.135269,23.61853],[52.136452,23.62384],[52.137909,23.62999],[52.139091,23.63512],[52.140079,23.63932],[52.143768,23.6551],[52.148842,23.67742],[52.150139,23.68292],[52.15052,23.68453],[52.15115,23.687281],[52.151402,23.68865],[52.151531,23.68964],[52.151569,23.69029],[52.151539,23.6905],[52.151482,23.69071],[52.151371,23.69096],[52.151291,23.69117],[52.151199,23.691401],[52.15115,23.69166],[52.15118,23.69203],[52.15126,23.69227],[52.151371,23.69243],[52.15147,23.69253],[52.151539,23.69256],[52.151619,23.692869],[52.151661,23.69306],[52.151661,23.693319],[52.151409,23.69803],[52.15023,23.716619],[52.149399,23.72999],[52.149052,23.73517],[52.148842,23.736971],[52.148689,23.73807],[52.14843,23.739651],[52.147911,23.741989],[52.14674,23.74641],[52.145618,23.750441],[52.14502,23.75275],[52.143379,23.758739],[52.140732,23.768591],[52.13792,23.778919],[52.134338,23.792219],[52.133091,23.796761],[52.13205,23.80051],[52.131889,23.80109],[52.131039,23.803761],[52.13002,23.807489],[52.12822,23.81422],[52.127369,23.81785],[52.125999,23.823071],[52.125622,23.824289],[52.125111,23.82625],[52.124451,23.82873],[52.123501,23.83223],[52.122688,23.83518],[52.119701,23.846319],[52.119282,23.84778],[52.11903,23.84841],[52.118832,23.848749],[52.11869,23.84897],[52.118542,23.84914],[52.117519,23.849951],[52.115879,23.85117],[52.1157,23.85137],[52.11554,23.85165],[52.115459,23.85203],[52.11549,23.852341],[52.11557,23.852631],[52.115791,23.85289],[52.116161,23.85309],[52.11647,23.85318],[52.116699,23.85335],[52.116909,23.853609],[52.11705,23.85391],[52.117249,23.85433],[52.117489,23.85548],[52.118221,23.859249],[52.119019,23.863449],[52.120411,23.870689],[52.122372,23.880699],[52.123039,23.88419],[52.12328,23.88542],[52.123749,23.887831],[52.124321,23.89076],[52.124779,23.893221],[52.125229,23.895611],[52.125561,23.897301],[52.126678,23.902849],[52.127029,23.904711],[52.128262,23.91103],[52.129269,23.91626],[52.132622,23.933611],[52.13448,23.94289],[52.136089,23.951241],[52.136509,23.953409],[52.142052,23.98245],[52.146332,24.00466],[52.150719,24.02721],[52.15287,24.038589],[52.153019,24.03994],[52.153469,24.04154],[52.156288,24.056391],[52.156681,24.058439],[52.161079,24.08123],[52.162399,24.089331],[52.174301,24.15033],[52.17466,24.152189],[52.174889,24.153469],[52.175442,24.15617],[52.18956,24.230101],[52.196079,24.264339],[52.199089,24.28031],[52.19923,24.281],[52.19944,24.282619],[52.199551,24.28367],[52.199581,24.284281],[52.199612,24.284599],[52.19965,24.28643],[52.199619,24.288059],[52.19957,24.28903],[52.199471,24.290131],[52.19928,24.291771],[52.199009,24.293159],[52.198792,24.29434],[52.198509,24.29549],[52.197891,24.297371],[52.197289,24.29891],[52.196892,24.29986],[52.196411,24.300791],[52.195591,24.302271],[52.188881,24.313999],[52.183769,24.323021],[52.183262,24.324051],[52.182659,24.32563],[52.181591,24.328341],[52.181141,24.32947],[52.179619,24.33334],[52.178951,24.33515],[52.178391,24.337999],[52.178268,24.339239],[52.17823,24.340731],[52.17831,24.34374],[52.179089,24.34906],[52.183552,24.378071],[52.183861,24.38007],[52.18441,24.38382],[52.18655,24.39747],[52.186989,24.399099],[52.187328,24.400299],[52.187931,24.40176],[52.18853,24.40288],[52.189732,24.40468],[52.20063,24.41729],[52.20261,24.4191],[52.204411,24.42038],[52.206039,24.42116],[52.211021,24.422621],[52.212681,24.42293],[52.214001,24.42318],[52.215591,24.42333],[52.217979,24.423161],[52.2192,24.42297],[52.22105,24.422831],[52.222321,24.42293],[52.22385,24.423321],[52.225868,24.42404],[52.228271,24.425619],[52.230419,24.427509],[52.231529,24.428801],[52.232738,24.430429],[52.233681,24.43189],[52.235142,24.434719],[52.23634,24.437719],[52.241661,24.452061],[52.242008,24.453091],[52.253422,24.4839],[52.26458,24.51351],[52.268871,24.525961],[52.269901,24.529051],[52.271702,24.53377],[52.28355,24.560369],[52.285519,24.564409],[52.287491,24.567841],[52.292042,24.574789],[52.306461,24.59617],[52.30748,24.59763],[52.30904,24.599939],[52.319759,24.616079],[52.32431,24.622601],[52.330669,24.632299],[52.33255,24.635481],[52.335209,24.64028],[52.337109,24.64397],[52.342079,24.654699],[52.343632,24.65839],[52.345772,24.66363],[52.349812,24.673929],[52.350559,24.676041],[52.35154,24.67881],[52.353062,24.68375],[52.354408,24.688789],[52.357021,24.69972],[52.35873,24.707319],[52.362679,24.72423],[52.363628,24.72757],[52.364658,24.730659],[52.367229,24.736759],[52.368778,24.739759],[52.373501,24.74791],[52.38131,24.761391],[52.383621,24.765249],[52.388451,24.773621],[52.38855,24.77379],[52.39101,24.77809],[52.393539,24.78227],[52.3965,24.78685],[52.41954,24.822229],[52.422569,24.827021],[52.424461,24.830351],[52.426479,24.834499],[52.427849,24.83754],[52.429131,24.840481],[52.430511,24.84441],[52.4314,24.8477],[52.441212,24.883829],[52.44294,24.88942],[52.443958,24.89241],[52.445389,24.896049],[52.44688,24.89949],[52.448021,24.90184],[52.449162,24.904119],[52.451,24.907551],[52.453011,24.910851],[52.455921,24.9151],[52.461411,24.922119],[52.467789,24.93049],[52.470421,24.934071],[52.473919,24.93903],[52.476212,24.942381],[52.479328,24.947491],[52.482948,24.95442],[52.48391,24.956329],[52.48698,24.96279],[52.48798,24.964991],[52.48925,24.967751],[52.490189,24.96986],[52.492401,24.97484],[52.492649,24.975401],[52.49403,24.978621],[52.49469,24.980169],[52.496922,24.98489],[52.498718,24.988501],[52.519588,25.0278],[52.520592,25.02973],[52.521301,25.031099],[52.52507,25.03837],[52.527649,25.04274],[52.52961,25.0455],[52.53075,25.046949],[52.53273,25.04933],[52.534431,25.051411],[52.5364,25.053301],[52.539749,25.056129],[52.541809,25.05759],[52.545658,25.059971],[52.547218,25.06094],[52.54744,25.061069],[52.549191,25.062229],[52.55151,25.064199],[52.551819,25.064489],[52.553219,25.06583],[52.553829,25.066351],[52.555779,25.068609],[52.558262,25.0716],[52.560169,25.07407],[52.561642,25.076389],[52.563782,25.07999],[52.56601,25.084459],[52.567131,25.08695],[52.568508,25.090639],[52.572731,25.10277],[52.57513,25.109541],[52.57803,25.11776],[52.579449,25.12146],[52.580349,25.1236],[52.582748,25.128571],[52.585499,25.1339],[52.587391,25.13707],[52.603531,25.16132],[52.60696,25.16728],[52.619831,25.19175],[52.62933,25.20981],[52.638729,25.2279],[52.642921,25.235781],[52.646118,25.24214],[52.648548,25.247339],[52.650021,25.250879],[52.65147,25.254431],[52.655708,25.26573],[52.657131,25.26956],[52.663799,25.28743],[52.670471,25.305389],[52.67519,25.317829],[52.676392,25.32058],[52.677589,25.323071],[52.678539,25.324949],[52.685322,25.33684],[52.686031,25.338091],[52.686932,25.33967],[52.690979,25.34693],[52.694809,25.35368],[52.696079,25.356079],[52.69733,25.35858],[52.698761,25.36157],[52.6996,25.363581],[52.701019,25.366541],[52.701279,25.3671],[52.705292,25.375839],[52.7066,25.37879],[52.70787,25.38176],[52.708672,25.383801],[52.709251,25.385441],[52.709419,25.38592],[52.709709,25.38682],[52.710079,25.388],[52.711231,25.392071],[52.716991,25.4137],[52.7183,25.418739],[52.720131,25.42551],[52.721111,25.428499],[52.739941,25.479],[52.741951,25.48362],[52.744061,25.487761],[52.746841,25.49316],[52.751289,25.501659],[52.755569,25.509899],[52.759911,25.518129],[52.764179,25.526369],[52.766369,25.530569],[52.768459,25.534611],[52.771091,25.53908],[52.77211,25.540621],[52.774021,25.54327],[52.775429,25.545059],[52.776859,25.546721],[52.779099,25.549101],[52.782619,25.552271],[52.783932,25.5534],[52.792992,25.56155],[52.80965,25.57682],[52.814861,25.581841],[52.819981,25.586889],[52.82056,25.58742],[52.823421,25.59034],[52.82497,25.59215],[52.82642,25.59403],[52.827709,25.59584],[52.829689,25.59893],[52.831699,25.6026],[52.848228,25.63558],[52.84856,25.636141],[52.851398,25.64073],[52.85294,25.64296],[52.854359,25.64463],[52.85601,25.64657],[52.856602,25.647209],[52.85952,25.65036],[52.862049,25.652399],[52.86385,25.65369],[52.87775,25.66201],[52.87981,25.66321],[52.909302,25.680429],[52.915451,25.684071],[52.91869,25.686131],[52.92049,25.68742],[52.922901,25.68939],[52.924961,25.69128],[52.942982,25.70956],[52.96899,25.73591],[52.97192,25.73875],[52.972931,25.73988],[52.974899,25.741449],[52.977322,25.743719],[52.979759,25.74596],[52.99173,25.756599],[52.995258,25.760201],[53.016541,25.78355],[53.019798,25.787149],[53.022121,25.7899],[53.023918,25.792471],[53.025719,25.795219],[53.027699,25.798651],[53.0289,25.80097],[53.03817,25.820801],[53.04126,25.827749],[53.04269,25.8312],[53.046341,25.83993],[53.048012,25.843889],[53.050179,25.84898],[53.05201,25.85334],[53.052311,25.85404],[53.05312,25.85597],[53.053879,25.857531],[53.05418,25.85813],[53.05508,25.85981],[53.055511,25.86055],[53.055969,25.861361],[53.057049,25.86311],[53.05798,25.8645],[53.058998,25.865959],[53.062111,25.870159],[53.065109,25.8743],[53.066399,25.87586],[53.067471,25.877171],[53.068508,25.878229],[53.07008,25.87978],[53.071529,25.88101],[53.072281,25.88184],[53.073898,25.88307],[53.075279,25.88385],[53.077129,25.88483],[53.079182,25.88578],[53.080479,25.8862],[53.083389,25.88695],[53.085979,25.8874],[53.087601,25.88747],[53.089241,25.8874],[53.09404,25.886721],[53.0961,25.886629],[53.096451,25.886629],[53.09988,25.88706],[53.102112,25.887569],[53.103748,25.88818],[53.105808,25.88912],[53.108028,25.89032],[53.112411,25.89315],[53.115761,25.895639],[53.119362,25.898821],[53.121681,25.90131],[53.123829,25.903879],[53.126228,25.907141],[53.132069,25.916241],[53.13332,25.918301],[53.13414,25.91993],[53.134918,25.92161],[53.135571,25.92318],[53.1362,25.92485],[53.13686,25.926741],[53.137531,25.92907],[53.13768,25.929621],[53.138199,25.93149],[53.143181,25.94968],[53.14468,25.955219],[53.145969,25.959669],[53.147171,25.96319],[53.148121,25.96542],[53.149151,25.967569],[53.150089,25.96937],[53.151649,25.971849],[53.15337,25.974279],[53.155159,25.97641],[53.157219,25.97847],[53.15992,25.981119],[53.1605,25.98172],[53.161949,25.983271],[53.162571,25.983999],[53.163448,25.985069],[53.16431,25.986231],[53.164928,25.98716],[53.165539,25.988171],[53.166439,25.989811],[53.167469,25.99184],[53.168159,25.993349],[53.169361,25.996111],[53.170769,25.99935],[53.172871,26.004181],[53.17337,26.005409],[53.17395,26.006849],[53.17477,26.00901],[53.175369,26.010719],[53.176022,26.012739],[53.177299,26.01713],[53.178398,26.020969],[53.17889,26.022751],[53.17992,26.02721],[53.18042,26.03027],[53.180641,26.031981],[53.180962,26.03536],[53.18111,26.03808],[53.18124,26.04175],[53.181339,26.044069],[53.181412,26.045179],[53.181511,26.04649],[53.181641,26.047819],[53.181862,26.049601],[53.182152,26.0516],[53.18261,26.05405],[53.183041,26.056061],[53.183689,26.05863],[53.184799,26.06218],[53.185841,26.06506],[53.186329,26.06621],[53.18679,26.067221],[53.18766,26.06904],[53.190399,26.073931],[53.191769,26.076349],[53.19278,26.078159],[53.193851,26.08016],[53.194691,26.08189],[53.195339,26.08326],[53.199032,26.09133],[53.202541,26.098961],[53.205929,26.106091],[53.20739,26.10952],[53.208809,26.113569],[53.2094,26.115471],[53.210152,26.118019],[53.21088,26.120831],[53.211411,26.12294],[53.214512,26.135269],[53.21537,26.138359],[53.216911,26.14283],[53.218201,26.146351],[53.220181,26.150721],[53.221458,26.15321],[53.222752,26.155701],[53.225071,26.159559],[53.231251,26.16943],[53.233479,26.17347],[53.235538,26.177759],[53.238289,26.184879],[53.25219,26.22514],[53.252789,26.2272],[53.254162,26.231581],[53.256481,26.24033],[53.265919,26.283159],[53.266911,26.28706],[53.26712,26.28784],[53.267841,26.290371],[53.268761,26.293369],[53.26973,26.29624],[53.270748,26.29887],[53.271671,26.301069],[53.27219,26.302299],[53.284641,26.32745],[53.286011,26.33037],[53.287338,26.33342],[53.289612,26.33955],[53.298111,26.368389],[53.2994,26.37191],[53.300369,26.374399],[53.301029,26.37586],[53.303261,26.380489],[53.304722,26.38315],[53.306862,26.386669],[53.32317,26.41036],[53.327122,26.41663],[53.333561,26.42787],[53.34557,26.44907],[53.353561,26.46315],[53.36377,26.481091],[53.38026,26.5079],[53.382992,26.512329],[53.384769,26.51553],[53.385658,26.51713],[53.388828,26.52306],[53.403172,26.549919],[53.410461,26.5634],[53.41235,26.56649],[53.413979,26.56889],[53.416801,26.57254],[53.419128,26.575069],[53.421341,26.57732],[53.42445,26.57979],[53.444881,26.594299],[53.445061,26.594469],[53.448471,26.597139],[53.450371,26.598591],[53.454659,26.60228],[53.47768,26.625601],[53.478031,26.62594],[53.478981,26.626881],[53.485222,26.633181],[53.488049,26.63652],[53.489861,26.63876],[53.492352,26.642191],[53.494888,26.646099],[53.508911,26.67008],[53.509418,26.67103],[53.511311,26.674629],[53.512939,26.678129],[53.514229,26.68124],[53.515598,26.68502],[53.51675,26.68894],[53.52256,26.710939],[53.525829,26.724689],[53.52702,26.72982],[53.528221,26.73597],[53.52869,26.738371],[53.529221,26.74115],[53.529961,26.745029],[53.530151,26.745899],[53.532902,26.76289],[53.533401,26.76598],[53.535519,26.779091],[53.536121,26.78458],[53.536461,26.789391],[53.53664,26.79497],[53.53664,26.7978],[53.536251,26.805441],[53.53595,26.80879],[53.535339,26.813669],[53.534401,26.819],[53.534229,26.819771],[53.530708,26.83737],[53.530209,26.83996],[53.52985,26.8426],[53.52951,26.84527],[53.529251,26.849039],[53.529171,26.852131],[53.529289,26.856291],[53.529591,26.86054],[53.530048,26.86355],[53.530369,26.86561],[53.53059,26.86692],[53.531738,26.872299],[53.536381,26.8929],[53.538391,26.90213],[53.543839,26.9268],[53.551048,26.95891],[53.551739,26.961479],[53.552341,26.963369],[53.55397,26.96689],[53.556889,26.9729],[53.569759,26.99976],[53.584961,27.03109],[53.588219,27.037609],[53.58942,27.03907],[53.590111,27.039761],[53.59095,27.040529],[53.592159,27.04105],[53.595341,27.04215],[53.595509,27.04221],[53.598179,27.043249],[53.60865,27.047779],[53.61459,27.050211],[53.619888,27.05237],[53.625561,27.05632],[53.642429,27.06823],[53.649181,27.073],[53.650631,27.074301],[53.651821,27.07575],[53.652611,27.076799],[53.654018,27.0788],[53.655418,27.08147],[53.656712,27.08456],[53.65757,27.087391],[53.65834,27.090401],[53.659031,27.095289],[53.659199,27.097521],[53.65937,27.11211],[53.659458,27.11709],[53.65971,27.12756],[53.660141,27.132629],[53.661091,27.137951],[53.661598,27.14044],[53.663151,27.14567],[53.666531,27.155149],[53.674389,27.17734],[53.675251,27.1798],[53.675869,27.182501],[53.676491,27.18531],[53.67712,27.189251],[53.677551,27.19454],[53.67757,27.19717],[53.677399,27.20146],[53.676708,27.20841],[53.676109,27.216311],[53.675758,27.223089],[53.675591,27.230471],[53.675758,27.243179],[53.676022,27.247549],[53.676449,27.25416],[53.676971,27.26008],[53.678001,27.267981],[53.679451,27.277531],[53.685551,27.31776],[53.686409,27.32394],[53.688721,27.340521],[53.691151,27.358589],[53.691441,27.36087],[53.694908,27.38806],[53.697571,27.409691],[53.698601,27.415951],[53.699711,27.42239],[53.701248,27.42951],[53.702412,27.434111],[53.703892,27.439819],[53.709179,27.45775],[53.709728,27.459539],[53.710258,27.461411],[53.723,27.503969],[53.723629,27.506109],[53.72496,27.51058],[53.72691,27.517099],[53.727348,27.51852],[53.72789,27.520281],[53.729149,27.52442],[53.729729,27.526529],[53.730129,27.528099],[53.73082,27.53133],[53.731548,27.534981],[53.73214,27.53829],[53.732651,27.54188],[53.733139,27.54612],[53.734119,27.55578],[53.736309,27.57708],[53.73687,27.58239],[53.737789,27.5914],[53.738548,27.59878],[53.739639,27.609711],[53.740021,27.61257],[53.740139,27.613449],[53.740749,27.61706],[53.741371,27.620041],[53.742371,27.62392],[53.743832,27.628731],[53.745338,27.632971],[53.746071,27.634689],[53.746868,27.6364],[53.747452,27.637609],[53.748058,27.63879],[53.749298,27.641029],[53.751671,27.64571],[53.752972,27.64875],[53.754261,27.65201],[53.75613,27.657351],[53.75626,27.657721],[53.756908,27.659731],[53.757381,27.6609],[53.7579,27.66235],[53.75832,27.663469],[53.759029,27.665319],[53.759819,27.66711],[53.7607,27.669029],[53.76162,27.67108],[53.762192,27.67214],[53.762901,27.673441],[53.78426,27.712919],[53.786491,27.71736],[53.78846,27.721979],[53.790089,27.726471],[53.79097,27.72916],[53.791382,27.73045],[53.79229,27.733801],[53.793221,27.73777],[53.793499,27.73922],[53.793591,27.739651],[53.793678,27.740191],[53.797211,27.759199],[53.797871,27.76277],[53.79966,27.77269],[53.799881,27.773951],[53.80064,27.778521],[53.802368,27.786659],[53.803139,27.78932],[53.804249,27.793011],[53.80431,27.79318],[53.804878,27.794809],[53.805222,27.795771],[53.80621,27.798479],[53.807301,27.801189],[53.807899,27.80257],[53.80859,27.80405],[53.809689,27.806351],[53.811291,27.80949],[53.813919,27.81415],[53.814121,27.81451],[53.81707,27.81988],[53.81773,27.82114],[53.825401,27.835051],[53.829479,27.842819],[53.833488,27.85062],[53.84153,27.866261],[53.84193,27.86705],[53.843239,27.86961],[53.843891,27.87084],[53.84454,27.872101],[53.845829,27.87459],[53.848412,27.879601],[53.849861,27.882389],[53.85133,27.885229],[53.854252,27.89086],[53.8601,27.902121],[53.861439,27.90472],[53.861599,27.90501],[53.861832,27.90547],[53.863529,27.90876],[53.867081,27.915569],[53.868511,27.91836],[53.86998,27.92103],[53.871288,27.923189],[53.87262,27.925261],[53.874321,27.92758],[53.87606,27.929779],[53.87867,27.93269],[53.878841,27.93284],[53.879501,27.933479],[53.88142,27.93531],[53.88348,27.936951],[53.885021,27.938061],[53.88905,27.94046],[53.891708,27.941771],[53.900379,27.94578],[53.90905,27.949909],[53.92561,27.957621],[53.929649,27.95952],[53.93251,27.960819],[53.935322,27.962351],[53.9361,27.96287],[53.93803,27.96422],[53.939861,27.96578],[53.943039,27.96896],[53.945961,27.972651],[53.946449,27.9734],[53.948139,27.976049],[53.948669,27.97698],[53.949188,27.97789],[53.949478,27.978399],[53.951279,27.98192],[53.952648,27.98527],[53.954319,27.98984],[53.955662,27.99394],[53.963131,28.020201],[53.967251,28.03454],[53.97094,28.047319],[53.973339,28.05479],[53.979519,28.07144],[53.98209,28.078051],[53.98476,28.08552],[53.986301,28.09041],[53.9869,28.09239],[53.98888,28.09968],[53.989651,28.103109],[53.992908,28.116159],[53.995659,28.12775],[53.99601,28.129181],[53.997028,28.13341],[53.998138,28.137791],[54.000198,28.144911],[54.001411,28.148689],[54.003471,28.154779],[54.005531,28.16062],[54.007931,28.167139],[54.009392,28.17161],[54.01128,28.17779],[54.011459,28.178431],[54.012642,28.18281],[54.013149,28.18469],[54.01342,28.18568],[54.014881,28.19212],[54.015739,28.19615],[54.01757,28.206301],[54.01849,28.21307],[54.019348,28.22019],[54.020149,28.22949],[54.020199,28.23004],[54.02026,28.230841],[54.025688,28.30113],[54.02647,28.30962],[54.026981,28.313141],[54.02906,28.32885],[54.03334,28.357349],[54.033852,28.36507],[54.035309,28.373911],[54.035309,28.374081],[54.037109,28.38241],[54.039768,28.39279],[54.041309,28.398251],[54.045609,28.413481],[54.04776,28.420601],[54.049469,28.425579],[54.050381,28.427641],[54.052132,28.431589],[54.054089,28.435329],[54.058441,28.443689],[54.062519,28.4515],[54.06673,28.458969],[54.068951,28.46274],[54.07069,28.465349],[54.07119,28.466089],[54.075909,28.47262],[54.08123,28.47879],[54.083618,28.481319],[54.090328,28.488411],[54.119419,28.518909],[54.120449,28.519991],[54.123631,28.523769],[54.132729,28.535789],[54.137619,28.54188],[54.141651,28.546431],[54.14526,28.550119],[54.148689,28.553471],[54.153591,28.55793],[54.157619,28.56119],[54.166599,28.56822],[54.172371,28.572741],[54.174809,28.574551],[54.177021,28.576191],[54.179588,28.5781],[54.183971,28.581619],[54.18663,28.58419],[54.194271,28.59235],[54.194778,28.592859],[54.207661,28.60651],[54.209042,28.60816],[54.211609,28.611231],[54.213921,28.614321],[54.217701,28.61964],[54.225941,28.632429],[54.237782,28.650801],[54.239159,28.652691],[54.242161,28.65612],[54.245602,28.65913],[54.24791,28.660931],[54.250912,28.662531],[54.251759,28.662979],[54.257092,28.665819],[54.258808,28.666759],[54.25959,28.66728],[54.260441,28.668051],[54.261471,28.669081],[54.262852,28.670799],[54.264141,28.672859],[54.265079,28.67457],[54.266201,28.677059],[54.266911,28.679251],[54.267231,28.680241],[54.268341,28.685101],[54.269032,28.688141],[54.26947,28.691031],[54.269539,28.691481],[54.269588,28.691971],[54.270061,28.69663],[54.270061,28.7071],[54.270111,28.708799],[54.27026,28.710541],[54.270401,28.711769],[54.270569,28.712681],[54.270908,28.71414],[54.271351,28.715691],[54.27232,28.718201],[54.272541,28.718781],[54.282761,28.738779],[54.28997,28.752939],[54.291,28.755939],[54.291599,28.758169],[54.291859,28.761259],[54.291931,28.763109],[54.29155,28.77039],[54.29108,28.780661],[54.29015,28.800529],[54.289959,28.804581],[54.289879,28.806379],[54.289688,28.810459],[54.289631,28.811729],[54.28904,28.8241],[54.288971,28.826241],[54.288971,28.82822],[54.289219,28.83215],[54.290699,28.85079],[54.291061,28.86319],[54.291309,28.87359],[54.29155,28.876591],[54.292801,28.884689],[54.295979,28.904261],[54.297779,28.916269],[54.29821,28.919451],[54.29855,28.923229],[54.300251,28.947069],[54.30027,28.948721],[54.300468,28.950411],[54.301041,28.95756],[54.301842,28.969],[54.301991,28.97043],[54.30262,28.97678],[54.30302,28.979361],[54.30756,29.00271],[54.308418,29.007339],[54.30928,29.01326],[54.31057,29.022791],[54.3116,29.029831],[54.31271,29.036091],[54.31366,29.04081],[54.31572,29.04871],[54.318378,29.056259],[54.331249,29.092911],[54.334259,29.099689],[54.3358,29.10261],[54.336319,29.10347],[54.339409,29.10836],[54.345329,29.11635],[54.347988,29.120119],[54.349541,29.12261],[54.35194,29.127251],[54.35434,29.13282],[54.355801,29.1366],[54.362148,29.155661],[54.362839,29.15814],[54.364391,29.16415],[54.364811,29.166031],[54.36499,29.167061],[54.36573,29.171209],[54.366531,29.17643],[54.370911,29.20389],[54.371681,29.209299],[54.3722,29.21393],[54.37244,29.217501],[54.372532,29.220209],[54.37252,29.22753],[54.371471,29.281111],[54.371391,29.285179],[54.371319,29.28879],[54.37125,29.291611],[54.37133,29.29336],[54.371422,29.295219],[54.37159,29.297819],[54.371891,29.300289],[54.37254,29.304399],[54.37331,29.30826],[54.374168,29.3111],[54.374729,29.312901],[54.375938,29.316811],[54.377258,29.321051],[54.377522,29.32234],[54.378811,29.3274],[54.379921,29.332979],[54.380428,29.336161],[54.380871,29.338989],[54.384121,29.36319],[54.38438,29.36491],[54.385578,29.37075],[54.39082,29.39521],[54.395538,29.417101],[54.396999,29.42594],[54.397598,29.42997],[54.400002,29.45031],[54.400139,29.4513],[54.401031,29.457689],[54.401981,29.46336],[54.403011,29.46817],[54.406269,29.48439],[54.40765,29.49065],[54.408932,29.49555],[54.409962,29.49881],[54.412708,29.506189],[54.419231,29.52121],[54.419899,29.523069],[54.421791,29.52866],[54.42292,29.532749],[54.424809,29.541121],[54.4291,29.5606],[54.430389,29.56739],[54.431252,29.57262],[54.43219,29.579491],[54.433311,29.588181],[54.433491,29.589689],[54.434528,29.596939],[54.435322,29.60264],[54.435619,29.60507],[54.436909,29.61408],[54.43708,29.615191],[54.437241,29.616381],[54.437531,29.618191],[54.438141,29.621481],[54.43848,29.623091],[54.43895,29.62516],[54.439571,29.627609],[54.439899,29.62882],[54.4403,29.63028],[54.44136,29.63376],[54.442451,29.63719],[54.444641,29.644039],[54.447151,29.652069],[54.447788,29.654169],[54.448349,29.655951],[54.449291,29.65892],[54.450218,29.66189],[54.451248,29.665831],[54.456188,29.687019],[54.45718,29.69128],[54.457722,29.693911],[54.458038,29.695749],[54.458679,29.69985],[54.45927,29.704639],[54.459541,29.70756],[54.460072,29.71306],[54.460258,29.715099],[54.461971,29.735531],[54.462318,29.738621],[54.46262,29.74155],[54.463428,29.746429],[54.46386,29.74917],[54.464981,29.754169],[54.46627,29.759899],[54.474419,29.79578],[54.47678,29.806629],[54.477001,29.807631],[54.477772,29.81303],[54.478512,29.819361],[54.479141,29.824711],[54.479389,29.829189],[54.479401,29.832861],[54.479401,29.835779],[54.479221,29.838869],[54.47897,29.84136],[54.478539,29.84436],[54.4776,29.84943],[54.476601,29.85458],[54.47485,29.86367],[54.474331,29.86685],[54.47393,29.870871],[54.47348,29.876631],[54.473301,29.882641],[54.473301,29.88702],[54.473549,29.892269],[54.473911,29.89637],[54.474331,29.90015],[54.475101,29.905821],[54.47588,29.911261],[54.476009,29.91217],[54.476131,29.912979],[54.477509,29.921949],[54.481918,29.952721],[54.482849,29.95892],[54.484451,29.969681],[54.485748,29.978769],[54.491371,30.01828],[54.492378,30.02508],[54.492661,30.02648],[54.493229,30.02866],[54.4939,30.03088],[54.498699,30.047119],[54.49884,30.047621],[54.49926,30.049259],[54.499592,30.051069],[54.49976,30.052429],[54.500011,30.055189],[54.500301,30.060289],[54.501331,30.07649],[54.501949,30.08609],[54.50198,30.087179],[54.502239,30.089689],[54.502361,30.090799],[54.50425,30.10475],[54.504608,30.107281],[54.506271,30.11908],[54.50687,30.12211],[54.50737,30.12393],[54.507919,30.125839],[54.508739,30.128019],[54.51511,30.1404],[54.518089,30.14632],[54.52309,30.15601],[54.538921,30.187611],[54.542049,30.193951],[54.542679,30.195641],[54.543171,30.19755],[54.543339,30.19824],[54.543598,30.19936],[54.546089,30.2173],[54.54718,30.225519],[54.547581,30.228439],[54.547989,30.23138],[54.548382,30.23432],[54.549858,30.244499],[54.553299,30.269739],[54.553471,30.27051],[54.55373,30.271799],[54.554161,30.273689],[54.55484,30.27557],[54.555531,30.277031],[54.56171,30.28862],[54.56274,30.29068],[54.563511,30.29283],[54.564201,30.29463],[54.570549,30.314199],[54.57132,30.31609],[54.572262,30.31806],[54.575699,30.32493],[54.576469,30.32621],[54.577251,30.32733],[54.590641,30.34347],[54.5914,30.344391],[54.59483,30.34856],[54.599911,30.35471],[54.600761,30.355829],[54.60162,30.357109],[54.602482,30.35874],[54.603939,30.36286],[54.6096,30.379601],[54.618641,30.405649],[54.619301,30.407579],[54.619732,30.40913],[54.620029,30.41082],[54.620369,30.41293],[54.62162,30.424231],[54.62302,30.435459],[54.623508,30.438999],[54.623852,30.44174],[54.624538,30.446289],[54.62994,30.48938],[54.632351,30.508261],[54.635349,30.53229],[54.638962,30.56225],[54.641529,30.583191],[54.642479,30.591089],[54.64325,30.59547],[54.652691,30.63521],[54.656288,30.650311],[54.65913,30.66264],[54.669769,30.70816],[54.672771,30.720779],[54.675861,30.738199],[54.683159,30.780769],[54.683159,30.78112],[54.68359,30.785839],[54.685989,30.830641],[54.686119,30.8328],[54.68737,30.854071],[54.689079,30.883511],[54.689362,30.889811],[54.68943,30.891411],[54.689861,30.926941],[54.68993,30.93252],[54.690369,30.968229],[54.690708,30.981791],[54.690842,30.992599],[54.69091,30.99811],[54.690929,30.999861],[54.69099,31.000401],[54.69099,31.000641],[54.690948,31.00079],[54.690971,31.001591],[54.691109,31.014879],[54.69112,31.0201],[54.689701,31.05283],[54.689949,31.06406],[54.69099,31.07468],[54.70348,31.20154],[54.709801,31.244169],[54.710098,31.24548],[54.72105,31.283421],[54.722359,31.28828],[54.72567,31.30747],[54.729439,31.33021],[54.730431,31.336189],[54.735111,31.35618],[54.738861,31.372881],[54.742531,31.41223],[54.744179,31.42782],[54.749039,31.478109],[54.74955,31.48155],[54.751961,31.488119],[54.771992,31.53681],[54.786671,31.57107],[54.791,31.578859],[54.792702,31.58213],[54.794479,31.58531],[54.795181,31.58655],[54.79652,31.589029],[54.802349,31.599859],[54.80621,31.60693],[54.80685,31.60828],[54.807449,31.610001],[54.80798,31.612209],[54.810699,31.62418],[54.81295,31.63438],[54.81358,31.63641],[54.814232,31.63796],[54.81496,31.639339],[54.815788,31.640591],[54.83802,31.663321],[54.841209,31.666731],[54.842098,31.66818],[54.842949,31.67001],[54.843651,31.6724],[54.84396,31.67371],[54.844181,31.675091],[54.844349,31.677031],[54.84444,31.679331],[54.84465,31.68441],[54.846569,31.740999],[54.849239,31.8048],[54.850559,31.838461],[54.850788,31.844669],[54.851139,31.852501],[54.851139,31.854111],[54.8512,31.85553],[54.851311,31.857031],[54.85144,31.85841],[54.85149,31.85882],[54.851688,31.860241],[54.852032,31.861959],[54.859341,31.893641],[54.859699,31.89522],[54.860031,31.896851],[54.860298,31.89867],[54.860409,31.900021],[54.860729,31.907431],[54.863209,31.965019],[54.863461,31.97064],[54.86396,31.97884],[54.864151,31.98205],[54.865582,32.003571],[54.865761,32.00528],[54.86586,32.00592],[54.86607,32.007],[54.86644,32.00843],[54.870831,32.024979],[54.87233,32.030609],[54.878571,32.05394],[54.882,32.067009],[54.882839,32.070171],[54.883598,32.073101],[54.883839,32.074139],[54.88406,32.075291],[54.884701,32.07951],[54.88501,32.081261],[54.889851,32.10043],[54.89156,32.105839],[54.893639,32.111629],[54.894569,32.113979],[54.895279,32.115372],[54.896961,32.11755],[54.89856,32.11887],[54.908989,32.124649],[54.91114,32.12619],[54.912048,32.127312],[54.914181,32.130299],[54.92564,32.14669],[54.92709,32.14933],[54.93465,32.165771],[54.941029,32.179642],[54.942371,32.18211],[54.951599,32.195801],[54.955898,32.20388],[54.957008,32.205929],[54.984772,32.2495],[55.009338,32.288151],[55.014061,32.29557],[55.01635,32.299301],[55.017502,32.302029],[55.02364,32.323231],[55.028831,32.340839],[55.029331,32.342609],[55.029751,32.344479],[55.02998,32.34597],[55.030151,32.347591],[55.032341,32.372421],[55.033009,32.38018],[55.033112,32.381931],[55.033699,32.402451],[55.03381,32.404652],[55.033901,32.405529],[55.034019,32.4063],[55.03429,32.407921],[55.055199,32.499489],[55.055729,32.501888],[55.056099,32.504452],[55.056629,32.51738],[55.05714,32.530281],[55.05822,32.55682],[55.059029,32.576729],[55.059422,32.586262],[55.059818,32.595951],[55.059959,32.597309],[55.060169,32.598701],[55.060711,32.601089],[55.066109,32.62178],[55.072861,32.647812],[55.073879,32.65197],[55.076351,32.664532],[55.077229,32.66922],[55.078171,32.674419],[55.07835,32.676239],[55.078659,32.678799],[55.078911,32.681412],[55.079029,32.684189],[55.079021,32.687019],[55.07896,32.69241],[55.07901,32.69603],[55.07906,32.696899],[55.079109,32.697769],[55.07943,32.70303],[55.079578,32.70578],[55.07967,32.708408],[55.07967,32.7094],[55.079659,32.710388],[55.079651,32.712261],[55.079632,32.716011],[55.079201,32.743149],[55.079231,32.7444],[55.079319,32.745689],[55.080929,32.757801],[55.081959,32.764309],[55.085812,32.792412],[55.09552,32.86187],[55.100609,32.89822],[55.101082,32.90139],[55.103889,32.921909],[55.105289,32.931881],[55.107571,32.952911],[55.11404,33.01384],[55.11478,33.020802],[55.116661,33.038502],[55.118839,33.05909],[55.11903,33.06097],[55.120232,33.07328],[55.12038,33.074821],[55.122749,33.097221],[55.12476,33.11731],[55.127258,33.141972],[55.12812,33.150501],[55.128658,33.155849],[55.12941,33.164082],[55.129551,33.167191],[55.130001,33.171902],[55.130329,33.174858],[55.13203,33.194359],[55.132179,33.19561],[55.132408,33.196869],[55.13242,33.196911],[55.133831,33.202961],[55.134621,33.206329],[55.13612,33.212269],[55.136971,33.21603],[55.138378,33.226891],[55.13974,33.23716],[55.140041,33.239479],[55.140072,33.239712],[55.140381,33.242279],[55.141708,33.25333],[55.142391,33.260139],[55.142422,33.26049],[55.14365,33.273491],[55.14463,33.283451],[55.144981,33.286999],[55.145432,33.290569],[55.145931,33.294651],[55.1493,33.320049],[55.15123,33.334499],[55.152111,33.340832],[55.15263,33.344742],[55.15284,33.346119],[55.15303,33.347069],[55.153801,33.350552],[55.157761,33.367619],[55.162682,33.38887],[55.16927,33.417389],[55.174042,33.43829],[55.17432,33.439339],[55.177589,33.450409],[55.178169,33.452431],[55.178768,33.454479],[55.17944,33.456749],[55.181782,33.46479],[55.182529,33.467381],[55.18285,33.468639],[55.183102,33.469921],[55.183289,33.471249],[55.183418,33.472778],[55.18343,33.474361],[55.183338,33.481991],[55.183201,33.492451],[55.182751,33.514259],[55.18269,33.517471],[55.182621,33.521042],[55.18235,33.535782],[55.181499,33.586811],[55.181259,33.603691],[55.181171,33.605801],[55.18055,33.617359],[55.180248,33.624809],[55.179798,33.634941],[55.179279,33.646099],[55.17955,33.6507],[55.180851,33.665352],[55.181721,33.67519],[55.185951,33.722252],[55.186932,33.733372],[55.188869,33.755901],[55.19022,33.769772],[55.19437,33.816299],[55.197609,33.853371],[55.198872,33.86784],[55.19912,33.874069],[55.199169,33.87693],[55.199551,33.897419],[55.19949,33.902531],[55.19912,33.9081],[55.197571,33.918049],[55.19138,33.95414],[55.190868,33.95586],[55.190411,33.975052],[55.18998,33.992599],[55.18977,34.000889],[55.189209,34.021259],[55.188301,34.037731],[55.18737,34.057541],[55.187382,34.059479],[55.187531,34.061371],[55.203011,34.140369],[55.20351,34.14296],[55.203991,34.144909],[55.20462,34.14682],[55.20575,34.149281],[55.205898,34.14962],[55.210041,34.158669],[55.2104,34.159451],[55.21236,34.171219],[55.220131,34.21777],[55.22076,34.222012],[55.22147,34.232059],[55.221619,34.234131],[55.22179,34.235569],[55.22208,34.237122],[55.222641,34.239288],[55.227921,34.257561],[55.228619,34.259899],[55.231991,34.271622],[55.24136,34.306641],[55.241661,34.307739],[55.24202,34.309109],[55.242371,34.310398],[55.243389,34.314209],[55.2435,34.314339],[55.245979,34.323818],[55.249329,34.336559],[55.249599,34.337589],[55.260361,34.372532],[55.261391,34.375931],[55.2654,34.389042],[55.266911,34.393532],[55.269669,34.401371],[55.288132,34.453289],[55.294189,34.472851],[55.315491,34.531731],[55.32428,34.562809],[55.356602,34.639191],[55.362381,34.65646],[55.36401,34.661339],[55.366451,34.668381],[55.370159,34.677132],[55.37426,34.68692],[55.383419,34.70425],[55.389469,34.713871],[55.41082,34.76725],[55.418419,34.78442],[55.425541,34.80146],[55.433361,34.82016],[55.43346,34.8204],[55.446468,34.851879],[55.448391,34.856579],[55.45153,34.864239],[55.470219,34.909729],[55.487339,34.948181],[55.49308,34.976509],[55.496552,35.007629],[55.496891,35.010681],[55.497028,35.011959],[55.49752,35.01646],[55.49955,35.036381],[55.499592,35.036758],[55.503189,35.101479],[55.505718,35.117962],[55.505718,35.120701],[55.503521,35.144611],[55.499298,35.190571],[55.499981,35.215981],[55.49902,35.240929],[55.498859,35.24894],[55.491619,35.31348],[55.491409,35.35181],[55.491329,35.367901],[55.491421,35.397419],[55.49123,35.400509],[55.487518,35.416309],[55.48074,35.444111],[55.48024,35.446171],[55.474239,35.491421],[55.471531,35.511909],[55.470581,35.519581],[55.47044,35.52206],[55.470119,35.529282],[55.468689,35.557758],[55.466881,35.593349],[55.46558,35.618931],[55.464211,35.645908],[55.46402,35.649601],[55.462921,35.676449],[55.461948,35.701061],[55.465279,35.759811],[55.46529,35.761002],[55.465351,35.769691],[55.465382,35.77354],[55.464821,35.826988],[55.464802,35.828949],[55.464779,35.83086],[55.464771,35.8321],[55.464691,35.839359],[55.4646,35.847698],[55.46542,35.903252],[55.46558,35.913269],[55.465382,35.917561],[55.46402,35.94331],[55.45993,36.022961],[55.459179,36.03561],[55.457581,36.060638],[55.457581,36.06271],[55.457821,36.064789],[55.458118,36.066799],[55.458641,36.068619],[55.474209,36.110161],[55.474339,36.11058],[55.49065,36.16309],[55.494148,36.174358],[55.50119,36.207119],[55.50909,36.243801],[55.51041,36.24992],[55.510818,36.251862],[55.51379,36.26569],[55.522362,36.31168],[55.525181,36.326809],[55.525589,36.32901],[55.531239,36.359341],[55.535961,36.384621],[55.536018,36.384899],[55.536072,36.385201],[55.536709,36.388729],[55.538609,36.39875],[55.53883,36.39996],[55.539341,36.40274],[55.53973,36.404888],[55.540291,36.407959],[55.54216,36.417648],[55.54895,36.455029],[55.551121,36.483101],[55.55114,36.483269],[55.551151,36.483429],[55.55167,36.490059],[55.55621,36.54797],[55.556221,36.548161],[55.55801,36.571011],[55.55822,36.573589],[55.55896,36.582569],[55.564362,36.632759],[55.565071,36.639389],[55.56826,36.669849],[55.571011,36.695881],[55.571018,36.69603],[55.571079,36.69664],[55.571091,36.696739],[55.572319,36.708599],[55.572392,36.70932],[55.572491,36.710251],[55.573101,36.716228],[55.573471,36.719952],[55.575031,36.73521],[55.575729,36.74213],[55.576229,36.747021],[55.57666,36.751289],[55.578522,36.76976],[55.57893,36.773891],[55.581409,36.798882],[55.584068,36.824989],[55.587349,36.85857],[55.58794,36.864269],[55.588421,36.869068],[55.58881,36.872978],[55.589039,36.875259],[55.59066,36.891609],[55.591808,36.90316],[55.594059,36.925831],[55.595589,36.93972],[55.595779,36.941292],[55.59602,36.94323],[55.596539,36.94767],[55.59848,36.964432],[55.598991,36.96875],[55.60051,36.981628],[55.60228,36.996632],[55.602638,36.99966],[55.603119,37.004261],[55.603149,37.004681],[55.603199,37.0051],[55.603249,37.005459],[55.60331,37.005859],[55.603821,37.01012],[55.604,37.011539],[55.604519,37.015621],[55.60535,37.02277],[55.605911,37.02747],[55.609039,37.05463],[55.60976,37.061089],[55.610279,37.06546],[55.610531,37.06673],[55.611149,37.069778],[55.61121,37.070091],[55.612518,37.076752],[55.61248,37.077709],[55.613091,37.081009],[55.613289,37.081989],[55.61565,37.093441],[55.616119,37.09626],[55.616531,37.09869],[55.616909,37.101959],[55.62027,37.126701],[55.62133,37.13377],[55.622608,37.142799],[55.62299,37.14724],[55.623268,37.151451],[55.623901,37.161259],[55.624741,37.174],[55.625259,37.181801],[55.625439,37.184681],[55.62553,37.185589],[55.625839,37.188622],[55.626049,37.191921],[55.62619,37.19376],[55.626339,37.195271],[55.62648,37.196281],[55.626652,37.197441],[55.626869,37.198662],[55.627129,37.19978],[55.627392,37.200779],[55.627831,37.202209],[55.628361,37.203701],[55.628811,37.20483],[55.629269,37.205891],[55.629539,37.20652],[55.631119,37.209999],[55.63187,37.211639],[55.632359,37.212799],[55.633801,37.216019],[55.634998,37.21875],[55.635479,37.219841],[55.635929,37.22084],[55.636299,37.22168],[55.637501,37.2244],[55.63868,37.227039],[55.639858,37.229698],[55.64106,37.23241],[55.642269,37.23513],[55.64267,37.236141],[55.643509,37.238441],[55.64431,37.240719],[55.645939,37.245239],[55.646641,37.247131],[55.64769,37.250061],[55.648029,37.251019],[55.648281,37.251839],[55.648548,37.252762],[55.648689,37.253342],[55.649071,37.255032],[55.649429,37.25684],[55.650082,37.260521],[55.65052,37.262779],[55.651131,37.266102],[55.651451,37.26786],[55.652248,37.272171],[55.65284,37.275341],[55.653412,37.278389],[55.654259,37.28299],[55.655399,37.28931],[55.655602,37.29039],[55.655788,37.291409],[55.656269,37.293739],[55.656448,37.29435],[55.656658,37.295059],[55.657089,37.29631],[55.657379,37.296982],[55.657879,37.298019],[55.658489,37.299019],[55.65905,37.29977],[55.659611,37.300468],[55.66087,37.301861],[55.66206,37.303169],[55.662281,37.30341],[55.663811,37.30505],[55.664719,37.306],[55.665619,37.307011],[55.666908,37.308472],[55.66782,37.309441],[55.66853,37.310169],[55.669109,37.31081],[55.66951,37.311241],[55.670639,37.3125],[55.671421,37.31332],[55.67263,37.31464],[55.672989,37.315029],[55.67794,37.320431],[55.67857,37.321129],[55.679428,37.322071],[55.67984,37.322559],[55.680038,37.3228],[55.680191,37.322941],[55.683571,37.326599],[55.683819,37.32687],[55.685791,37.328991],[55.690022,37.333519],[55.693169,37.336971],[55.694759,37.338631],[55.69556,37.339531],[55.69595,37.34],[55.696331,37.340481],[55.696732,37.341011],[55.697109,37.341579],[55.697842,37.3428],[55.698311,37.34359],[55.698471,37.343861],[55.698639,37.344151],[55.698738,37.34433],[55.69949,37.34568],[55.69978,37.34621],[55.700371,37.34729],[55.701241,37.348869],[55.702839,37.351891],[55.703732,37.35355],[55.703949,37.353958],[55.704472,37.354939],[55.705002,37.3559],[55.705441,37.356682],[55.706081,37.357891],[55.706638,37.358891],[55.70705,37.35965],[55.70755,37.360569],[55.707878,37.36121],[55.708172,37.361801],[55.708382,37.36227],[55.70882,37.363319],[55.70911,37.36401],[55.709499,37.36504],[55.709728,37.36573],[55.70998,37.366482],[55.710281,37.367481],[55.710541,37.368431],[55.710812,37.36953],[55.71104,37.37059],[55.711269,37.3717],[55.711849,37.375118],[55.71209,37.376629],[55.71262,37.38015],[55.71286,37.381729],[55.712818,37.382339],[55.712799,37.382561],[55.712742,37.382771],[55.71244,37.38372],[55.712261,37.384258],[55.71199,37.38509],[55.711929,37.385281],[55.71167,37.386082],[55.71138,37.386688],[55.710949,37.387459],[55.710098,37.38821],[55.70993,37.388371],[55.709641,37.38863],[55.70837,37.39016],[55.707981,37.390572],[55.70681,37.392139],[55.70639,37.392712],[55.705299,37.394119],[55.704361,37.395302],[55.70406,37.39571],[55.702068,37.398418],[55.701469,37.399239],[55.700809,37.40015],[55.700291,37.400841],[55.699841,37.401459],[55.699261,37.40226],[55.698799,37.402901],[55.69754,37.404541],[55.693779,37.40976],[55.69265,37.41103],[55.692039,37.411659],[55.691422,37.412251],[55.690071,37.41328],[55.689751,37.413502],[55.689011,37.413952],[55.688309,37.41433],[55.687618,37.41465],[55.686611,37.41502],[55.686401,37.4151],[55.685848,37.41526],[55.685699,37.415272],[55.685081,37.415489],[55.684391,37.415779],[55.684059,37.415932],[55.683659,37.41613],[55.683281,37.41634],[55.68285,37.416599],[55.68243,37.41687],[55.68206,37.41713],[55.680611,37.418221],[55.67614,37.421558],[55.670879,37.425499],[55.669231,37.426739],[55.668152,37.427551],[55.66732,37.428162],[55.666191,37.429008],[55.66576,37.42934],[55.664509,37.430271],[55.664131,37.43058],[55.663528,37.431091],[55.66267,37.43187],[55.661491,37.432999],[55.66053,37.433929],[55.66013,37.434341],[55.659729,37.43478],[55.659309,37.435249],[55.659088,37.43549],[55.658169,37.436569],[55.656479,37.438549],[55.65451,37.440849],[55.65411,37.441319],[55.653751,37.44178],[55.652359,37.4436],[55.652111,37.44389],[55.65086,37.445358],[55.645191,37.451988],[55.643459,37.454021],[55.641281,37.45657],[55.639191,37.459019],[55.6385,37.459839],[55.637131,37.461441],[55.6366,37.462059],[55.635941,37.462818],[55.632431,37.466919],[55.631828,37.467621],[55.63158,37.467899],[55.630939,37.468651],[55.628601,37.471371],[55.627361,37.47282],[55.625629,37.474838],[55.620949,37.48032],[55.617222,37.48468],[55.6157,37.48645],[55.614529,37.48782],[55.61364,37.48885],[55.613361,37.489182],[55.611931,37.490841],[55.611519,37.491322],[55.610699,37.492279],[55.609539,37.493629],[55.608521,37.49482],[55.607571,37.49593],[55.60601,37.497749],[55.6035,37.500671],[55.60091,37.503681],[55.600288,37.504429],[55.599682,37.505211],[55.599121,37.505989],[55.59874,37.506592],[55.598339,37.507221],[55.59782,37.508129],[55.59745,37.508789],[55.597092,37.50948],[55.596691,37.510311],[55.596321,37.51115],[55.59586,37.512249],[55.595428,37.513359],[55.595081,37.51437],[55.594688,37.515591],[55.594349,37.516731],[55.59404,37.517948],[55.593811,37.518921],[55.592319,37.525131],[55.591541,37.528412],[55.59132,37.529339],[55.590912,37.53101],[55.59005,37.534599],[55.587421,37.545601],[55.587139,37.54678],[55.586491,37.549469],[55.584969,37.55584],[55.58287,37.564602],[55.582199,37.567421],[55.581779,37.56916],[55.580719,37.57357],[55.580261,37.57552],[55.579342,37.579361],[55.577278,37.58794],[55.577141,37.588551],[55.577,37.58918],[55.57687,37.589771],[55.576759,37.590408],[55.576641,37.591091],[55.576439,37.59227],[55.57634,37.592911],[55.576241,37.593521],[55.57616,37.594131],[55.576092,37.594742],[55.576019,37.59539],[55.57597,37.596008],[55.575932,37.59655],[55.57589,37.597099],[55.575809,37.598301],[55.575741,37.599659],[55.575611,37.601822],[55.575329,37.606709],[55.575241,37.608158],[55.574982,37.612598],[55.574921,37.613659],[55.574581,37.61935],[55.574409,37.62228],[55.573818,37.632408],[55.573681,37.63475],[55.573589,37.636292],[55.573471,37.638309],[55.57336,37.640308],[55.57325,37.64204],[55.57304,37.645771],[55.572929,37.647671],[55.57283,37.6492],[55.572639,37.652538],[55.572609,37.653061],[55.57254,37.654121],[55.572491,37.655071],[55.571991,37.6633],[55.57196,37.66394],[55.57193,37.664619],[55.571892,37.665298],[55.571869,37.665932],[55.571838,37.666599],[55.571831,37.667271],[55.571819,37.66795],[55.571819,37.66864],[55.571831,37.669312],[55.571861,37.669998],[55.57188,37.67067],[55.571918,37.671349],[55.571972,37.67202],[55.572029,37.672691],[55.57209,37.673359],[55.57217,37.67403],[55.57225,37.674702],[55.57233,37.675362],[55.572418,37.67601],[55.572529,37.67667],[55.57275,37.677952],[55.572861,37.678589],[55.573002,37.679241],[55.573139,37.679871],[55.573299,37.680489],[55.57346,37.68108],[55.573608,37.68166],[55.57375,37.68219],[55.573929,37.682758],[55.5741,37.683331],[55.57428,37.683868],[55.574459,37.68441],[55.574631,37.684891],[55.575432,37.687099],[55.575649,37.687721],[55.576092,37.688889],[55.577709,37.69323],[55.579571,37.698189],[55.581402,37.703121],[55.581951,37.704578],[55.582272,37.705448],[55.582729,37.70668],[55.584511,37.711472],[55.585201,37.71331],[55.585819,37.714989],[55.586071,37.715672],[55.58654,37.716949],[55.587009,37.71822],[55.58749,37.719452],[55.587688,37.719952],[55.588299,37.72142],[55.588951,37.723],[55.589619,37.724548],[55.59016,37.725842],[55.591499,37.729031],[55.591949,37.73011],[55.593449,37.733688],[55.59478,37.736851],[55.594959,37.737309],[55.5952,37.737869],[55.595829,37.739429],[55.599812,37.748901],[55.600319,37.750092],[55.600761,37.751122],[55.601151,37.752041],[55.60165,37.753132],[55.602089,37.75404],[55.602669,37.755161],[55.603168,37.756088],[55.6063,37.761768],[55.60696,37.762981],[55.612579,37.77314],[55.616131,37.779572],[55.616459,37.78017],[55.616638,37.780491],[55.617081,37.7813],[55.617619,37.78228],[55.618858,37.784519],[55.619438,37.785568],[55.619869,37.786461],[55.620838,37.788631],[55.621399,37.789799],[55.621929,37.790821],[55.622391,37.791649],[55.624439,37.795361],[55.62495,37.796268],[55.625351,37.796909],[55.62574,37.797508],[55.626129,37.7981],[55.62619,37.798199],[55.626411,37.79847],[55.62669,37.798851],[55.62711,37.79945],[55.627621,37.800201],[55.62772,37.800331],[55.63179,37.806599],[55.638611,37.817032],[55.63908,37.817719],[55.640419,37.819771],[55.640659,37.820141],[55.643909,37.825119],[55.645351,37.827309],[55.647419,37.83049],[55.648521,37.83213],[55.648972,37.832802],[55.649021,37.83287],[55.649658,37.833721],[55.650372,37.834641],[55.65123,37.835602],[55.65181,37.83617],[55.652519,37.8368],[55.653511,37.837551],[55.654282,37.838051],[55.65493,37.838428],[55.655941,37.83894],[55.656559,37.839191],[55.657131,37.83939],[55.65794,37.839581],[55.65889,37.839771],[55.65974,37.839859],[55.660549,37.839901],[55.661308,37.839901],[55.662201,37.839809],[55.662971,37.839668],[55.663738,37.83947],[55.664799,37.839111],[55.670181,37.837132],[55.679001,37.83392],[55.682739,37.832371],[55.68362,37.832031],[55.68544,37.83136],[55.687061,37.830761],[55.6875,37.830589],[55.687778,37.830502],[55.68898,37.83012],[55.690079,37.829849],[55.691051,37.829689],[55.692001,37.829571],[55.692879,37.829521],[55.693741,37.829529],[55.694759,37.82959],[55.69569,37.829708],[55.696659,37.82988],[55.697041,37.82999],[55.697418,37.83009],[55.697479,37.830109],[55.69804,37.830269],[55.698479,37.830421],[55.69883,37.83054],[55.69899,37.830608],[55.6996,37.830849],[55.70039,37.831211],[55.701149,37.831589],[55.704849,37.833591],[55.705349,37.833851],[55.707619,37.83506],[55.708229,37.835381],[55.709419,37.83601],[55.709961,37.8363],[55.71011,37.83638],[55.712391,37.837589],[55.71328,37.838032],[55.71402,37.838322],[55.714729,37.838558],[55.715511,37.838741],[55.71656,37.838909],[55.72023,37.839359],[55.72298,37.839691],[55.728729,37.840382],[55.731949,37.840771],[55.732861,37.84087],[55.734409,37.841068],[55.736671,37.841351],[55.74012,37.841801],[55.740929,37.841881],[55.74213,37.84201],[55.74361,37.842098],[55.745289,37.842159],[55.747231,37.842251],[55.748741,37.8423],[55.74939,37.842319],[55.749931,37.842361],[55.75071,37.842419],[55.752129,37.84251],[55.753551,37.84259],[55.75523,37.84272],[55.755501,37.842739],[55.757359,37.84288],[55.757561,37.84288],[55.757641,37.84288],[55.758911,37.842892],[55.759331,37.842899],[55.760319,37.84296],[55.760971,37.842991],[55.762878,37.843102],[55.76572,37.843239],[55.766689,37.843288],[55.76738,37.843319],[55.767891,37.843349],[55.768021,37.843361],[55.768501,37.843391],[55.770119,37.843491],[55.770489,37.843491],[55.77145,37.843491],[55.772919,37.843342],[55.774342,37.843208],[55.77499,37.84338],[55.775249,37.843491],[55.775452,37.843689],[55.776039,37.844742],[55.77623,37.844978],[55.77705,37.845612],[55.777222,37.845779],[55.777351,37.84594],[55.777531,37.846272],[55.777889,37.847328],[55.778801,37.85104],[55.779202,37.852638],[55.779339,37.853279],[55.779732,37.85498],[55.782631,37.867538],[55.782661,37.867661],[55.783169,37.869801],[55.783279,37.870251],[55.78421,37.874069],[55.784538,37.875488],[55.78471,37.87619],[55.784889,37.876949],[55.78561,37.880032],[55.786098,37.882141],[55.78651,37.883801],[55.786739,37.884609],[55.78746,37.88699],[55.788448,37.890148],[55.78949,37.893379],[55.789871,37.894581],[55.790169,37.89555],[55.790199,37.895641],[55.791199,37.8988],[55.792561,37.903049],[55.793041,37.904652],[55.793282,37.905579],[55.793419,37.906479],[55.793461,37.90691],[55.793468,37.907089],[55.79348,37.907341],[55.793499,37.907871],[55.793499,37.908539],[55.79351,37.916191],[55.793522,37.91724],[55.79353,37.918259],[55.793549,37.921631],[55.79361,37.92384],[55.793732,37.927231],[55.793892,37.931759],[55.79398,37.934212],[55.793991,37.934639],[55.794022,37.935371],[55.794041,37.936089],[55.794109,37.937531],[55.794331,37.942131],[55.794441,37.944149],[55.794559,37.946301],[55.794571,37.946381],[55.794628,37.947529],[55.794731,37.948898],[55.794922,37.950771],[55.79525,37.95372],[55.795479,37.955669],[55.795589,37.95673],[55.795792,37.958351],[55.79586,37.9589],[55.79657,37.965309],[55.79681,37.96735],[55.796989,37.96891],[55.79707,37.969711],[55.797421,37.972721],[55.798012,37.97784],[55.798828,37.984989],[55.798981,37.98632],[55.799068,37.987122],[55.799309,37.989269],[55.799389,37.989929],[55.79995,37.99477],[55.800179,37.996861],[55.800678,38.001228],[55.80167,38.009972],[55.802582,38.017769],[55.802711,38.018841],[55.80275,38.019249],[55.804459,38.034031],[55.804798,38.036968],[55.805111,38.03968],[55.806099,38.048382],[55.80703,38.056568],[55.807659,38.062111],[55.807812,38.0634],[55.80801,38.065159],[55.808071,38.065659],[55.8083,38.067612],[55.808739,38.071411],[55.80938,38.07703],[55.809841,38.081131],[55.809959,38.082241],[55.81068,38.088501],[55.810719,38.08881],[55.81139,38.094582],[55.812359,38.10323],[55.81303,38.1092],[55.813881,38.116638],[55.81868,38.15852],[55.819,38.161419],[55.820221,38.172131],[55.820431,38.17411],[55.82132,38.181702],[55.821442,38.182949],[55.821461,38.183102],[55.821499,38.18354],[55.82225,38.190128],[55.822361,38.191101],[55.823551,38.20171],[55.824329,38.208481],[55.824909,38.213718],[55.8251,38.215611],[55.825329,38.218121],[55.82571,38.223591],[55.82608,38.228828],[55.826542,38.23563],[55.826778,38.239231],[55.827629,38.25211],[55.82795,38.25732],[55.828331,38.263401],[55.828781,38.2701],[55.829109,38.275379],[55.829342,38.280701],[55.829639,38.28738],[55.829659,38.287949],[55.82967,38.288231],[55.830051,38.29707],[55.830502,38.30489],[55.83194,38.33017],[55.83239,38.338009],[55.83342,38.35574],[55.833599,38.358952],[55.83403,38.366322],[55.834381,38.372669],[55.834702,38.377949],[55.83482,38.380878],[55.834839,38.382549],[55.83477,38.383881],[55.834599,38.385471],[55.833721,38.390701],[55.832951,38.395111],[55.832809,38.395908],[55.831779,38.401699],[55.8312,38.40456],[55.83094,38.405682],[55.830631,38.406898],[55.82999,38.408829],[55.82972,38.409592],[55.829151,38.41106],[55.828331,38.412979],[55.826809,38.416618],[55.826031,38.418549],[55.825748,38.419392],[55.825581,38.419949],[55.825089,38.42218],[55.824982,38.42305],[55.824871,38.42392],[55.82478,38.425251],[55.82473,38.426109],[55.82473,38.427311],[55.82476,38.428051],[55.824749,38.428509],[55.82481,38.429169],[55.824989,38.430969],[55.825199,38.432529],[55.825371,38.433399],[55.825699,38.434738],[55.826401,38.43708],[55.828979,38.44458],[55.83062,38.449169],[55.83115,38.45071],[55.832279,38.453861],[55.832829,38.455311],[55.833351,38.456581],[55.835171,38.46122],[55.83836,38.47044],[55.83844,38.47068],[55.839958,38.474972],[55.84132,38.47831],[55.842251,38.480808],[55.843899,38.484718],[55.849442,38.496941],[55.850368,38.499081],[55.851299,38.501099],[55.852501,38.50391],[55.853249,38.505562],[55.853828,38.507092],[55.854752,38.510052],[55.855492,38.5131],[55.85606,38.516289],[55.856522,38.519611],[55.85675,38.522591],[55.85672,38.52573],[55.8564,38.533169],[55.855999,38.541279],[55.85569,38.548031],[55.855461,38.55389],[55.855381,38.556011],[55.85527,38.558819],[55.855179,38.56089],[55.855011,38.565231],[55.854752,38.572048],[55.854591,38.575989],[55.854359,38.580959],[55.854198,38.58392],[55.853821,38.590309],[55.85355,38.594608],[55.853199,38.600342],[55.852901,38.605492],[55.852631,38.609772],[55.852612,38.610142],[55.85257,38.611061],[55.852402,38.613701],[55.85223,38.6166],[55.8522,38.617729],[55.85215,38.62241],[55.8521,38.625439],[55.852089,38.627972],[55.85202,38.63319],[55.851978,38.6376],[55.851929,38.641621],[55.851929,38.641899],[55.851871,38.646179],[55.85181,38.651909],[55.851761,38.656639],[55.851719,38.657131],[55.851452,38.658691],[55.850929,38.660412],[55.849529,38.664989],[55.848789,38.667549],[55.84853,38.668701],[55.84827,38.670448],[55.848209,38.671341],[55.848202,38.672771],[55.848221,38.674671],[55.84837,38.681469],[55.848541,38.689041],[55.848701,38.69688],[55.848831,38.70393],[55.84893,38.708691],[55.849152,38.718632],[55.849251,38.72348],[55.849361,38.728699],[55.849468,38.73336],[55.849529,38.736099],[55.849739,38.747841],[55.84996,38.75782],[55.85006,38.762772],[55.850109,38.76535],[55.85014,38.766449],[55.85014,38.76672],[55.850151,38.767639],[55.850201,38.77037],[55.850281,38.774529],[55.850449,38.782619],[55.85054,38.787449],[55.850739,38.797169],[55.85083,38.801781],[55.850929,38.806992],[55.851028,38.811989],[55.851151,38.817791],[55.851349,38.826908],[55.851452,38.83194],[55.851559,38.836769],[55.851669,38.84137],[55.85183,38.850101],[55.851959,38.854939],[55.852131,38.85675],[55.85244,38.859402],[55.852741,38.861851],[55.85297,38.86401],[55.853298,38.86705],[55.853371,38.86755],[55.853649,38.86882],[55.853851,38.869652],[55.854881,38.8736],[55.855572,38.876369],[55.856621,38.880428],[55.857498,38.883888],[55.857632,38.884441],[55.857899,38.885509],[55.858608,38.888271],[55.858761,38.888851],[55.859509,38.89172],[55.859638,38.892189],[55.86071,38.89637],[55.861301,38.898579],[55.86179,38.900471],[55.862309,38.90255],[55.866249,38.917938],[55.867081,38.921101],[55.869419,38.930328],[55.872372,38.945221],[55.873741,38.952301],[55.875,38.958649],[55.876041,38.962421],[55.876839,38.965401],[55.877029,38.96616],[55.878761,38.97385],[55.880711,38.982849],[55.88147,38.986351],[55.883362,38.9953],[55.88361,38.99654],[55.884048,38.998951],[55.884491,39.00079],[55.885399,39.004181],[55.886238,39.007469],[55.88715,39.010571],[55.88763,39.0121],[55.88805,39.013111],[55.896252,39.043819],[55.897362,39.047932],[55.897861,39.049789],[55.898151,39.051102],[55.898708,39.054008],[55.899109,39.05714],[55.899559,39.061008],[55.899792,39.063019],[55.899811,39.0634],[55.89986,39.063911],[55.899899,39.064449],[55.900002,39.065868],[55.900299,39.071079],[55.900551,39.0737],[55.90118,39.077179],[55.901691,39.079651],[55.901829,39.080311],[55.90213,39.081772],[55.905811,39.098789],[55.90694,39.10458],[55.91214,39.137428],[55.913052,39.14325],[55.913601,39.14687],[55.914108,39.150108],[55.91431,39.151501],[55.914421,39.152279],[55.914471,39.152599],[55.914822,39.154758],[55.915722,39.160469],[55.917042,39.168201],[55.9174,39.171108],[55.917789,39.17503],[55.918152,39.178669],[55.918442,39.181862],[55.91853,39.18288],[55.918919,39.186878],[55.919079,39.188759],[55.91988,39.199379],[55.920479,39.208561],[55.921219,39.21978],[55.921299,39.220951],[55.921619,39.22559],[55.92292,39.244621],[55.923351,39.250851],[55.926182,39.29248],[55.92696,39.3041],[55.927559,39.313049],[55.927952,39.318871],[55.928181,39.322529],[55.92836,39.325321],[55.92836,39.325371],[55.928421,39.326351],[55.928478,39.327202],[55.931431,39.37112],[55.93227,39.38385],[55.932812,39.391972],[55.933029,39.39529],[55.933151,39.397049],[55.934731,39.42107],[55.93491,39.423988],[55.936069,39.441189],[55.93721,39.45771],[55.93779,39.467388],[55.938061,39.46907],[55.93853,39.471161],[55.93972,39.475498],[55.941811,39.483219],[55.943611,39.499222],[55.943939,39.502159],[55.944931,39.511028],[55.94593,39.519939],[55.945969,39.520309],[55.952301,39.577099],[55.953369,39.586811],[55.955349,39.60461],[55.955799,39.60836],[55.956348,39.613419],[55.957291,39.622089],[55.957088,39.626629],[55.95681,39.632778],[55.95673,39.634609],[55.956711,39.635139],[55.956791,39.638279],[55.957359,39.64682],[55.958721,39.66798],[55.960369,39.69347],[55.960659,39.697731],[55.96085,39.700539],[55.96191,39.716789],[55.9622,39.72086],[55.96225,39.721691],[55.964409,39.75536],[55.964851,39.762169],[55.96489,39.762718],[55.96524,39.768108],[55.965439,39.774719],[55.965809,39.777882],[55.96764,39.784889],[55.98246,39.840961],[56.000141,39.908619],[56.000488,39.909969],[56.001431,39.913559],[56.001511,39.91383],[56.001701,39.91441],[56.002071,39.915791],[56.002529,39.917],[56.005741,39.92347],[56.007729,39.92849],[56.008629,39.931511],[56.008701,39.931782],[56.010071,39.936958],[56.011211,39.941299],[56.012619,39.94664],[56.013988,39.95166],[56.014,39.951679],[56.014729,39.95438],[56.017101,39.963089],[56.019081,39.970409],[56.019932,39.973541],[56.020969,39.97736],[56.021751,39.98024],[56.022251,39.982071],[56.022449,39.9828],[56.024139,39.989029],[56.024891,39.991821],[56.029888,40.01022],[56.033798,40.024639],[56.034512,40.027241],[56.036812,40.035728],[56.04406,40.06221],[56.04781,40.075932],[56.048531,40.07859],[56.050949,40.087429],[56.051281,40.08868],[56.05249,40.093159],[56.05315,40.095581],[56.060669,40.123489],[56.060928,40.1245],[56.06554,40.141541],[56.072929,40.169151],[56.073399,40.170849],[56.073719,40.172039],[56.076439,40.182251],[56.076839,40.1838],[56.0769,40.184021],[56.077229,40.185268],[56.078369,40.1894],[56.0798,40.195129],[56.08007,40.196331],[56.080158,40.196941],[56.080238,40.197891],[56.08025,40.19841],[56.080231,40.199059],[56.080151,40.19973],[56.080009,40.200539],[56.078861,40.20388],[56.078739,40.20433],[56.077461,40.207958],[56.075371,40.213879],[56.07259,40.221809],[56.07198,40.224579],[56.071739,40.22599],[56.071541,40.22797],[56.07151,40.231892],[56.071579,40.239571],[56.071621,40.242199],[56.071671,40.247181],[56.07172,40.251339],[56.071819,40.25576],[56.071899,40.264408],[56.072021,40.275421],[56.07201,40.277401],[56.071911,40.279362],[56.071751,40.281521],[56.071301,40.284851],[56.070419,40.289349],[56.070091,40.29105],[56.066311,40.311272],[56.065369,40.317341],[56.06509,40.320469],[56.064861,40.32436],[56.064812,40.32885],[56.06509,40.357712],[56.065109,40.36055],[56.064899,40.362999],[56.064381,40.365318],[56.063999,40.36647],[56.06348,40.368031],[56.062969,40.36956],[56.060211,40.37785],[56.058392,40.385189],[56.05584,40.401508],[56.05529,40.40506],[56.05397,40.413551],[56.053379,40.41769],[56.053059,40.422169],[56.053268,40.426491],[56.053631,40.429062],[56.054138,40.431789],[56.054539,40.433529],[56.055012,40.435131],[56.056149,40.438919],[56.057251,40.442509],[56.059212,40.448811],[56.059971,40.450859],[56.060799,40.45266],[56.061741,40.45451],[56.062462,40.455631],[56.063801,40.4575],[56.064159,40.457951],[56.06485,40.45874],[56.068939,40.462528],[56.07304,40.466202],[56.075062,40.468109],[56.076439,40.469688],[56.078892,40.473],[56.080009,40.47448],[56.080471,40.47506],[56.081928,40.476929],[56.082432,40.4776],[56.083141,40.478611],[56.0839,40.47998],[56.08466,40.481571],[56.085461,40.483891],[56.08606,40.486351],[56.089851,40.509869],[56.090389,40.513908],[56.092449,40.530998],[56.094212,40.545502],[56.095581,40.557201],[56.096889,40.568321],[56.097149,40.570969],[56.097328,40.57296],[56.09763,40.57518],[56.09798,40.577381],[56.098412,40.580799],[56.098591,40.58226],[56.099152,40.587151],[56.099369,40.589512],[56.099529,40.591148],[56.099812,40.593361],[56.100121,40.59547],[56.10041,40.597481],[56.102051,40.611118],[56.103661,40.624569],[56.103882,40.62677],[56.10405,40.629089],[56.10413,40.633461],[56.104019,40.641369],[56.103821,40.64497],[56.103828,40.648499],[56.10384,40.65242],[56.10363,40.661339],[56.103519,40.66444],[56.103489,40.667622],[56.103519,40.67067],[56.10334,40.683609],[56.103329,40.68642],[56.102959,40.711189],[56.102249,40.763199],[56.102329,40.76741],[56.102589,40.771111],[56.102612,40.771339],[56.102779,40.773022],[56.102951,40.774342],[56.103111,40.7756],[56.104851,40.787209],[56.10527,40.79002],[56.108238,40.809799],[56.111141,40.828381],[56.11182,40.83308],[56.112591,40.83646],[56.113392,40.839539],[56.114681,40.843609],[56.11602,40.84687],[56.118992,40.85318],[56.129902,40.876259],[56.13113,40.879059],[56.132191,40.881241],[56.132561,40.881989],[56.13348,40.88377],[56.134041,40.884899],[56.134701,40.88633],[56.137161,40.891621],[56.138111,40.893848],[56.139389,40.89642],[56.14061,40.898788],[56.146461,40.911152],[56.14753,40.91304],[56.14859,40.914761],[56.149818,40.91655],[56.151058,40.918201],[56.154869,40.922371],[56.158642,40.926521],[56.16753,40.93631],[56.173779,40.94326],[56.175091,40.94445],[56.176392,40.945431],[56.177738,40.946201],[56.1791,40.946781],[56.19043,40.950539],[56.190891,40.950729],[56.192089,40.95116],[56.192841,40.951611],[56.193321,40.95216],[56.193722,40.952839],[56.193989,40.95359],[56.19418,40.954418],[56.194321,40.955502],[56.19463,40.9617],[56.194931,40.968739],[56.195351,40.9744],[56.196018,40.986382],[56.196251,40.99144],[56.196758,41.00251],[56.197819,41.02309],[56.20219,41.11478],[56.20306,41.133041],[56.20385,41.149139],[56.2043,41.158642],[56.204361,41.15974],[56.206051,41.196301],[56.206631,41.206532],[56.207371,41.222488],[56.20882,41.251839],[56.211048,41.30019],[56.211201,41.303452],[56.212311,41.326351],[56.212448,41.33046],[56.216839,41.43071],[56.21756,41.447971],[56.218842,41.474659],[56.223141,41.56255],[56.225788,41.630322],[56.226082,41.63707],[56.226181,41.639389],[56.227459,41.669319],[56.22855,41.694981],[56.228828,41.701469],[56.228859,41.702179],[56.229172,41.709389],[56.230148,41.732349],[56.230259,41.73505],[56.230331,41.736679],[56.232471,41.786751],[56.232738,41.794498],[56.23291,41.79882],[56.23296,41.79998],[56.23317,41.805161],[56.233189,41.805889],[56.233589,41.817379],[56.234089,41.838871],[56.234402,41.85252],[56.23465,41.866039],[56.2351,41.8848],[56.23513,41.885979],[56.235168,41.887909],[56.2355,41.903431],[56.235889,41.921749],[56.236118,41.931831],[56.23632,41.94083],[56.23634,41.941792],[56.236351,41.94276],[56.23637,41.94421],[56.236561,41.952782],[56.23658,41.954411],[56.236591,41.95488],[56.236629,41.956581],[56.236629,41.956711],[56.236881,41.966068],[56.236931,41.97105],[56.236969,41.973549],[56.237,41.974812],[56.237041,41.976479],[56.237049,41.97715],[56.237061,41.97784],[56.23724,41.98439],[56.237301,41.98632],[56.23732,41.98719],[56.23737,41.98933],[56.237419,41.992352],[56.23745,41.993832],[56.237461,41.994499],[56.237541,41.99876],[56.237549,41.99931],[56.237621,42.00243],[56.237652,42.004131],[56.237789,42.009571],[56.23793,42.017139],[56.237999,42.02042],[56.238091,42.02457],[56.238201,42.02961],[56.238239,42.030991],[56.238331,42.034069],[56.238392,42.036381],[56.238419,42.037552],[56.238468,42.039661],[56.23851,42.041389],[56.238541,42.042309],[56.238659,42.047852],[56.238789,42.053452],[56.238899,42.058681],[56.238918,42.059441],[56.238991,42.062641],[56.239029,42.06456],[56.239059,42.066071],[56.239079,42.066719],[56.23912,42.068748],[56.23912,42.069061],[56.239128,42.069359],[56.239159,42.070831],[56.239262,42.075661],[56.239281,42.0765],[56.239319,42.07877],[56.23938,42.081821],[56.239422,42.083851],[56.23946,42.086319],[56.239498,42.088009],[56.239571,42.090832],[56.239658,42.09568],[56.2397,42.097988],[56.239719,42.099369],[56.239738,42.101269],[56.23975,42.101719],[56.239712,42.102219],[56.2397,42.102371],[56.239609,42.10305],[56.239429,42.10384],[56.239231,42.104568],[56.23909,42.105],[56.238941,42.105389],[56.238762,42.10577],[56.238419,42.106441],[56.238049,42.10704],[56.23793,42.10722],[56.23737,42.10807],[56.236279,42.109791],[56.235409,42.11121],[56.234341,42.112789],[56.23365,42.113869],[56.232689,42.115391],[56.231682,42.117001],[56.230629,42.11869],[56.22974,42.120159],[56.22879,42.121719],[56.22765,42.12347],[56.226768,42.124859],[56.22617,42.125839],[56.225601,42.126751],[56.225189,42.127468],[56.224949,42.127869],[56.224731,42.12825],[56.224499,42.128681],[56.22414,42.129459],[56.223801,42.130241],[56.22337,42.131451],[56.222969,42.132702],[56.222679,42.13369],[56.22237,42.13488],[56.222351,42.134972],[56.222271,42.13533],[56.222191,42.13578],[56.221951,42.136971],[56.221802,42.137798],[56.22171,42.138329],[56.22163,42.13887],[56.221539,42.139568],[56.22147,42.140251],[56.221359,42.141621],[56.22126,42.14344],[56.22121,42.144508],[56.221111,42.1465],[56.221081,42.147301],[56.221039,42.147991],[56.220989,42.149342],[56.220951,42.150242],[56.22086,42.151829],[56.220829,42.152328],[56.22076,42.153728],[56.220661,42.156261],[56.22057,42.158321],[56.220482,42.16037],[56.22044,42.16106],[56.220379,42.162239],[56.220242,42.1651],[56.220131,42.167999],[56.22007,42.169552],[56.220032,42.17033],[56.21991,42.172489],[56.219849,42.17411],[56.21983,42.17485],[56.219749,42.17614],[56.219639,42.17831],[56.219559,42.180012],[56.219509,42.181019],[56.21946,42.182041],[56.219452,42.182171],[56.219391,42.183201],[56.219341,42.18401],[56.219269,42.185101],[56.219189,42.18644],[56.219109,42.187599],[56.218929,42.190868],[56.218849,42.192341],[56.218769,42.193939],[56.218719,42.19487],[56.218681,42.195591],[56.218639,42.196548],[56.218578,42.19772],[56.218491,42.199581],[56.21841,42.201229],[56.21833,42.202839],[56.218288,42.203579],[56.218239,42.204659],[56.218159,42.206322],[56.218151,42.206532],[56.218102,42.207401],[56.218021,42.209061],[56.217918,42.211029],[56.21785,42.212399],[56.217781,42.213848],[56.217659,42.216492],[56.217541,42.218849],[56.217419,42.221321],[56.21735,42.222679],[56.217281,42.22393],[56.217239,42.22472],[56.21714,42.226871],[56.217079,42.228149],[56.21703,42.229679],[56.216999,42.230999],[56.216961,42.2323],[56.216888,42.233879],[56.216831,42.235279],[56.216728,42.237122],[56.21664,42.238911],[56.21656,42.24078],[56.216412,42.243759],[56.216209,42.245811],[56.215931,42.247929],[56.215611,42.24984],[56.215359,42.251202],[56.215031,42.25272],[56.21471,42.254009],[56.214241,42.255501],[56.213951,42.25647],[56.21389,42.25666],[56.2136,42.25761],[56.213039,42.259548],[56.212559,42.261139],[56.211979,42.263111],[56.21138,42.26503],[56.210609,42.267651],[56.209949,42.269829],[56.209171,42.272491],[56.208221,42.275631],[56.207611,42.277748],[56.20694,42.27998],[56.206249,42.282349],[56.205791,42.283871],[56.205238,42.28566],[56.20525,42.28627],[56.20401,42.290192],[56.203461,42.2924],[56.20311,42.31216],[56.202709,42.350479],[56.202141,42.353569],[56.20055,42.358742],[56.19643,42.370819],[56.192322,42.383091],[56.187889,42.39357],[56.180851,42.4077],[56.174171,42.41687],[56.173489,42.41782],[56.17289,42.41898],[56.172581,42.42009],[56.172379,42.421188],[56.170639,42.432362],[56.169659,42.43837],[56.16935,42.441959],[56.165829,42.482651],[56.164501,42.491241],[56.159721,42.51355],[56.15876,42.520081],[56.159119,42.531361],[56.15947,42.544979],[56.160858,42.594921],[56.161251,42.60453],[56.16552,42.619999],[56.172901,42.646759],[56.173481,42.649509],[56.178452,42.65913],[56.191662,42.686031],[56.19186,42.686432],[56.193371,42.689461],[56.196049,42.695148],[56.196758,42.698891],[56.197948,42.70261],[56.218712,42.76685],[56.220501,42.772598],[56.221661,42.77668],[56.223629,42.782749],[56.224579,42.78558],[56.226028,42.789421],[56.226971,42.792339],[56.22842,42.79681],[56.229061,42.798882],[56.23,42.802238],[56.230999,42.805901],[56.24231,42.84774],[56.242371,42.84795],[56.249691,42.874859],[56.256721,42.90099],[56.260399,42.91436],[56.26405,42.927792],[56.27478,42.967529],[56.275219,42.969231],[56.27552,42.970509],[56.275791,42.971901],[56.275982,42.973129],[56.27615,42.97443],[56.27631,42.976299],[56.276451,42.978531],[56.276951,42.98867],[56.277401,42.998749],[56.278488,43.02235],[56.280121,43.058609],[56.2817,43.09417],[56.28487,43.16291],[56.285,43.165661],[56.28511,43.16753],[56.286179,43.19146],[56.28981,43.27335],[56.293308,43.355141],[56.293659,43.3633],[56.298222,43.473461],[56.298351,43.476559],[56.298439,43.478661],[56.30085,43.538639],[56.300961,43.541592],[56.301022,43.542969],[56.30117,43.54668],[56.301609,43.557201],[56.301689,43.559189],[56.301788,43.56168],[56.302059,43.56789],[56.302711,43.58334],[56.30302,43.590809],[56.303028,43.59116],[56.303051,43.591572],[56.303471,43.601101],[56.304211,43.618938],[56.304508,43.625919],[56.304779,43.63308],[56.30534,43.648609],[56.305931,43.66502],[56.3064,43.678478],[56.306499,43.681099],[56.306599,43.684059],[56.30685,43.690491],[56.306889,43.691631],[56.30698,43.693989],[56.307541,43.709881],[56.308159,43.726921],[56.308701,43.742699],[56.308842,43.746109],[56.308861,43.74688],[56.309269,43.759121],[56.309689,43.770309],[56.309891,43.77544],[56.31036,43.788029],[56.31041,43.78923],[56.31052,43.79203],[56.31076,43.798061],[56.310822,43.799671],[56.310879,43.800941],[56.31118,43.808899],[56.311352,43.81353],[56.311588,43.819901],[56.31181,43.825691],[56.311871,43.826111],[56.311878,43.82626],[56.311951,43.828098],[56.312481,43.84042],[56.312481,43.84058],[56.3125,43.84108],[56.312569,43.84277],[56.312729,43.846748],[56.312771,43.847858],[56.312908,43.851131],[56.313179,43.858212],[56.313381,43.86322],[56.313339,43.86388],[56.31329,43.864182],[56.31319,43.864399],[56.31303,43.864601],[56.312889,43.864811],[56.312809,43.86499],[56.312752,43.865238],[56.312729,43.86554],[56.31271,43.865829],[56.312649,43.866119],[56.312569,43.866451],[56.312401,43.86694],[56.31234,43.867142],[56.31226,43.867359],[56.312019,43.868],[56.31189,43.868252],[56.311749,43.868431],[56.311569,43.86861],[56.311371,43.868721],[56.31123,43.86879],[56.311039,43.868851],[56.310219,43.869301],[56.309959,43.869438],[56.308971,43.86998],[56.30854,43.870209],[56.307701,43.87067],[56.30727,43.870861],[56.306358,43.871262],[56.30381,43.872391],[56.30378,43.87241],[56.302429,43.873341],[56.301121,43.874241],[56.300819,43.874489],[56.300529,43.874741],[56.30027,43.87495],[56.299419,43.875721],[56.298512,43.876701],[56.296959,43.878609],[56.29636,43.87933],[56.296249,43.879471],[56.295639,43.880219],[56.292381,43.884319],[56.29105,43.88586],[56.290588,43.886318],[56.290161,43.886688],[56.289589,43.887131],[56.288311,43.88802],[56.285702,43.889679],[56.28524,43.890011],[56.284592,43.890591],[56.284111,43.89122],[56.283798,43.891769],[56.283489,43.89238],[56.283249,43.89304],[56.282909,43.894009],[56.28241,43.895481],[56.28233,43.895679],[56.282242,43.895889],[56.282108,43.896191],[56.281689,43.896961],[56.281368,43.897442],[56.280849,43.898109],[56.279018,43.900459],[56.277939,43.90184],[56.275742,43.904671],[56.275139,43.905418],[56.273869,43.907001],[56.271389,43.910061],[56.27079,43.910809],[56.27037,43.91135],[56.26947,43.912491],[56.268799,43.913399],[56.267921,43.914761],[56.26685,43.916649],[56.265621,43.918991],[56.26532,43.919529],[56.265091,43.919971],[56.26498,43.92017],[56.264561,43.92083],[56.26289,43.923988],[56.259861,43.9296],[56.258461,43.93219],[56.257511,43.93396],[56.25581,43.937119],[56.255291,43.93811],[56.25526,43.93816],[56.254051,43.940411],[56.253658,43.94112],[56.25359,43.94136],[56.247311,43.952999],[56.24699,43.953442],[56.246658,43.954079],[56.246319,43.954781],[56.2458,43.956051],[56.245468,43.956982],[56.245251,43.957668],[56.244961,43.95874],[56.244759,43.959629],[56.244659,43.96011],[56.24461,43.960312],[56.244431,43.96151],[56.244259,43.9632],[56.24329,43.969559],[56.242779,43.972801],[56.242569,43.974159],[56.241779,43.979431],[56.24115,43.98365],[56.240299,43.989269],[56.240002,43.991211],[56.239479,43.994652],[56.239391,43.995251],[56.239059,43.997501],[56.238861,43.998791],[56.23848,44.001282],[56.237991,44.00481],[56.237598,44.007809],[56.236511,44.016102],[56.23597,44.020561],[56.235611,44.023499],[56.23531,44.025822],[56.235142,44.027859],[56.234989,44.029701],[56.234871,44.031559],[56.234852,44.033421],[56.234821,44.035389],[56.234798,44.037701],[56.234859,44.039421],[56.23494,44.041561],[56.234959,44.042831],[56.23494,44.04459],[56.234901,44.046188],[56.234798,44.04805],[56.234711,44.04911],[56.234631,44.050011],[56.234371,44.052341],[56.234089,44.054321],[56.23373,44.056801],[56.233471,44.058552],[56.233158,44.060539],[56.232841,44.062511],[56.232368,44.064899],[56.23204,44.066311],[56.231579,44.067959],[56.230968,44.06966],[56.230179,44.071381],[56.22961,44.07238],[56.229092,44.07309],[56.228531,44.073719],[56.22784,44.074341],[56.227322,44.07473],[56.22718,44.074841],[56.226452,44.07531],[56.225849,44.07563],[56.225422,44.07584],[56.224709,44.076099],[56.224461,44.07616],[56.224079,44.076279],[56.222832,44.076618],[56.222149,44.076801],[56.221401,44.077],[56.221279,44.07703],[56.221031,44.077099],[56.219299,44.077549],[56.218559,44.077789],[56.218239,44.0779],[56.21714,44.078289],[56.216202,44.07869],[56.214901,44.07935],[56.213631,44.080139],[56.212791,44.080719],[56.2122,44.0812],[56.21196,44.081409],[56.210991,44.08226],[56.209549,44.084049],[56.208542,44.085522],[56.20752,44.087189],[56.206581,44.088951],[56.20557,44.091019],[56.204281,44.093899],[56.202381,44.098438],[56.200378,44.103588],[56.1991,44.10717],[56.19838,44.109509],[56.197811,44.111912],[56.197239,44.11475],[56.196892,44.116421],[56.19648,44.11845],[56.1959,44.120911],[56.195431,44.122639],[56.19519,44.12355],[56.194889,44.124451],[56.194031,44.126621],[56.19368,44.127392],[56.192139,44.130371],[56.184631,44.1441],[56.18375,44.145748],[56.183289,44.14687],[56.18206,44.149559],[56.181019,44.151909],[56.18055,44.152851],[56.180149,44.153339],[56.179749,44.153751],[56.179279,44.154121],[56.178768,44.15432],[56.17852,44.1544],[56.17807,44.154442],[56.17754,44.154362],[56.1758,44.153782],[56.17519,44.15361],[56.174358,44.1534],[56.172741,44.153111],[56.171921,44.153011],[56.170971,44.153091],[56.1702,44.153309],[56.169479,44.15358],[56.167912,44.154518],[56.167179,44.154819],[56.166439,44.155022],[56.165722,44.15506],[56.164558,44.154861],[56.162151,44.154259],[56.16098,44.154011],[56.16011,44.153992],[56.15934,44.154072],[56.159271,44.154091],[56.158569,44.154289],[56.157799,44.154652],[56.15654,44.155418],[56.154202,44.156952],[56.152458,44.158081],[56.152191,44.15826],[56.151131,44.158859],[56.150391,44.15918],[56.149712,44.15934],[56.148991,44.159351],[56.14843,44.159248],[56.147739,44.159031],[56.146961,44.15876],[56.14455,44.15778],[56.142811,44.157021],[56.14106,44.156429],[56.139969,44.156181],[56.13829,44.15604],[56.13681,44.15617],[56.13583,44.156361],[56.134491,44.156769],[56.132931,44.157539],[56.131821,44.158249],[56.130699,44.159069],[56.128441,44.161259],[56.12693,44.162819],[56.126362,44.163399],[56.12606,44.163509],[56.12534,44.163601],[56.125229,44.163601],[56.12508,44.163631],[56.124931,44.163719],[56.12479,44.163849],[56.12468,44.16404],[56.124569,44.164322],[56.124561,44.164581],[56.12447,44.165009],[56.124352,44.16531],[56.124161,44.165581],[56.11639,44.172829],[56.114761,44.175751],[56.114281,44.18227],[56.113708,44.20322],[56.118099,44.20797],[56.120731,44.212132],[56.122238,44.217312],[56.123001,44.221142],[56.124619,44.233261],[56.124748,44.236141],[56.124519,44.23875],[56.123379,44.245941],[56.123192,44.248219],[56.123291,44.25174],[56.123562,44.253281],[56.123821,44.254478],[56.124229,44.25581],[56.124779,44.257179],[56.125118,44.257881],[56.125809,44.259491],[56.126011,44.260029],[56.126171,44.260712],[56.126259,44.261318],[56.126282,44.26189],[56.12627,44.26244],[56.12616,44.263191],[56.125919,44.264118],[56.125099,44.265911],[56.124939,44.2663],[56.124069,44.267879],[56.123779,44.26833],[56.12331,44.26902],[56.122421,44.270199],[56.12162,44.271191],[56.119259,44.273941],[56.118172,44.275181],[56.116798,44.276749],[56.116131,44.277519],[56.116051,44.277611],[56.110699,44.283699],[56.110271,44.284191],[56.109791,44.284729],[56.109711,44.28484],[56.10701,44.287941],[56.106419,44.288818],[56.105862,44.289761],[56.105419,44.290649],[56.105,44.29166],[56.10062,44.3041],[56.100159,44.305382],[56.099739,44.306492],[56.099602,44.306808],[56.099461,44.307152],[56.099281,44.307499],[56.09911,44.3078],[56.09856,44.308731],[56.098141,44.309391],[56.097229,44.31078],[56.096748,44.311501],[56.096439,44.311989],[56.096069,44.312691],[56.095699,44.313511],[56.09544,44.314381],[56.095169,44.315392],[56.09502,44.316132],[56.094589,44.31863],[56.094391,44.319469],[56.094189,44.32019],[56.093269,44.323238],[56.092361,44.326302],[56.092079,44.327221],[56.091511,44.32906],[56.09087,44.33099],[56.089882,44.33382],[56.08746,44.34079],[56.085609,44.346218],[56.08498,44.348091],[56.078499,44.367161],[56.07822,44.367901],[56.0779,44.368568],[56.077641,44.369019],[56.077221,44.369598],[56.076939,44.36993],[56.07653,44.370312],[56.076092,44.37064],[56.075611,44.37093],[56.07449,44.37151],[56.072449,44.37249],[56.07077,44.37331],[56.070179,44.3736],[56.06971,44.373821],[56.06889,44.374222],[56.06757,44.374809],[56.06712,44.37505],[56.066761,44.375278],[56.06636,44.37561],[56.066021,44.375938],[56.06572,44.376289],[56.065331,44.376808],[56.06496,44.37743],[56.064522,44.378269],[56.06411,44.37928],[56.06295,44.382271],[56.061211,44.386551],[56.06065,44.38792],[56.060341,44.388691],[56.059681,44.390308],[56.058399,44.393452],[56.05621,44.3988],[56.048389,44.418091],[56.046501,44.422661],[56.046261,44.423382],[56.04607,44.42403],[56.045879,44.42485],[56.0457,44.425869],[56.045631,44.426609],[56.045601,44.427601],[56.04567,44.43103],[56.045658,44.43306],[56.045601,44.433769],[56.045422,44.43491],[56.045189,44.43594],[56.044868,44.43692],[56.04438,44.438099],[56.043289,44.44075],[56.042999,44.441589],[56.042721,44.442501],[56.042519,44.443401],[56.04229,44.444969],[56.04158,44.452389],[56.040192,44.46664],[56.03883,44.480659],[56.038719,44.481689],[56.03862,44.48259],[56.038479,44.483471],[56.0383,44.48428],[56.03804,44.485199],[56.032162,44.502251],[56.031761,44.503448],[56.03149,44.50462],[56.031231,44.505871],[56.031078,44.50705],[56.030899,44.510342],[56.029461,44.545521],[56.028801,44.55407],[56.028011,44.56155],[56.02747,44.568169],[56.027908,44.584888],[56.027229,44.601978],[56.027962,44.60656],[56.02803,44.60738],[56.028179,44.608879],[56.027988,44.613171],[56.02737,44.620541],[56.026791,44.622929],[56.025871,44.624432],[56.025089,44.624889],[56.023769,44.625179],[56.01659,44.625172],[56.015221,44.62529],[56.014061,44.625511],[56.01297,44.625832],[56.011951,44.626362],[56.007408,44.628609],[56.006721,44.629009],[56.0061,44.62944],[56.005871,44.629589],[56.005348,44.630001],[56.004879,44.63052],[56.004238,44.631302],[56.003769,44.631981],[56.002949,44.633129],[56.001518,44.635151],[55.99966,44.63776],[55.998241,44.63979],[55.99741,44.640949],[55.99712,44.641411],[55.996738,44.642159],[55.996521,44.642689],[55.996262,44.643299],[55.996029,44.64399],[55.99559,44.645599],[55.995281,44.647511],[55.995129,44.649059],[55.994919,44.652161],[55.994518,44.658161],[55.99395,44.666309],[55.993889,44.667858],[55.9939,44.66943],[55.998219,44.71011],[55.998539,44.712761],[55.998741,44.713772],[55.999039,44.71479],[55.99942,44.715759],[56,44.71698],[56.00106,44.719109],[56.00182,44.720669],[56.002209,44.721561],[56.00251,44.722279],[56.002708,44.7229],[56.002911,44.72369],[56.003139,44.72504],[56.00322,44.72617],[56.003151,44.72768],[56.002838,44.730659],[56.00259,44.734131],[56.001751,44.74255],[56.00153,44.744381],[56.00132,44.74527],[56.00106,44.745949],[56.00074,44.74662],[55.999279,44.748779],[55.992989,44.757961],[55.990791,44.761318],[55.99033,44.762321],[55.990009,44.76318],[55.989819,44.764069],[55.989719,44.76498],[55.9897,44.765968],[55.99073,44.773331],[55.992962,44.788288],[55.997372,44.81881],[55.997601,44.820049],[55.99781,44.82066],[55.999069,44.823261],[56.004459,44.834709],[56.005829,44.837769],[56.006161,44.83881],[56.006748,44.841309],[56.011189,44.860889],[56.011292,44.861591],[56.011341,44.862282],[56.011372,44.863121],[56.011292,44.86404],[56.01112,44.864929],[56.01088,44.865551],[56.009129,44.869228],[56.008862,44.870022],[56.008659,44.87093],[56.008221,44.873871],[56.005791,44.88974],[56.005718,44.890362],[56.005669,44.890942],[56.005661,44.891472],[56.00568,44.89201],[56.005779,44.89299],[56.007172,44.900478],[56.010979,44.920929],[56.011169,44.922211],[56.011269,44.923309],[56.01128,44.924629],[56.011219,44.925812],[56.01107,44.92696],[56.01088,44.928028],[56.01038,44.92984],[56.009178,44.934361],[56.00882,44.936081],[56.00861,44.93779],[56.008499,44.939602],[56.00845,44.941158],[56.008499,44.94244],[56.008629,44.943741],[56.016418,44.996269],[56.016571,44.997238],[56.016651,44.998199],[56.016651,44.999229],[56.016579,45.000408],[56.01646,45.001598],[56.015572,45.008961],[56.014961,45.014542],[56.01482,45.015701],[56.01453,45.018242],[56.013649,45.026249],[56.013618,45.02721],[56.013519,45.03426],[56.013458,45.039619],[56.0135,45.04118],[56.013618,45.042728],[56.013851,45.044189],[56.01667,45.059238],[56.016972,45.061581],[56.017262,45.06358],[56.017792,45.06654],[56.01825,45.068859],[56.01857,45.069988],[56.019001,45.071701],[56.019669,45.07513],[56.021061,45.082458],[56.021461,45.084579],[56.022079,45.087971],[56.022369,45.089191],[56.023079,45.09153],[56.032928,45.121109],[56.033489,45.122829],[56.03371,45.1236],[56.03389,45.12447],[56.033981,45.125229],[56.034012,45.125919],[56.033951,45.140442],[56.033981,45.141682],[56.03405,45.142712],[56.034149,45.143501],[56.034302,45.14452],[56.03447,45.14547],[56.036381,45.15469],[56.037941,45.162331],[56.03825,45.163601],[56.038639,45.164841],[56.04472,45.18079],[56.0452,45.182331],[56.045761,45.18428],[56.046219,45.18568],[56.05463,45.209648],[56.055241,45.21146],[56.056541,45.215519],[56.05685,45.216721],[56.05695,45.21751],[56.056931,45.218281],[56.056839,45.219101],[56.055882,45.224049],[56.055679,45.224819],[56.05537,45.225571],[56.055038,45.226059],[56.054619,45.226501],[56.052269,45.22813],[56.05188,45.228588],[56.051609,45.228958],[56.051338,45.229519],[56.051128,45.230221],[56.050152,45.234531],[56.050018,45.235241],[56.04998,45.235939],[56.049992,45.236629],[56.050049,45.237339],[56.050549,45.241348],[56.050812,45.24242],[56.05117,45.243542],[56.054352,45.252941],[56.054729,45.254261],[56.057491,45.26442],[56.057732,45.265572],[56.057899,45.266819],[56.06147,45.302731],[56.06155,45.30365],[56.061569,45.3046],[56.06155,45.305679],[56.059879,45.333832],[56.059811,45.334759],[56.05975,45.335331],[56.05962,45.335831],[56.059311,45.336651],[56.05505,45.3456],[56.054668,45.346481],[56.054428,45.347198],[56.054138,45.348209],[56.053459,45.350941],[56.048328,45.371361],[56.045738,45.383511],[56.045441,45.385231],[56.045231,45.386841],[56.045151,45.388439],[56.045139,45.390099],[56.045349,45.412231],[56.04546,45.416229],[56.045818,45.427399],[56.04599,45.433071],[56.046089,45.43544],[56.046261,45.43782],[56.048069,45.462238],[56.048229,45.464199],[56.048649,45.4678],[56.04969,45.476719],[56.049881,45.478939],[56.050049,45.481541],[56.05159,45.50951],[56.05167,45.511181],[56.051689,45.512569],[56.051651,45.513699],[56.051338,45.521839],[56.051022,45.52972],[56.05093,45.531212],[56.050331,45.5387],[56.050159,45.542641],[56.04998,45.547421],[56.049931,45.549541],[56.049801,45.556591],[56.04974,45.558392],[56.049622,45.559582],[56.04945,45.560902],[56.042751,45.60685],[56.042622,45.608101],[56.042542,45.609371],[56.0425,45.610531],[56.042519,45.611721],[56.043781,45.639339],[56.043911,45.642521],[56.043968,45.64629],[56.043991,45.648689],[56.044109,45.65126],[56.044941,45.669449],[56.046001,45.69286],[56.047169,45.718689],[56.047298,45.721008],[56.047428,45.72295],[56.04747,45.723801],[56.047531,45.72514],[56.047611,45.72768],[56.047642,45.729301],[56.047729,45.73056],[56.047878,45.732529],[56.0481,45.73505],[56.049339,45.76276],[56.05212,45.825199],[56.052471,45.833271],[56.052521,45.834949],[56.052521,45.83625],[56.052479,45.837379],[56.052319,45.83881],[56.05183,45.8419],[56.05162,45.843281],[56.051498,45.844559],[56.05138,45.84687],[56.05125,45.8498],[56.051159,45.851379],[56.050831,45.854912],[56.050701,45.856312],[56.049992,45.862358],[56.049831,45.864239],[56.049709,45.86623],[56.049679,45.86813],[56.049728,45.876091],[56.049679,45.88908],[56.04977,45.914181],[56.04974,45.917419],[56.049679,45.918701],[56.049541,45.919899],[56.04932,45.921299],[56.049019,45.9226],[56.04644,45.932362],[56.043549,45.943329],[56.040409,45.955261],[56.038261,45.96336],[56.03299,45.983471],[56.031689,45.988319],[56.03056,45.99202],[56.029942,45.994209],[56.029259,45.997021],[56.02877,45.999298],[56.02837,46.0009],[56.027851,46.002811],[56.027481,46.00399],[56.027149,46.005001],[56.024632,46.011688],[56.0242,46.01265],[56.023731,46.01347],[56.023338,46.013981],[56.022781,46.014511],[56.013191,46.021309],[56.01276,46.021709],[56.01244,46.02203],[56.012001,46.022621],[56.010399,46.025391],[56.000919,46.041672],[56.000729,46.042179],[56.000549,46.042931],[56.0005,46.043468],[56.000519,46.044189],[56.001808,46.052929],[56.00206,46.05484],[56.002281,46.057281],[56.002369,46.059891],[56.002361,46.062141],[56.0023,46.06382],[56.00206,46.06641],[56.001732,46.06881],[56.00156,46.07061],[56.001492,46.071232],[56.001389,46.07185],[56.001308,46.072269],[56.001221,46.072941],[56.00119,46.07328],[56.00116,46.07373],[56.001141,46.073952],[56.001122,46.074341],[56.001099,46.074928],[56.001091,46.075539],[56.00108,46.076149],[56.001049,46.076752],[56.00053,46.083248],[55.999199,46.09798],[55.99498,46.14637],[55.994808,46.148331],[55.99472,46.149422],[55.994701,46.149609],[55.99176,46.183311],[55.991692,46.18539],[55.991638,46.186008],[55.991428,46.188259],[55.991402,46.19009],[55.991539,46.191662],[55.991871,46.193192],[55.99226,46.19455],[55.99284,46.195869],[55.993382,46.196812],[55.99437,46.198441],[55.995071,46.199669],[55.999889,46.20805],[56.00531,46.217491],[56.023251,46.24873],[56.02623,46.251999],[56.0299,46.251999],[56.03352,46.251999],[56.035919,46.251999],[56.037731,46.254398],[56.038311,46.25835],[56.039459,46.27895],[56.041672,46.29525],[56.046558,46.307789],[56.048191,46.31345],[56.048672,46.31723],[56.04723,46.332329],[56.04541,46.343491],[56.041759,46.352589],[56.041859,46.360661],[56.043789,46.388691],[56.043659,46.392811],[56.043491,46.39859],[56.043449,46.401878],[56.043591,46.405979],[56.04475,46.41238],[56.046619,46.41885],[56.053459,46.44117],[56.05431,46.446171],[56.054729,46.451389],[56.054611,46.45636],[56.05423,46.461418],[56.05331,46.47226],[56.053188,46.473629],[56.053181,46.474159],[56.053089,46.481258],[56.052898,46.485489],[56.052528,46.489059],[56.052441,46.49054],[56.05159,46.49752],[56.0509,46.50153],[56.049671,46.506149],[56.04829,46.509941],[56.046009,46.515419],[56.04472,46.51873],[56.044022,46.521999],[56.043678,46.529739],[56.04335,46.53318],[56.042351,46.53688],[56.035011,46.55698],[56.033741,46.56041],[56.032841,46.563221],[56.032211,46.565639],[56.031391,46.57016],[56.029469,46.585281],[56.028889,46.595551],[56.028278,46.6063],[56.027569,46.619801],[56.027309,46.626148],[56.027309,46.627911],[56.027512,46.629749],[56.027939,46.632141],[56.02964,46.639069],[56.031391,46.645939],[56.033852,46.656311],[56.034889,46.660709],[56.035099,46.66254],[56.036781,46.69265],[56.037251,46.697632],[56.0387,46.703979],[56.0387,46.707932],[56.037731,46.721489],[56.039558,46.728699],[56.042339,46.737801],[56.04314,46.746071],[56.04319,46.748631],[56.042961,46.750309],[56.041538,46.754669],[56.040661,46.758701],[56.040581,46.759079],[56.040421,46.759769],[56.03957,46.765049],[56.03772,46.77631],[56.036991,46.780369],[56.0368,46.78244],[56.036869,46.786209],[56.0392,46.803761],[56.039871,46.80917],[56.039822,46.810558],[56.038109,46.81823],[56.036789,46.824089],[56.036869,46.82579],[56.03714,46.826839],[56.038311,46.831009],[56.03957,46.835312],[56.041149,46.839378],[56.04311,46.844231],[56.043839,46.846352],[56.04438,46.848721],[56.045879,46.855339],[56.04665,46.8587],[56.047611,46.86174],[56.047932,46.86235],[56.049171,46.864792],[56.050739,46.868031],[56.05175,46.870609],[56.055851,46.88237],[56.05761,46.887409],[56.062759,46.901951],[56.064739,46.907742],[56.065029,46.90863],[56.06554,46.910461],[56.066238,46.912868],[56.066681,46.91515],[56.067039,46.91732],[56.067291,46.920391],[56.067451,46.923191],[56.067589,46.927719],[56.067719,46.931561],[56.068031,46.935589],[56.068279,46.938339],[56.068352,46.942348],[56.068211,46.946701],[56.068069,46.948849],[56.067928,46.951],[56.067291,46.957489],[56.06702,46.962231],[56.06741,46.966591],[56.070992,46.979061],[56.072788,46.985001],[56.07473,46.98983],[56.076599,46.994331],[56.078522,46.998268],[56.08009,46.9995],[56.08173,47.000271],[56.086712,47.000271],[56.09016,47.000099],[56.093441,47.00481],[56.09473,47.007542],[56.095901,47.010571],[56.097309,47.017738],[56.098011,47.021351],[56.099701,47.029541],[56.100319,47.031738],[56.10128,47.034081],[56.103828,47.039719],[56.105461,47.043171],[56.105839,47.043861],[56.106319,47.045059],[56.10738,47.05011],[56.107681,47.0527],[56.1077,47.055019],[56.107552,47.0574],[56.10709,47.06049],[56.1063,47.063309],[56.105301,47.065731],[56.101891,47.073051],[56.09856,47.08017],[56.097729,47.08242],[56.096951,47.085232],[56.095699,47.090679],[56.095421,47.092789],[56.095249,47.096661],[56.095261,47.102612],[56.095139,47.104542],[56.09481,47.107121],[56.094398,47.109299],[56.09375,47.11121],[56.093029,47.11285],[56.091702,47.11507],[56.091091,47.116089],[56.091,47.116241],[56.089619,47.118511],[56.085571,47.125172],[56.08503,47.125961],[56.084919,47.12611],[56.084301,47.126968],[56.082741,47.12915],[56.082001,47.130772],[56.081478,47.132332],[56.08107,47.13361],[56.08086,47.134651],[56.080711,47.135799],[56.080631,47.136902],[56.08065,47.137569],[56.0807,47.13879],[56.080799,47.140129],[56.080929,47.142139],[56.081001,47.145439],[56.080872,47.14772],[56.08075,47.149818],[56.079498,47.161301],[56.07925,47.163631],[56.07827,47.1726],[56.07814,47.17382],[56.07724,47.18169],[56.07579,47.192719],[56.07357,47.20916],[56.073471,47.20993],[56.073029,47.213341],[56.07275,47.215809],[56.072189,47.223049],[56.071972,47.22517],[56.071758,47.226429],[56.071571,47.227032],[56.071289,47.227921],[56.070801,47.228939],[56.070629,47.229309],[56.069908,47.23064],[56.068779,47.23275],[56.067348,47.235401],[56.06498,47.239841],[56.064011,47.242249],[56.063122,47.244579],[56.062851,47.245441],[56.062271,47.247372],[56.06118,47.251011],[56.056301,47.26749],[56.054482,47.273621],[56.053581,47.27618],[56.05265,47.278511],[56.05154,47.280701],[56.050781,47.282139],[56.05019,47.283138],[56.04969,47.283932],[56.048931,47.285118],[56.048679,47.285511],[56.04755,47.287201],[56.047009,47.287998],[56.04649,47.288818],[56.045841,47.289921],[56.044739,47.291401],[56.04414,47.291889],[56.042969,47.292278],[56.04179,47.292721],[56.039879,47.29364],[56.038231,47.294399],[56.037552,47.294621],[56.037109,47.294861],[56.03508,47.29686],[56.034489,47.29744],[56.03326,47.298691],[56.031361,47.300598],[56.030918,47.30106],[56.028469,47.303589],[56.027229,47.30484],[56.026321,47.305721],[56.025711,47.306198],[56.025188,47.306469],[56.023659,47.306641],[56.022579,47.306549],[56.02203,47.306499],[56.020481,47.306591],[56.019878,47.306801],[56.015999,47.308731],[56.01519,47.30917],[56.014252,47.309811],[56.01292,47.311291],[56.012001,47.31255],[56.006481,47.320141],[56.001209,47.327278],[55.999889,47.329128],[55.99604,47.335972],[55.995331,47.337238],[55.993549,47.340099],[55.991451,47.342548],[55.98999,47.34383],[55.988159,47.345169],[55.986809,47.346241],[55.981941,47.349789],[55.980881,47.35088],[55.979839,47.352501],[55.97887,47.3545],[55.977589,47.357769],[55.976109,47.361542],[55.975159,47.363609],[55.974258,47.36512],[55.973839,47.365681],[55.973351,47.36636],[55.972488,47.367199],[55.971161,47.368111],[55.967972,47.369289],[55.955429,47.373619],[55.954979,47.373798],[55.953979,47.37418],[55.952679,47.374729],[55.94875,47.376019],[55.946899,47.376781],[55.945938,47.377571],[55.943161,47.380451],[55.940948,47.38271],[55.939751,47.384411],[55.936741,47.389381],[55.935101,47.391281],[55.933262,47.392971],[55.93121,47.394451],[55.929211,47.395889],[55.927551,47.39724],[55.926399,47.398449],[55.9226,47.403091],[55.921741,47.404148],[55.920528,47.405579],[55.918819,47.40807],[55.91716,47.41069],[55.916698,47.411671],[55.916309,47.412498],[55.914101,47.418381],[55.913441,47.41946],[55.912418,47.420738],[55.908581,47.424839],[55.90633,47.426651],[55.901878,47.42955],[55.901161,47.430031],[55.895618,47.433651],[55.894421,47.434689],[55.892799,47.43697],[55.88855,47.443161],[55.888069,47.443851],[55.887871,47.44413],[55.88583,47.446899],[55.883289,47.45002],[55.88179,47.4515],[55.880421,47.452499],[55.879139,47.45322],[55.875099,47.455521],[55.873589,47.456379],[55.87035,47.45821],[55.867191,47.460121],[55.865879,47.460709],[55.864021,47.461391],[55.862419,47.46183],[55.86158,47.462151],[55.861351,47.462231],[55.859638,47.46286],[55.859451,47.462879],[55.859299,47.46291],[55.859112,47.462898],[55.85899,47.46286],[55.858898,47.46283],[55.858799,47.46283],[55.858669,47.462811],[55.858521,47.46286],[55.858379,47.462978],[55.85828,47.463181],[55.858189,47.463459],[55.85804,47.463772],[55.857811,47.46413],[55.856998,47.46505],[55.856281,47.466],[55.855221,47.467789],[55.854542,47.46933],[55.853779,47.471619],[55.853168,47.474701],[55.852329,47.47958],[55.851681,47.483719],[55.851299,47.48711],[55.851219,47.49049],[55.85128,47.498058],[55.851151,47.502029],[55.845791,47.519192],[55.838692,47.54253],[55.83746,47.545639],[55.83424,47.549709],[55.822781,47.554779],[55.822071,47.555401],[55.8214,47.55621],[55.82056,47.557529],[55.819908,47.55875],[55.819012,47.560822],[55.815189,47.571041],[55.81255,47.578011],[55.812,47.579971],[55.81171,47.581741],[55.81152,47.583],[55.811409,47.584469],[55.811451,47.59251],[55.811501,47.600479],[55.81134,47.603279],[55.81094,47.605721],[55.809799,47.61113],[55.809341,47.612709],[55.808788,47.614182],[55.807251,47.617229],[55.805641,47.62014],[55.804741,47.622139],[55.804001,47.624081],[55.796421,47.655689],[55.790298,47.67799],[55.790199,47.687599],[55.78907,47.721489],[55.788929,47.727829],[55.788792,47.732651],[55.788681,47.737221],[55.788841,47.739471],[55.788872,47.739948],[55.789661,47.75219],[55.791161,47.77618],[55.79425,47.819092],[55.796959,47.839352],[55.798401,47.845871],[55.799179,47.85342],[55.803902,47.910759],[55.809399,47.984749],[55.811138,48.006031],[55.809589,48.024609],[55.808731,48.035042],[55.808239,48.037788],[55.805061,48.045681],[55.796379,48.063881],[55.795891,48.068169],[55.79628,48.075378],[55.796959,48.099411],[55.797729,48.12001],[55.79744,48.122929],[55.79174,48.140961],[55.79081,48.14307],[55.787991,48.147861],[55.786129,48.151039],[55.785351,48.153011],[55.784908,48.154751],[55.784889,48.157612],[55.783482,48.167641],[55.783218,48.17033],[55.782959,48.17271],[55.78307,48.175579],[55.783562,48.181591],[55.7841,48.18906],[55.78397,48.1908],[55.7836,48.191669],[55.78286,48.19384],[55.78233,48.19453],[55.781609,48.194939],[55.77676,48.197281],[55.775921,48.197571],[55.774609,48.197338],[55.769562,48.195862],[55.767288,48.19524],[55.767208,48.195221],[55.766178,48.195019],[55.764969,48.195171],[55.763771,48.195541],[55.762272,48.19659],[55.76128,48.197472],[55.75486,48.20602],[55.754292,48.206829],[55.753349,48.20816],[55.751961,48.21014],[55.750992,48.212811],[55.748829,48.221031],[55.74847,48.222401],[55.74749,48.226292],[55.746792,48.228279],[55.745819,48.230492],[55.740162,48.241928],[55.736431,48.249859],[55.735241,48.252369],[55.734249,48.255829],[55.734001,48.25742],[55.73391,48.258011],[55.733479,48.260769],[55.733292,48.263561],[55.73196,48.28344],[55.729641,48.31657],[55.728531,48.33514],[55.726929,48.358971],[55.726551,48.365829],[55.727131,48.378361],[55.727901,48.391411],[55.728291,48.399479],[55.726261,48.420422],[55.72374,48.442909],[55.723259,48.449261],[55.72435,48.473381],[55.724442,48.475319],[55.724609,48.479351],[55.724628,48.479721],[55.724689,48.481239],[55.72472,48.481918],[55.724812,48.4837],[55.725609,48.501598],[55.726059,48.513119],[55.725769,48.521702],[55.723808,48.537479],[55.72298,48.544708],[55.722809,48.546188],[55.722778,48.546421],[55.722511,48.548721],[55.72242,48.549431],[55.72216,48.551521],[55.720852,48.56385],[55.71925,48.587608],[55.718788,48.594051],[55.71841,48.600231],[55.718651,48.60326],[55.71933,48.60606],[55.720329,48.608978],[55.721291,48.6115],[55.721859,48.61425],[55.722092,48.617691],[55.721741,48.621189],[55.720551,48.624641],[55.71751,48.632191],[55.71529,48.637199],[55.71262,48.64547],[55.710941,48.65123],[55.709511,48.659721],[55.709011,48.666119],[55.709049,48.672401],[55.70961,48.679729],[55.713921,48.70715],[55.71434,48.709961],[55.717049,48.726921],[55.720501,48.741638],[55.7239,48.750832],[55.726299,48.75732],[55.72715,48.759762],[55.73185,48.77322],[55.736031,48.781219],[55.73642,48.781841],[55.737579,48.783642],[55.738392,48.784809],[55.739342,48.786091],[55.740749,48.788021],[55.745781,48.794651],[55.75082,48.8013],[55.751629,48.80241],[55.752258,48.80331],[55.7528,48.804081],[55.756809,48.809929],[55.75943,48.813789],[55.76038,48.815289],[55.761608,48.817402],[55.76215,48.818352],[55.76366,48.821548],[55.76429,48.822929],[55.767189,48.830311],[55.767399,48.830799],[55.76833,48.832699],[55.769058,48.833981],[55.769821,48.835091],[55.770969,48.836609],[55.77169,48.837471],[55.77243,48.838051],[55.773232,48.838661],[55.774052,48.839119],[55.775669,48.839828],[55.776451,48.840069],[55.77763,48.84024],[55.77924,48.840401],[55.780281,48.84042],[55.78125,48.840401],[55.78252,48.84037],[55.79047,48.840889],[55.79126,48.840981],[55.79628,48.84124],[55.810371,48.842041],[55.81245,48.842159],[55.81451,48.842449],[55.817261,48.843128],[55.81889,48.843719],[55.82074,48.84462],[55.82346,48.8461],[55.824162,48.846531],[55.825279,48.84721],[55.826191,48.847801],[55.82811,48.848751],[55.82967,48.849312],[55.831299,48.849709],[55.842369,48.85191],[55.85397,48.854259],[55.857552,48.854969],[55.858131,48.855091],[55.858681,48.855209],[55.86179,48.85582],[55.862728,48.85601],[55.86491,48.85643],[55.866829,48.856758],[55.867088,48.856812],[55.86832,48.857052],[55.87402,48.85825],[55.874458,48.858341],[55.875801,48.85862],[55.87849,48.859192],[55.879089,48.859379],[55.879398,48.859482],[55.88028,48.859791],[55.881779,48.86042],[55.88269,48.86084],[55.883381,48.86121],[55.883549,48.861309],[55.884319,48.861851],[55.885052,48.86253],[55.885811,48.863361],[55.886429,48.86414],[55.886959,48.86504],[55.887611,48.866402],[55.889069,48.86982],[55.894341,48.882118],[55.89912,48.893269],[55.899479,48.89418],[55.899811,48.895111],[55.899948,48.895519],[55.900108,48.896061],[55.900341,48.896919],[55.900639,48.898281],[55.900841,48.899288],[55.90115,48.901321],[55.901241,48.90221],[55.90131,48.903439],[55.901371,48.908951],[55.901489,48.934219],[55.901569,48.94532],[55.901619,48.94698],[55.901718,48.94865],[55.901871,48.950539],[55.90263,48.958179],[55.903069,48.962841],[55.9035,48.96714],[55.903839,48.96991],[55.904228,48.972649],[55.904598,48.975201],[55.904678,48.975761],[55.904968,48.977859],[55.905239,48.98037],[55.905411,48.98254],[55.90551,48.984798],[55.90564,48.996738],[55.905651,48.997532],[55.905701,49.000679],[55.905739,49.002041],[55.905849,49.004139],[55.90646,49.01107],[55.90659,49.01252],[55.906952,49.016472],[55.907299,49.021412],[55.907688,49.028358],[55.90789,49.031841],[55.908131,49.03532],[55.909142,49.048611],[55.91011,49.061829],[55.91058,49.0681],[55.91304,49.10125],[55.913399,49.105782],[55.91375,49.108921],[55.914108,49.111359],[55.915451,49.11953],[55.917259,49.13028],[55.917542,49.13213],[55.917751,49.13401],[55.917919,49.136051],[55.918011,49.138062],[55.918079,49.140659],[55.918079,49.140942],[55.918079,49.141891],[55.91806,49.14267],[55.918011,49.143711],[55.91785,49.14669],[55.91774,49.14798],[55.917671,49.148739],[55.91758,49.149448],[55.9175,49.15007],[55.91737,49.150928],[55.917122,49.15247],[55.91684,49.153858],[55.916649,49.1548],[55.916538,49.155289],[55.916382,49.15575],[55.91571,49.157372],[55.91449,49.15987],[55.914261,49.160358],[55.913288,49.162361],[55.913029,49.16288],[55.91275,49.163441],[55.911339,49.166302],[55.909439,49.17012],[55.90852,49.171951],[55.907379,49.17429],[55.90675,49.175739],[55.9063,49.177059],[55.906059,49.177879],[55.903801,49.187191],[55.90324,49.189468],[55.902882,49.19091],[55.90094,49.197899],[55.899979,49.20108],[55.897701,49.208038],[55.89743,49.20879],[55.896938,49.210251],[55.896599,49.211151],[55.896229,49.212002],[55.895828,49.212769],[55.895222,49.21386],[55.891121,49.220089],[55.88998,49.22205],[55.889542,49.22287],[55.88913,49.223881],[55.887421,49.229141],[55.887131,49.230061],[55.88678,49.231129],[55.885368,49.235481],[55.883381,49.241539],[55.88155,49.247051],[55.880661,49.249741],[55.880192,49.25145],[55.879341,49.255569],[55.87923,49.256111],[55.879009,49.257191],[55.87899,49.25724],[55.878139,49.261341],[55.877831,49.262829],[55.875278,49.275089],[55.874748,49.277889],[55.874599,49.279041],[55.87447,49.280949],[55.874432,49.281898],[55.874409,49.282921],[55.874451,49.286308],[55.874409,49.287281],[55.874321,49.288139],[55.874249,49.288631],[55.874149,49.289082],[55.873909,49.28989],[55.87376,49.290329],[55.873589,49.290722],[55.87318,49.291531],[55.872768,49.292179],[55.868851,49.297501],[55.864491,49.303478],[55.864029,49.304119],[55.863571,49.304741],[55.8629,49.305691],[55.862179,49.306919],[55.8615,49.30843],[55.861099,49.30941],[55.86034,49.311329],[55.856941,49.320042],[55.855289,49.3242],[55.85498,49.32497],[55.854019,49.327141],[55.852772,49.329521],[55.8521,49.330669],[55.85125,49.33194],[55.849388,49.334419],[55.84597,49.33873],[55.845089,49.339859],[55.842171,49.343578],[55.841888,49.343948],[55.839329,49.347221],[55.83844,49.348289],[55.837448,49.349178],[55.83709,49.349449],[55.83672,49.34967],[55.835918,49.350029],[55.835232,49.350281],[55.8344,49.350449],[55.833851,49.350479],[55.833279,49.35046],[55.827381,49.349319],[55.82436,49.348759],[55.820412,49.347988],[55.817551,49.347408],[55.814449,49.34679],[55.80788,49.345421],[55.806519,49.34499],[55.805069,49.34449],[55.80228,49.34269],[55.801941,49.342461],[55.801262,49.341991],[55.800152,49.34124],[55.79987,49.34111],[55.79977,49.341061],[55.798828,49.34063],[55.79855,49.34053],[55.797771,49.340229],[55.796341,49.33971],[55.795601,49.339581],[55.79493,49.33939],[55.794128,49.339191],[55.79306,49.338909],[55.790668,49.338329],[55.78896,49.338009],[55.787819,49.337959],[55.786671,49.338039],[55.7854,49.33828],[55.784168,49.338711],[55.7826,49.339481],[55.781071,49.340549],[55.77916,49.342152],[55.777271,49.34399],[55.775661,49.345612],[55.770809,49.350368],[55.768848,49.352299],[55.766171,49.354881],[55.764488,49.356651],[55.76366,49.35759],[55.762871,49.35865],[55.761959,49.360008],[55.761108,49.361549],[55.760429,49.363079],[55.75985,49.36475],[55.759171,49.367229],[55.75901,49.367901],[55.75864,49.369801],[55.758389,49.371201],[55.75779,49.375252],[55.757118,49.379761],[55.756821,49.38129],[55.7565,49.382751],[55.7561,49.384159],[55.755611,49.38562],[55.755081,49.386921],[55.75423,49.388512],[55.75375,49.389259],[55.753201,49.38998],[55.75185,49.391521],[55.750408,49.392879],[55.74662,49.396191],[55.74567,49.396999],[55.74464,49.397919],[55.742962,49.399429],[55.73914,49.402771],[55.737881,49.4039],[55.736629,49.405258],[55.735451,49.406811],[55.734341,49.40852],[55.733452,49.410141],[55.732689,49.41172],[55.731949,49.41349],[55.73106,49.416012],[55.72821,49.42469],[55.72747,49.426868],[55.72681,49.429169],[55.726109,49.432178],[55.72559,49.435211],[55.723309,49.454868],[55.721859,49.467388],[55.721828,49.468811],[55.721088,49.475471],[55.72084,49.47847],[55.72049,49.48299],[55.720322,49.48457],[55.71999,49.486889],[55.719212,49.491779],[55.71891,49.494171],[55.717731,49.504021],[55.715759,49.51825],[55.715542,49.520241],[55.715351,49.522381],[55.71505,49.526329],[55.714691,49.529739],[55.714272,49.53249],[55.713779,49.535],[55.712921,49.539001],[55.71228,49.543491],[55.711769,49.546242],[55.711349,49.548149],[55.710831,49.550201],[55.710312,49.55209],[55.70977,49.553822],[55.709358,49.55508],[55.708321,49.557899],[55.707878,49.559269],[55.70607,49.565182],[55.704769,49.56871],[55.703491,49.57159],[55.70248,49.57373],[55.700901,49.577671],[55.698959,49.58271],[55.698479,49.58408],[55.698391,49.584381],[55.697769,49.58646],[55.697399,49.588139],[55.697121,49.589901],[55.696781,49.593609],[55.69672,49.596779],[55.696941,49.60041],[55.69894,49.620121],[55.699268,49.623772],[55.699329,49.626282],[55.699429,49.63052],[55.699188,49.635651],[55.699131,49.636211],[55.698631,49.6409],[55.697899,49.645988],[55.697361,49.6493],[55.696671,49.652451],[55.695919,49.655079],[55.694691,49.658611],[55.6931,49.662861],[55.692421,49.66433],[55.686729,49.673569],[55.68568,49.675289],[55.682789,49.680199],[55.681389,49.682941],[55.680019,49.68642],[55.677219,49.69487],[55.676929,49.695751],[55.67514,49.701241],[55.674641,49.702789],[55.673882,49.70512],[55.67276,49.708469],[55.671028,49.713631],[55.670712,49.714882],[55.670368,49.716511],[55.670109,49.718151],[55.66991,49.719311],[55.669762,49.721729],[55.669689,49.725491],[55.66991,49.728981],[55.670898,49.735821],[55.67218,49.744549],[55.676151,49.77142],[55.677071,49.778099],[55.677879,49.78434],[55.679729,49.806068],[55.680698,49.81786],[55.68087,49.821381],[55.680851,49.824558],[55.680698,49.82822],[55.680328,49.832458],[55.67968,49.837151],[55.678848,49.840969],[55.67778,49.84499],[55.675209,49.852699],[55.669899,49.868599],[55.66441,49.884682],[55.662361,49.890949],[55.661579,49.89394],[55.661129,49.896309],[55.66074,49.898891],[55.6605,49.901852],[55.66032,49.90493],[55.66037,49.908569],[55.66069,49.91169],[55.6618,49.924728],[55.661781,49.929359],[55.661308,49.934101],[55.66082,49.93692],[55.660252,49.939541],[55.65942,49.942471],[55.652618,49.964859],[55.650421,49.9725],[55.650299,49.972931],[55.646881,49.98391],[55.64555,49.98941],[55.644489,49.996422],[55.644161,50.000069],[55.644138,50.000751],[55.644032,50.004379],[55.644161,50.009281],[55.64423,50.010761],[55.645821,50.02383],[55.649719,50.05447],[55.653332,50.083469],[55.65374,50.08638],[55.654129,50.088669],[55.654652,50.091179],[55.655239,50.093651],[55.656609,50.098728],[55.657021,50.100281],[55.65707,50.100449],[55.661041,50.11528],[55.663261,50.123562],[55.664349,50.12772],[55.665371,50.13192],[55.668301,50.14389],[55.669769,50.149879],[55.670509,50.15292],[55.67086,50.15456],[55.67112,50.15593],[55.67136,50.157249],[55.671612,50.159081],[55.672039,50.162979],[55.672371,50.166901],[55.67392,50.186131],[55.6749,50.19799],[55.67572,50.20845],[55.67588,50.20982],[55.676208,50.212551],[55.676651,50.215321],[55.676979,50.217072],[55.67733,50.218658],[55.678268,50.22224],[55.681259,50.23251],[55.684158,50.24255],[55.687481,50.253929],[55.690571,50.264641],[55.691029,50.266361],[55.691422,50.268101],[55.691738,50.269581],[55.692032,50.271111],[55.692532,50.274361],[55.696041,50.307381],[55.696362,50.31065],[55.696678,50.313869],[55.69672,50.31422],[55.697319,50.32008],[55.697498,50.322521],[55.697578,50.324661],[55.697609,50.32692],[55.697601,50.328941],[55.697521,50.330891],[55.697411,50.33284],[55.697239,50.334782],[55.69635,50.344231],[55.695911,50.348961],[55.695419,50.354191],[55.69521,50.356339],[55.690521,50.406368],[55.688931,50.423382],[55.68734,50.440971],[55.686909,50.447571],[55.686771,50.45068],[55.686459,50.468208],[55.686249,50.480068],[55.68605,50.492432],[55.685509,50.524719],[55.685299,50.53756],[55.685349,50.540649],[55.685429,50.54372],[55.68549,50.54525],[55.685581,50.54636],[55.686039,50.549801],[55.686821,50.554131],[55.687618,50.558208],[55.688141,50.561829],[55.68832,50.563541],[55.688499,50.566299],[55.68853,50.568859],[55.688549,50.570358],[55.688499,50.572529],[55.688351,50.57476],[55.68792,50.579449],[55.68745,50.583328],[55.68634,50.59124],[55.685959,50.593609],[55.685711,50.594891],[55.685169,50.596901],[55.684582,50.598881],[55.68396,50.60078],[55.683239,50.602749],[55.682251,50.605331],[55.681309,50.607971],[55.680618,50.610081],[55.68,50.61237],[55.679581,50.614182],[55.67915,50.616341],[55.678841,50.618198],[55.678539,50.620289],[55.67601,50.641548],[55.675159,50.648911],[55.675049,50.650261],[55.6749,50.652691],[55.674831,50.654949],[55.67482,50.657501],[55.67487,50.65955],[55.674999,50.662289],[55.67524,50.66497],[55.675529,50.667419],[55.675892,50.669891],[55.676929,50.675911],[55.677311,50.67804],[55.677631,50.679859],[55.678249,50.683979],[55.678711,50.687851],[55.678951,50.690338],[55.679119,50.692928],[55.679279,50.696079],[55.679291,50.699471],[55.677898,50.740601],[55.677589,50.748569],[55.677399,50.75116],[55.67709,50.753811],[55.676601,50.757061],[55.675961,50.760399],[55.675301,50.763119],[55.674541,50.7659],[55.6731,50.77002],[55.67226,50.77206],[55.670979,50.774719],[55.657162,50.800831],[55.653919,50.80698],[55.652611,50.80941],[55.651291,50.812],[55.65049,50.813931],[55.64954,50.81675],[55.648701,50.82],[55.64806,50.823479],[55.64769,50.826519],[55.64753,50.82851],[55.647369,50.83252],[55.646912,50.845772],[55.64653,50.855751],[55.645721,50.876942],[55.645618,50.87822],[55.64547,50.879902],[55.645351,50.88089],[55.64489,50.883621],[55.64452,50.88567],[55.644138,50.887661],[55.64341,50.89093],[55.641479,50.897221],[55.640289,50.90099],[55.63921,50.90485],[55.638802,50.906441],[55.638439,50.90807],[55.63805,50.910309],[55.637718,50.912609],[55.63747,50.91502],[55.637211,50.918209],[55.63657,50.928921],[55.636181,50.935612],[55.63575,50.943008],[55.635681,50.94548],[55.6357,50.948002],[55.63588,50.951729],[55.636238,50.955761],[55.636669,50.958931],[55.64035,50.980049],[55.642658,50.9935],[55.64296,50.995331],[55.643372,50.99828],[55.643719,51.00169],[55.64389,51.00452],[55.643951,51.007172],[55.643959,51.00975],[55.643959,51.012459],[55.644058,51.045509],[55.644169,51.047729],[55.64426,51.049591],[55.64455,51.051651],[55.64481,51.052929],[55.645081,51.054119],[55.645432,51.055191],[55.645721,51.055988],[55.646141,51.056919],[55.64666,51.057919],[55.647259,51.05896],[55.648029,51.060108],[55.64978,51.062431],[55.651482,51.064861],[55.652489,51.066429],[55.65332,51.068008],[55.654209,51.07019],[55.654709,51.07193],[55.655071,51.073841],[55.65519,51.07539],[55.655231,51.076809],[55.655201,51.07851],[55.654999,51.08028],[55.654659,51.082531],[55.65414,51.085091],[55.653461,51.08786],[55.652431,51.091888],[55.652142,51.093651],[55.651909,51.095669],[55.651859,51.09763],[55.651951,51.098869],[55.652279,51.100891],[55.652721,51.102619],[55.65324,51.104309],[55.655621,51.110699],[55.656132,51.112202],[55.656609,51.11422],[55.65707,51.11644],[55.65733,51.118481],[55.65736,51.119492],[55.657299,51.123192],[55.6572,51.124001],[55.656769,51.127159],[55.656479,51.128868],[55.655319,51.134979],[55.65453,51.139481],[55.65419,51.14172],[55.653759,51.145229],[55.653679,51.14616],[55.65345,51.149071],[55.653511,51.152081],[55.65374,51.15472],[55.654388,51.158871],[55.65506,51.16201],[55.65617,51.16552],[55.660042,51.17598],[55.661221,51.179111],[55.66349,51.186131],[55.665001,51.19173],[55.665798,51.195229],[55.66663,51.19968],[55.667809,51.207119],[55.66964,51.221359],[55.671249,51.234001],[55.671398,51.235371],[55.6717,51.2383],[55.67186,51.240551],[55.671921,51.242199],[55.671921,51.243191],[55.671909,51.244572],[55.67178,51.24646],[55.671631,51.247921],[55.671429,51.249191],[55.671162,51.250542],[55.670811,51.251888],[55.670368,51.2533],[55.6693,51.25629],[55.66856,51.258011],[55.665871,51.263908],[55.665352,51.265091],[55.66431,51.2677],[55.66396,51.268631],[55.663422,51.270229],[55.663052,51.271381],[55.662579,51.273159],[55.66235,51.27433],[55.662182,51.275089],[55.6619,51.27692],[55.66177,51.277821],[55.661591,51.279369],[55.661449,51.281639],[55.661331,51.284241],[55.66127,51.286369],[55.661259,51.287922],[55.661282,51.293129],[55.661301,51.295361],[55.661388,51.30225],[55.66135,51.304352],[55.661129,51.308788],[55.660969,51.311001],[55.660889,51.31181],[55.66048,51.314831],[55.660172,51.316669],[55.656269,51.33997],[55.65115,51.370121],[55.650101,51.376541],[55.64996,51.37743],[55.64954,51.37999],[55.64949,51.38031],[55.64912,51.38258],[55.648979,51.383911],[55.64893,51.384609],[55.648899,51.386002],[55.64896,51.387772],[55.649071,51.389061],[55.64941,51.39122],[55.649799,51.393108],[55.650059,51.39418],[55.650391,51.39518],[55.65134,51.396999],[55.65202,51.398102],[55.652679,51.398991],[55.653431,51.399872],[55.656631,51.402611],[55.657398,51.403191],[55.658329,51.403831],[55.661049,51.405479],[55.66185,51.406189],[55.66246,51.406811],[55.66296,51.407379],[55.66349,51.40807],[55.663818,51.40855],[55.66394,51.40873],[55.664612,51.40992],[55.665001,51.41077],[55.66539,51.4118],[55.66584,51.41317],[55.666321,51.414791],[55.66888,51.423191],[55.66972,51.4259],[55.67144,51.43161],[55.671909,51.433189],[55.672352,51.43462],[55.677689,51.452171],[55.67905,51.45612],[55.680439,51.459789],[55.68087,51.4608],[55.682091,51.463509],[55.6828,51.465],[55.68573,51.470791],[55.688469,51.476189],[55.689339,51.477989],[55.690701,51.481079],[55.690971,51.481758],[55.69199,51.48439],[55.693562,51.48893],[55.695011,51.493679],[55.695518,51.495628],[55.695889,51.497108],[55.70332,51.531422],[55.706501,51.5462],[55.706989,51.548721],[55.7075,51.55143],[55.708221,51.555592],[55.70882,51.559441],[55.709221,51.562199],[55.709591,51.565022],[55.7099,51.567551],[55.710339,51.571621],[55.711189,51.58115],[55.71254,51.596439],[55.712711,51.599602],[55.712811,51.60178],[55.712841,51.60294],[55.712849,51.60466],[55.712799,51.607578],[55.7122,51.624611],[55.712151,51.62603],[55.712101,51.627251],[55.711441,51.644531],[55.711319,51.64764],[55.711281,51.650318],[55.711288,51.652691],[55.711349,51.655529],[55.711559,51.659061],[55.7117,51.66074],[55.71188,51.662609],[55.712219,51.665421],[55.71246,51.66711],[55.71402,51.676769],[55.71463,51.679581],[55.715221,51.681911],[55.71693,51.687439],[55.718941,51.69244],[55.719601,51.694069],[55.720299,51.695671],[55.721561,51.698292],[55.721901,51.69891],[55.722099,51.699261],[55.72261,51.700039],[55.723381,51.701118],[55.72575,51.70401],[55.726799,51.705551],[55.727711,51.70739],[55.73074,51.71487],[55.731682,51.717339],[55.732731,51.72094],[55.73333,51.723331],[55.733871,51.725269],[55.734291,51.726639],[55.735668,51.730011],[55.736431,51.731579],[55.737579,51.733879],[55.738319,51.735439],[55.738831,51.736679],[55.739491,51.73859],[55.739899,51.739891],[55.74033,51.741421],[55.742481,51.75071],[55.743118,51.753731],[55.746429,51.768318],[55.748341,51.776112],[55.752659,51.790218],[55.759251,51.811508],[55.7607,51.815601],[55.762489,51.819321],[55.764339,51.822701],[55.766369,51.82571],[55.772129,51.832142],[55.77663,51.837151],[55.778831,51.839802],[55.780842,51.842659],[55.782471,51.84565],[55.78384,51.848549],[55.785179,51.851929],[55.786469,51.855801],[55.787449,51.859379],[55.788342,51.86385],[55.79689,51.908421],[55.797081,51.909882],[55.797611,51.916401],[55.79763,51.918541],[55.79763,51.9207],[55.7976,51.92284],[55.797409,51.927021],[55.797329,51.928532],[55.79726,51.930019],[55.797081,51.93383],[55.7971,51.934799],[55.79718,51.936218],[55.797249,51.937019],[55.797352,51.937721],[55.797501,51.938511],[55.79768,51.939339],[55.79784,51.93996],[55.797989,51.940491],[55.798161,51.941002],[55.798321,51.941448],[55.79866,51.942322],[55.79887,51.942741],[55.799332,51.9436],[55.799671,51.944172],[55.807259,51.956848],[55.807739,51.957722],[55.808239,51.95879],[55.808701,51.959949],[55.808979,51.96093],[55.813591,51.980122],[55.813961,51.981949],[55.814171,51.983379],[55.81432,51.985371],[55.814339,51.98695],[55.814251,51.998631],[55.814232,52.000389],[55.813709,52.06361],[55.81366,52.069031],[55.813648,52.070789],[55.81361,52.075951],[55.813301,52.108681],[55.81324,52.11496],[55.81319,52.1203],[55.813122,52.121632],[55.812851,52.123539],[55.812431,52.125431],[55.811821,52.12714],[55.811001,52.128849],[55.80444,52.139221],[55.803692,52.140442],[55.783829,52.171841],[55.783279,52.17284],[55.782768,52.174129],[55.782219,52.176041],[55.781929,52.17728],[55.781521,52.179192],[55.781361,52.18087],[55.781311,52.182621],[55.781311,52.183571],[55.781399,52.185379],[55.781429,52.186661],[55.781429,52.188091],[55.781399,52.188881],[55.78133,52.189789],[55.78125,52.190899],[55.781189,52.191502],[55.781132,52.192032],[55.78101,52.19265],[55.780819,52.193741],[55.780529,52.194908],[55.780361,52.195518],[55.78014,52.19622],[55.779881,52.196972],[55.779598,52.19767],[55.77927,52.19833],[55.778961,52.198971],[55.778599,52.199551],[55.77718,52.202],[55.77422,52.207008],[55.771309,52.211922],[55.76897,52.215889],[55.76841,52.216808],[55.766151,52.2206],[55.765202,52.222229],[55.759621,52.23164],[55.75816,52.234112],[55.757721,52.234821],[55.756699,52.236328],[55.75634,52.236832],[55.755852,52.2374],[55.755569,52.237671],[55.755348,52.237869],[55.75518,52.237999],[55.754238,52.238701],[55.75383,52.23904],[55.753559,52.239319],[55.7533,52.239639],[55.752312,52.240871],[55.751579,52.241791],[55.75127,52.242111],[55.75106,52.24229],[55.750519,52.242691],[55.749741,52.24321],[55.73579,52.251579],[55.727631,52.256451],[55.725208,52.2579],[55.72377,52.258781],[55.7234,52.25906],[55.722851,52.25956],[55.720501,52.262089],[55.720291,52.262321],[55.717449,52.265339],[55.71051,52.273041],[55.709721,52.273708],[55.709179,52.274078],[55.708549,52.274391],[55.703751,52.276489],[55.69817,52.278881],[55.69619,52.27977],[55.695301,52.280201],[55.693359,52.281471],[55.692009,52.282261],[55.69125,52.282619],[55.690701,52.282829],[55.690102,52.28297],[55.689499,52.283031],[55.689041,52.283051],[55.68858,52.28299],[55.68829,52.282959],[55.687962,52.282848],[55.68729,52.2826],[55.686741,52.282341],[55.68317,52.279949],[55.682301,52.279339],[55.682011,52.279148],[55.681671,52.278999],[55.681419,52.27898],[55.681149,52.27903],[55.68087,52.27919],[55.68074,52.279301],[55.680401,52.279739],[55.680061,52.280331],[55.679749,52.28075],[55.679111,52.281368],[55.67849,52.28191],[55.677841,52.282661],[55.677471,52.283279],[55.675369,52.28727],[55.674358,52.289181],[55.673279,52.29121],[55.673019,52.291721],[55.672562,52.292591],[55.672119,52.29343],[55.670609,52.296329],[55.67033,52.29686],[55.668861,52.299648],[55.66848,52.300381],[55.668339,52.30064],[55.667721,52.301811],[55.667461,52.30241],[55.667068,52.303429],[55.66674,52.304699],[55.666561,52.30563],[55.666439,52.30658],[55.66637,52.30748],[55.66637,52.308411],[55.666401,52.309368],[55.66655,52.310638],[55.666729,52.311661],[55.6674,52.314411],[55.668072,52.317181],[55.6684,52.318241],[55.668812,52.319221],[55.67284,52.32666],[55.675659,52.33189],[55.67635,52.33313],[55.676819,52.333981],[55.677719,52.335609],[55.677879,52.335911],[55.68063,52.340981],[55.68615,52.351101],[55.690151,52.35844],[55.69622,52.369579],[55.69659,52.370281],[55.696629,52.370338],[55.699631,52.375858],[55.69989,52.376339],[55.700821,52.37804],[55.70174,52.379749],[55.701801,52.379841],[55.702808,52.38171],[55.7033,52.382549],[55.703899,52.383709],[55.704239,52.384331],[55.704979,52.385731],[55.705872,52.387321],[55.707142,52.389622],[55.707169,52.389671],[55.707378,52.39027],[55.70742,52.39061],[55.707409,52.39093],[55.707371,52.39156],[55.707409,52.392189],[55.707409,52.39275],[55.707321,52.39315],[55.707191,52.393452],[55.706982,52.39381],[55.706039,52.39542],[55.705978,52.395531],[55.70512,52.396999],[55.704239,52.398479],[55.70282,52.400879],[55.701019,52.403938],[55.70005,52.405579],[55.69923,52.406952],[55.697472,52.40995],[55.696301,52.411949],[55.69445,52.415131],[55.68821,52.4258],[55.68763,52.42662],[55.68729,52.426929],[55.686039,52.427731],[55.685669,52.428059],[55.68531,52.428501],[55.68504,52.428982],[55.68483,52.429401],[55.684631,52.430019],[55.684139,52.43232],[55.68396,52.432941],[55.683769,52.433361],[55.68354,52.43383],[55.682079,52.436249],[55.67815,52.44297],[55.67725,52.444481],[55.676971,52.44495],[55.67622,52.446251],[55.675152,52.448051],[55.674011,52.45002],[55.670921,52.455299],[55.67057,52.455898],[55.670471,52.456181],[55.670429,52.45647],[55.67049,52.456779],[55.670609,52.457119],[55.67086,52.4576],[55.678631,52.471859],[55.682621,52.479179],[55.685921,52.485222],[55.685619,52.485741],[55.685261,52.486542],[55.685101,52.486881],[55.684761,52.487549],[55.682831,52.49123],[55.679352,52.497681],[55.677639,52.50095],[55.67712,52.50198],[55.67664,52.503071],[55.676079,52.504501],[55.675571,52.505939],[55.675209,52.50713],[55.67466,52.509109],[55.673908,52.511829],[55.673679,52.512699],[55.673489,52.513561],[55.67337,52.51432],[55.673328,52.514912],[55.673271,52.516418],[55.673241,52.517658],[55.67305,52.523499],[55.67292,52.528938],[55.67281,52.532299],[55.672661,52.537601],[55.6726,52.538269],[55.672451,52.539371],[55.672199,52.54076],[55.671501,52.543941],[55.670971,52.545891],[55.669621,52.54969],[55.667969,52.554371],[55.66539,52.563148],[55.66473,52.564739],[55.66301,52.56778],[55.662319,52.569321],[55.66164,52.571339],[55.658588,52.58429],[55.65654,52.593121],[55.655369,52.597691],[55.654362,52.601082],[55.65126,52.60873],[55.64576,52.622341],[55.643822,52.62743],[55.643391,52.628719],[55.643169,52.630539],[55.643108,52.63242],[55.64323,52.634209],[55.64381,52.641621],[55.645309,52.66272],[55.645321,52.665001],[55.645222,52.667549],[55.64325,52.682449],[55.642529,52.68782],[55.639309,52.712391],[55.637852,52.722641],[55.63607,52.733749],[55.635971,52.73761],[55.636169,52.743118],[55.636471,52.751598],[55.63649,52.754292],[55.636131,52.761169],[55.636269,52.7631],[55.63707,52.766842],[55.637798,52.77449],[55.63829,52.77763],[55.642929,52.80006],[55.643501,52.805939],[55.644241,52.815681],[55.644779,52.822552],[55.645939,52.83707],[55.646069,52.838692],[55.64642,52.84306],[55.64658,52.846931],[55.64695,52.849682],[55.64827,52.855042],[55.648991,52.85799],[55.65287,52.873421],[55.653889,52.876011],[55.65781,52.884899],[55.660789,52.892078],[55.661629,52.894821],[55.670052,52.921558],[55.674309,52.934212],[55.67485,52.935478],[55.682678,52.952129],[55.68465,52.958199],[55.691521,52.978222],[55.692421,52.981289],[55.69302,52.983971],[55.693562,52.987148],[55.694321,52.993038],[55.697681,53.011028],[55.69928,53.01918],[55.704781,53.040829],[55.70789,53.052311],[55.710011,53.059601],[55.710178,53.060631],[55.71014,53.061729],[55.709648,53.064369],[55.70866,53.068539],[55.70723,53.072842],[55.704472,53.079929],[55.702789,53.08424],[55.699131,53.093811],[55.694149,53.106819],[55.692871,53.110142],[55.676922,53.151619],[55.668449,53.173512],[55.660149,53.195129],[55.65966,53.196121],[55.650101,53.21085],[55.637341,53.230019],[55.628769,53.23912],[55.62315,53.245098],[55.619541,53.248459],[55.61657,53.250809],[55.613331,53.253071],[55.61142,53.255001],[55.60989,53.256939],[55.608349,53.259449],[55.60717,53.261848],[55.604401,53.268929],[55.598129,53.284931],[55.594898,53.292999],[55.581131,53.328781],[55.564869,53.370869],[55.550812,53.406952],[55.550091,53.40863],[55.548779,53.41198],[55.547771,53.415569],[55.547058,53.419151],[55.546749,53.420689],[55.546619,53.422409],[55.54705,53.434429],[55.548222,53.464298],[55.548389,53.46764],[55.54985,53.48539],[55.549969,53.487419],[55.5499,53.488548],[55.549671,53.489529],[55.548119,53.49712],[55.546909,53.503609],[55.542259,53.530602],[55.542068,53.531681],[55.541752,53.53487],[55.5392,53.56073],[55.53825,53.570389],[55.537701,53.575939],[55.537392,53.57917],[55.537182,53.580139],[55.536591,53.582211],[55.53326,53.59341],[55.53297,53.594631],[55.530918,53.608089],[55.530819,53.609329],[55.53083,53.610641],[55.531311,53.619499],[55.531189,53.622349],[55.52932,53.64687],[55.526699,53.66592],[55.524429,53.682209],[55.52264,53.694988],[55.52021,53.711361],[55.516571,53.739811],[55.514339,53.75666],[55.513729,53.76046],[55.51334,53.76226],[55.512871,53.763851],[55.51223,53.765751],[55.509541,53.773739],[55.508492,53.777111],[55.502892,53.803589],[55.50111,53.811771],[55.494579,53.834061],[55.490639,53.84745],[55.490189,53.849079],[55.489601,53.852291],[55.489239,53.856819],[55.48904,53.864101],[55.488972,53.867031],[55.488731,53.870461],[55.48848,53.87254],[55.488159,53.875191],[55.48772,53.878819],[55.48727,53.880661],[55.48658,53.882549],[55.484219,53.88773],[55.48243,53.892479],[55.481289,53.895081],[55.47945,53.898918],[55.477989,53.901131],[55.474831,53.90564],[55.47131,53.911831],[55.467682,53.918968],[55.46714,53.92078],[55.466629,53.923649],[55.466049,53.92635],[55.465599,53.927929],[55.46487,53.929932],[55.462429,53.936199],[55.461441,53.938709],[55.460609,53.941231],[55.460091,53.95723],[55.459911,53.962921],[55.45985,53.964741],[55.46014,53.965679],[55.47105,53.991089],[55.471519,53.992229],[55.47184,53.99353],[55.475712,54.01577],[55.477589,54.025909],[55.47768,54.02668],[55.477581,54.027409],[55.476978,54.029301],[55.47562,54.033089],[55.472099,54.042679],[55.46788,54.054298],[55.467541,54.055519],[55.466969,54.062222],[55.466251,54.07093],[55.46756,54.08437],[55.468208,54.091629],[55.469379,54.104031],[55.46936,54.105049],[55.4678,54.12318],[55.466782,54.134659],[55.466579,54.13686],[55.466011,54.138771],[55.465939,54.14032],[55.465542,54.151291],[55.465172,54.16132],[55.464439,54.181629],[55.464352,54.183262],[55.464069,54.18449],[55.46048,54.194721],[55.459839,54.19688],[55.458569,54.201759],[55.45583,54.212189],[55.45314,54.222198],[55.452351,54.22514],[55.450249,54.235771],[55.44936,54.240509],[55.448101,54.2467],[55.445122,54.260769],[55.443291,54.26936],[55.441669,54.277119],[55.440521,54.28236],[55.439941,54.285179],[55.43869,54.291149],[55.43848,54.292141],[55.437771,54.29549],[55.437672,54.29628],[55.437771,54.297291],[55.439812,54.306301],[55.440399,54.30888],[55.440369,54.309509],[55.44022,54.31002],[55.439949,54.31076],[55.438702,54.314041],[55.438412,54.315071],[55.438278,54.31609],[55.43832,54.317341],[55.438801,54.32312],[55.43996,54.328449],[55.440269,54.330811],[55.440929,54.33857],[55.441071,54.341572],[55.44125,54.354111],[55.44125,54.35651],[55.441471,54.37236],[55.441689,54.39426],[55.441898,54.396351],[55.443249,54.399651],[55.44857,54.412609],[55.453491,54.424721],[55.457619,54.434971],[55.459049,54.438339],[55.464409,54.449371],[55.472149,54.465191],[55.472691,54.466339],[55.473259,54.46796],[55.479778,54.48851],[55.48167,54.494282],[55.482269,54.4963],[55.482269,54.49688],[55.482208,54.497639],[55.480141,54.523861],[55.480061,54.52449],[55.479851,54.52504],[55.47739,54.529381],[55.477249,54.529961],[55.477139,54.531151],[55.476219,54.541729],[55.474201,54.56496],[55.472179,54.588112],[55.470009,54.602631],[55.46994,54.603722],[55.470009,54.60487],[55.47002,54.606098],[55.4697,54.607128],[55.466881,54.614262],[55.466309,54.615631],[55.465858,54.61721],[55.46109,54.641659],[55.45863,54.65427],[55.450989,54.692638],[55.448528,54.705078],[55.44825,54.706329],[55.447842,54.707321],[55.443432,54.714001],[55.44199,54.716171],[55.441441,54.717289],[55.44091,54.71899],[55.437439,54.732639],[55.436798,54.736691],[55.433289,54.762531],[55.429932,54.788712],[55.42807,54.804649],[55.42786,54.8064],[55.42186,54.808319],[55.415779,54.813831],[55.40538,54.82312],[55.403271,54.82542],[55.40086,54.828671],[55.397289,54.834862],[55.386391,54.854118],[55.380249,54.864861],[55.369701,54.8834],[55.358471,54.902908],[55.35318,54.912109],[55.351509,54.91544],[55.349781,54.919559],[55.342049,54.93811],[55.3386,54.946571],[55.336929,54.950459],[55.336231,54.951691],[55.334591,54.954632],[55.3298,54.96291],[55.312511,54.993309],[55.311871,54.994419],[55.308102,55.000999],[55.30405,55.008072],[55.3022,55.010731],[55.28294,55.035019],[55.279598,55.03928],[55.268822,55.05315],[55.267792,55.054459],[55.26683,55.05555],[55.265709,55.05661],[55.252621,55.067379],[55.25045,55.069149],[55.243279,55.07502],[55.224491,55.089691],[55.207741,55.103001],[55.199909,55.10997],[55.1982,55.111778],[55.19545,55.11475],[55.191879,55.118969],[55.19067,55.1203],[55.18932,55.12162],[55.186298,55.12389],[55.183521,55.125851],[55.181499,55.127331],[55.18042,55.128021],[55.179428,55.12838],[55.177521,55.12801],[55.16737,55.125011],[55.165501,55.124741],[55.164558,55.124889],[55.16367,55.125469],[55.16188,55.12706],[55.161518,55.127361],[55.160049,55.12886],[55.158371,55.131279],[55.155941,55.135269],[55.153461,55.1399],[55.15033,55.145969],[55.150051,55.146511],[55.149441,55.14777],[55.14867,55.149139],[55.14415,55.1558],[55.143341,55.15712],[55.142609,55.158779],[55.139751,55.16539],[55.138371,55.168598],[55.137951,55.169781],[55.1376,55.17123],[55.137371,55.173859],[55.1362,55.20266],[55.1362,55.205269],[55.13681,55.21809],[55.13707,55.223808],[55.137791,55.240391],[55.138359,55.25322],[55.138321,55.255421],[55.137699,55.262341],[55.136608,55.274231],[55.135632,55.28524],[55.135288,55.288342],[55.134731,55.2915],[55.133968,55.29459],[55.133099,55.297482],[55.132069,55.30043],[55.13176,55.301201],[55.131229,55.302311],[55.130878,55.30302],[55.12941,55.305309],[55.12796,55.307301],[55.126549,55.30899],[55.12381,55.311699],[55.11132,55.323582],[55.110668,55.324211],[55.108189,55.3265],[55.10717,55.327438],[55.105671,55.328819],[55.10144,55.332741],[55.09919,55.334999],[55.097191,55.336868],[55.09584,55.338089],[55.09359,55.34045],[55.092049,55.342411],[55.090729,55.344521],[55.089588,55.346729],[55.087269,55.35218],[55.08271,55.362839],[55.082249,55.36393],[55.081749,55.365261],[55.080891,55.36813],[55.080441,55.369781],[55.079609,55.37392],[55.07925,55.376831],[55.079079,55.37896],[55.079021,55.381001],[55.07909,55.384651],[55.079231,55.388241],[55.079262,55.388969],[55.079369,55.391682],[55.07935,55.394051],[55.07914,55.395279],[55.07906,55.395779],[55.078541,55.397449],[55.071011,55.4119],[55.0662,55.418678],[55.058552,55.429279],[55.056671,55.431881],[55.055168,55.433979],[55.054169,55.435371],[55.047668,55.444351],[55.043839,55.448471],[55.039921,55.452671],[55.036121,55.45673],[55.031078,55.462132],[55.02993,55.463169],[55.025261,55.46817],[55.022678,55.47121],[55.015419,55.479031],[55.011471,55.48325],[55.00721,55.487881],[55.005341,55.489841],[55.004292,55.490971],[55.00346,55.49194],[54.99976,55.498241],[54.998421,55.50032],[54.99715,55.502731],[54.995659,55.505291],[54.994041,55.508141],[54.992279,55.511211],[54.990582,55.51408],[54.990299,55.514549],[54.98629,55.521851],[54.985031,55.524109],[54.98386,55.526711],[54.982948,55.52956],[54.982239,55.53286],[54.981892,55.534679],[54.981621,55.536919],[54.9813,55.544868],[54.980869,55.552792],[54.980659,55.555901],[54.980492,55.557461],[54.980221,55.559052],[54.979321,55.562901],[54.97818,55.566582],[54.976959,55.569439],[54.975311,55.57222],[54.974522,55.573341],[54.973621,55.574402],[54.971722,55.576469],[54.971329,55.576859],[54.96925,55.57906],[54.96706,55.58123],[54.96434,55.583359],[54.963219,55.584129],[54.9617,55.584751],[54.960991,55.58493],[54.960312,55.585121],[54.95866,55.585331],[54.95718,55.585369],[54.955688,55.58519],[54.954731,55.58482],[54.95295,55.584179],[54.95126,55.583809],[54.94902,55.583092],[54.936508,55.579128],[54.929699,55.576931],[54.928501,55.576672],[54.927219,55.576641],[54.925781,55.57695],[54.924301,55.57769],[54.92363,55.578098],[54.922749,55.578892],[54.921341,55.580318],[54.920849,55.581131],[54.917332,55.586761],[54.912281,55.594929],[54.91058,55.598148],[54.909321,55.601109],[54.90807,55.604259],[54.907341,55.60648],[54.907028,55.607632],[54.906559,55.60955],[54.906288,55.611069],[54.904819,55.617901],[54.904518,55.619251],[54.904251,55.620491],[54.903919,55.623051],[54.90332,55.625488],[54.90237,55.628021],[54.89941,55.632771],[54.897282,55.636261],[54.895359,55.639481],[54.89484,55.640339],[54.893181,55.64394],[54.892159,55.646889],[54.891472,55.649391],[54.890732,55.652821],[54.88763,55.66811],[54.884869,55.681709],[54.88084,55.701359],[54.8797,55.707031],[54.879181,55.708351],[54.878559,55.709251],[54.877338,55.710411],[54.876289,55.710949],[54.875462,55.710911],[54.87104,55.70813],[54.868149,55.70644],[54.865608,55.705261],[54.86319,55.704411],[54.860741,55.703659],[54.859039,55.70335],[54.85738,55.70327],[54.85548,55.703381],[54.853649,55.703701],[54.851921,55.704239],[54.850761,55.704659],[54.849751,55.70525],[54.848782,55.70591],[54.84721,55.70734],[54.845921,55.708721],[54.844639,55.710331],[54.84071,55.715698],[54.836929,55.72089],[54.8363,55.72171],[54.834869,55.72319],[54.833141,55.72448],[54.83075,55.725441],[54.825741,55.726768],[54.824032,55.72728],[54.82127,55.728668],[54.819839,55.729481],[54.817902,55.73098],[54.81694,55.731861],[54.81477,55.734138],[54.812309,55.73679],[54.802979,55.746792],[54.800652,55.749561],[54.799351,55.751381],[54.79845,55.752991],[54.796921,55.75589],[54.795879,55.758228],[54.794369,55.761349],[54.79351,55.763039],[54.79216,55.76535],[54.79192,55.765701],[54.79015,55.768139],[54.787418,55.77142],[54.78384,55.775379],[54.782242,55.777538],[54.78157,55.77866],[54.780529,55.780682],[54.77985,55.782009],[54.77916,55.783081],[54.778511,55.783878],[54.777679,55.78474],[54.776909,55.78529],[54.775822,55.785759],[54.773682,55.785789],[54.767872,55.784031],[54.767189,55.783829],[54.763988,55.78289],[54.759991,55.781792],[54.75808,55.781342],[54.756199,55.781139],[54.754761,55.781101],[54.752392,55.781139],[54.750481,55.781422],[54.745941,55.782139],[54.742882,55.7826],[54.74194,55.782761],[54.737862,55.783428],[54.73595,55.783138],[54.73439,55.78228],[54.73304,55.78133],[54.727871,55.777618],[54.726528,55.777081],[54.72509,55.776852],[54.722149,55.776829],[54.716301,55.776749],[54.71484,55.776451],[54.713188,55.77586],[54.702301,55.769932],[54.701519,55.769451],[54.699902,55.768169],[54.698761,55.76675],[54.69836,55.76622],[54.697201,55.763741],[54.696548,55.762081],[54.694908,55.75774],[54.692669,55.752022],[54.692101,55.750641],[54.690891,55.748219],[54.689869,55.746479],[54.686829,55.74213],[54.682739,55.736439],[54.68071,55.733608],[54.67926,55.731918],[54.678429,55.73122],[54.677441,55.730518],[54.675678,55.72998],[54.67395,55.73003],[54.672249,55.730549],[54.667721,55.733021],[54.66748,55.733139],[54.665081,55.734409],[54.6642,55.734871],[54.66375,55.734989],[54.663479,55.73489],[54.663288,55.73465],[54.663139,55.734032],[54.66317,55.733631],[54.663349,55.733261],[54.66354,55.73307],[54.663929,55.73312],[54.664181,55.733551],[54.664421,55.734371],[54.664551,55.735081],[54.664921,55.737061],[54.66534,55.73914],[54.666069,55.743031],[54.67001,55.764301],[54.672119,55.77565],[54.673309,55.782028],[54.674702,55.79158],[54.67527,55.79491],[54.67614,55.799492],[54.676418,55.80175],[54.67643,55.802879],[54.67638,55.804379],[54.676319,55.80537],[54.676239,55.806561],[54.67598,55.809849],[54.675838,55.811871],[54.67556,55.81443],[54.67535,55.81543],[54.674171,55.820782],[54.672138,55.82967],[54.669331,55.841999],[54.66674,55.853401],[54.665531,55.858742],[54.6642,55.864491],[54.66288,55.870319],[54.66124,55.87759],[54.659679,55.8843],[54.65884,55.887218],[54.65807,55.88958],[54.657139,55.89201],[54.656559,55.893372],[54.655449,55.89584],[54.65424,55.89856],[54.65205,55.903351],[54.650982,55.905739],[54.649849,55.90834],[54.649391,55.90958],[54.648708,55.911469],[54.648022,55.913471],[54.647282,55.916161],[54.646801,55.918159],[54.6465,55.919479],[54.645939,55.922279],[54.645641,55.924271],[54.64521,55.926781],[54.6451,55.927639],[54.644539,55.930771],[54.64452,55.93137],[54.644321,55.932629],[54.644161,55.933701],[54.643681,55.937119],[54.643181,55.94035],[54.64291,55.942261],[54.642731,55.943569],[54.642559,55.94508],[54.642441,55.946609],[54.642399,55.947449],[54.642368,55.94833],[54.642349,55.949909],[54.64238,55.951591],[54.64246,55.95335],[54.64257,55.955132],[54.643391,55.967979],[54.643871,55.974979],[54.644112,55.9758],[54.645401,55.995911],[54.645649,55.999821],[54.64595,56.004421],[54.646801,56.017712],[54.64777,56.032749],[54.648731,56.047531],[54.649361,56.057251],[54.649399,56.057941],[54.650101,56.068951],[54.65044,56.074249],[54.650661,56.07782],[54.650669,56.078011],[54.650871,56.080952],[54.65089,56.081348],[54.65107,56.08419],[54.651089,56.08453],[54.651299,56.087551],[54.651409,56.08976],[54.652229,56.102268],[54.65279,56.10857],[54.653149,56.11108],[54.654079,56.115681],[54.654282,56.116501],[54.654678,56.118099],[54.655411,56.120739],[54.65723,56.127541],[54.659191,56.134892],[54.660511,56.139309],[54.662338,56.144741],[54.665249,56.153381],[54.66642,56.15691],[54.668629,56.16354],[54.672539,56.17519],[54.67445,56.180859],[54.675129,56.182831],[54.6763,56.185509],[54.677559,56.18787],[54.678829,56.18977],[54.681629,56.19302],[54.685379,56.1973],[54.687679,56.199921],[54.69323,56.206329],[54.69767,56.211479],[54.700779,56.21513],[54.70499,56.220051],[54.70713,56.222591],[54.70863,56.224312],[54.719292,56.236759],[54.72155,56.239792],[54.722988,56.242111],[54.724621,56.244949],[54.72646,56.248669],[54.728119,56.25267],[54.729301,56.255981],[54.730671,56.26046],[54.732208,56.266048],[54.73465,56.274929],[54.737309,56.284599],[54.740238,56.29528],[54.741459,56.299759],[54.742451,56.30331],[54.74308,56.305641],[54.743328,56.306549],[54.744011,56.309292],[54.744431,56.310799],[54.745178,56.313339],[54.746929,56.319698],[54.74913,56.327782],[54.75127,56.335579],[54.751911,56.337952],[54.752621,56.34087],[54.753189,56.343601],[54.75383,56.347221],[54.754681,56.352612],[54.755508,56.357979],[54.757141,56.368118],[54.758308,56.375591],[54.759369,56.38224],[54.760269,56.387981],[54.761181,56.393742],[54.76202,56.399109],[54.763481,56.408401],[54.764179,56.412868],[54.764912,56.417439],[54.766361,56.426579],[54.767849,56.436069],[54.769329,56.44548],[54.77029,56.451439],[54.77095,56.455681],[54.771599,56.459869],[54.772919,56.467838],[54.773529,56.471001],[54.77557,56.48167],[54.779339,56.501308],[54.782982,56.520302],[54.784142,56.526348],[54.78595,56.535759],[54.786251,56.537338],[54.786739,56.539989],[54.788971,56.551559],[54.791481,56.564621],[54.793541,56.575432],[54.7953,56.584549],[54.796471,56.590401],[54.802078,56.612301],[54.80304,56.616119],[54.80336,56.617279],[54.804211,56.620689],[54.80545,56.625519],[54.806412,56.629318],[54.807411,56.63324],[54.80817,56.636829],[54.808491,56.63871],[54.80912,56.643742],[54.809792,56.649261],[54.810619,56.656109],[54.811432,56.662949],[54.812271,56.66996],[54.813332,56.67894],[54.813869,56.683289],[54.81422,56.686359],[54.814671,56.69001],[54.815281,56.69503],[54.81559,56.697639],[54.81612,56.702271],[54.81625,56.703381],[54.816319,56.70443],[54.816441,56.706532],[54.816559,56.709141],[54.816639,56.714771],[54.816681,56.722599],[54.816738,56.729401],[54.81675,56.730419],[54.816799,56.73798],[54.81686,56.749969],[54.816921,56.757],[54.816921,56.757542],[54.81715,56.793861],[54.817181,56.799141],[54.817402,56.839279],[54.81752,56.863491],[54.817558,56.866192],[54.817768,56.868931],[54.818138,56.871922],[54.818588,56.874352],[54.81926,56.877159],[54.820061,56.87973],[54.82132,56.88287],[54.825951,56.893631],[54.826462,56.894989],[54.82671,56.896278],[54.8269,56.89827],[54.826988,56.900848],[54.827091,56.903469],[54.827251,56.90778],[54.827751,56.91758],[54.828339,56.922459],[54.82917,56.927349],[54.82991,56.93148],[54.830528,56.935371],[54.83102,56.939499],[54.831219,56.942089],[54.83136,56.944679],[54.83186,56.96133],[54.832298,56.976261],[54.832489,56.981819],[54.832611,56.98418],[54.832748,56.98595],[54.832909,56.987659],[54.841751,57.05891],[54.842751,57.066971],[54.845871,57.092319],[54.846611,57.098259],[54.847,57.1012],[54.847179,57.10244],[54.847271,57.103039],[54.847351,57.1035],[54.847511,57.104221],[54.847729,57.105179],[54.850578,57.11689],[54.85368,57.12962],[54.853931,57.13068],[54.856098,57.13966],[54.857651,57.146091],[54.859219,57.152538],[54.860199,57.156212],[54.86039,57.156841],[54.860592,57.157551],[54.86079,57.158089],[54.860989,57.15863],[54.861271,57.15929],[54.86327,57.164169],[54.865829,57.170479],[54.870941,57.183079],[54.873699,57.189919],[54.874222,57.191341],[54.874599,57.192589],[54.87492,57.193729],[54.875172,57.19487],[54.875389,57.19598],[54.87561,57.197201],[54.875809,57.198551],[54.87598,57.199921],[54.876228,57.20211],[54.879848,57.23526],[54.883839,57.271709],[54.88488,57.281361],[54.885391,57.286228],[54.885761,57.289349],[54.886009,57.291],[54.88623,57.29237],[54.88662,57.29438],[54.88707,57.296478],[54.887661,57.298771],[54.888168,57.30069],[54.888451,57.30154],[54.88868,57.30225],[54.88908,57.30341],[54.889408,57.304249],[54.889931,57.305592],[54.890362,57.306591],[54.89061,57.307152],[54.891491,57.309158],[54.893631,57.313969],[54.8983,57.324348],[54.90033,57.328899],[54.902451,57.333641],[54.902882,57.334629],[54.903229,57.33551],[54.903599,57.336491],[54.904221,57.338348],[54.904751,57.340061],[54.90514,57.341339],[54.905849,57.343498],[54.905949,57.344791],[54.907589,57.352791],[54.90855,57.35762],[54.909931,57.364521],[54.910099,57.365318],[54.911282,57.370911],[54.911678,57.372929],[54.911949,57.37447],[54.91214,57.375969],[54.912251,57.37751],[54.912239,57.379021],[54.91217,57.380489],[54.912048,57.382011],[54.911758,57.385181],[54.911671,57.386372],[54.911621,57.38739],[54.91164,57.388378],[54.911709,57.389439],[54.9118,57.390491],[54.911961,57.391682],[54.912128,57.392632],[54.912338,57.393501],[54.912579,57.394428],[54.913738,57.398151],[54.915539,57.40395],[54.915821,57.404789],[54.916302,57.406052],[54.916759,57.40707],[54.91745,57.40836],[54.918049,57.409409],[54.91856,57.410229],[54.91906,57.410919],[54.919621,57.41161],[54.920891,57.412979],[54.92168,57.41362],[54.922581,57.41423],[54.922661,57.41428],[54.923611,57.414799],[54.92411,57.415031],[54.924591,57.415218],[54.92514,57.41539],[54.925991,57.41552],[54.927502,57.41568],[54.928959,57.415852],[54.930241,57.41597],[54.931141,57.416088],[54.931541,57.41621],[54.93187,57.41637],[54.932251,57.416611],[54.932732,57.416939],[54.93317,57.417301],[54.933681,57.417839],[54.934261,57.418579],[54.934978,57.419701],[54.936569,57.422218],[54.9384,57.425159],[54.93906,57.42614],[54.93964,57.426949],[54.940189,57.42765],[54.940929,57.42841],[54.941841,57.429161],[54.942799,57.429859],[54.943611,57.430462],[54.944111,57.430882],[54.944618,57.431351],[54.945148,57.431881],[54.945789,57.432579],[54.946369,57.433239],[54.946819,57.4338],[54.94735,57.434559],[54.947849,57.43528],[54.948238,57.435871],[54.948559,57.43642],[54.94891,57.437119],[54.94923,57.438049],[54.949471,57.43898],[54.94981,57.44046],[54.951229,57.4473],[54.952629,57.454121],[54.953041,57.456089],[54.953308,57.45726],[54.953541,57.458179],[54.953732,57.458931],[54.953999,57.459751],[54.9543,57.46064],[54.954609,57.46146],[54.95499,57.46244],[54.955421,57.463322],[54.95623,57.46487],[54.956848,57.465889],[54.95752,57.466869],[54.959419,57.469212],[54.961609,57.471859],[54.964561,57.476082],[54.966679,57.479179],[54.96748,57.480358],[54.967831,57.480942],[54.968151,57.48151],[54.96851,57.482231],[54.969051,57.48349],[54.969601,57.484901],[54.969872,57.48568],[54.970131,57.48679],[54.970421,57.488289],[54.971851,57.496109],[54.973801,57.507069],[54.9743,57.509739],[54.974812,57.51218],[54.976761,57.520279],[54.97905,57.529819],[54.980228,57.53471],[54.980942,57.537682],[54.981831,57.541401],[54.982738,57.5452],[54.983238,57.547199],[54.983589,57.54863],[54.98391,57.54998],[54.984211,57.551189],[54.984638,57.553089],[54.985069,57.555191],[54.98534,57.556782],[54.986221,57.562389],[54.987881,57.573261],[54.989071,57.58107],[54.990009,57.587139],[54.990292,57.588848],[54.99073,57.59108],[54.991402,57.594082],[54.991611,57.594971],[54.991829,57.595711],[54.9921,57.596432],[54.992481,57.597321],[54.993031,57.598309],[54.99374,57.599461],[54.99625,57.603321],[54.996559,57.603901],[54.99678,57.604401],[54.997028,57.605068],[54.997261,57.60582],[54.997509,57.606812],[54.997761,57.60796],[54.99929,57.614929],[54.999401,57.615528],[54.999569,57.616638],[54.99963,57.617451],[54.999649,57.61824],[54.999619,57.619141],[54.999561,57.62038],[54.999458,57.621529],[54.999352,57.622421],[54.999161,57.62368],[54.998989,57.625019],[54.99894,57.62561],[54.998909,57.626289],[54.998932,57.626961],[54.999008,57.627781],[54.999111,57.628422],[54.999241,57.628922],[55.00016,57.631901],[55.000332,57.632721],[55.000439,57.63356],[55.000511,57.63483],[55.00053,57.636471],[55.00045,57.640511],[55.00042,57.641621],[55.000351,57.64259],[55.00021,57.643822],[55.00005,57.64492],[54.999748,57.646561],[54.999561,57.647572],[54.99942,57.648769],[54.999329,57.649891],[54.999298,57.6511],[54.999359,57.652069],[54.999569,57.65411],[54.99979,57.655891],[55.00016,57.658321],[55.000462,57.65979],[55.00074,57.660851],[55.00108,57.66193],[55.002369,57.66563],[55.00433,57.671101],[55.00518,57.67347],[55.005989,57.675831],[55.006229,57.676601],[55.00647,57.677422],[55.006779,57.678558],[55.00705,57.679668],[55.00732,57.68092],[55.007439,57.681728],[55.0075,57.682461],[55.007542,57.683418],[55.007561,57.684841],[55.007568,57.686138],[55.007542,57.687408],[55.007469,57.688499],[55.007381,57.689579],[55.007271,57.690868],[55.006889,57.69455],[55.006748,57.69582],[55.006229,57.701149],[55.006039,57.703571],[55.005871,57.70657],[55.005852,57.70681],[55.00584,57.70705],[55.0056,57.711048],[55.005508,57.711979],[55.005371,57.712799],[55.004532,57.716129],[55.004219,57.716888],[55.003811,57.71769],[55.003349,57.718189],[55.002869,57.718571],[55.002399,57.7188],[55.00169,57.718868],[55.001129,57.71875],[55.000629,57.718449],[55.00013,57.71801],[54.99934,57.71719],[54.998329,57.71587],[54.99786,57.715302],[54.99728,57.71468],[54.996689,57.71402],[54.996109,57.713409],[54.995838,57.713181],[54.99559,57.713032],[54.99535,57.712971],[54.995129,57.712978],[54.994869,57.713051],[54.994678,57.713169],[54.994511,57.713322],[54.994339,57.713558],[54.994171,57.71394],[54.994041,57.71434],[54.993969,57.71484],[54.993961,57.71534],[54.99408,57.71619],[54.994362,57.71743],[54.994888,57.719109],[54.995029,57.71981],[54.995121,57.720612],[54.99514,57.721199],[54.995071,57.721741],[54.99469,57.723579],[54.992451,57.73497],[54.99155,57.739571],[54.99041,57.745319],[54.986382,57.765751],[54.98336,57.777149],[54.982868,57.77919],[54.9827,57.780079],[54.982578,57.781471],[54.982521,57.7831],[54.982521,57.784019],[54.9827,57.78746],[54.982929,57.791069],[54.983139,57.794201],[54.983219,57.79554],[54.983261,57.79657],[54.98328,57.79734],[54.983231,57.798279],[54.98299,57.79966],[54.982281,57.802799],[54.981541,57.806122],[54.980991,57.80854],[54.980259,57.811661],[54.980068,57.812382],[54.97966,57.813519],[54.979259,57.81432],[54.978779,57.815109],[54.978222,57.815849],[54.977699,57.816441],[54.977139,57.81702],[54.975739,57.81852],[54.974232,57.82011],[54.97271,57.821732],[54.971359,57.823158],[54.970249,57.824379],[54.969761,57.82505],[54.96928,57.825802],[54.96904,57.826241],[54.96875,57.82695],[54.968449,57.827839],[54.968182,57.828892],[54.967529,57.832352],[54.965641,57.842831],[54.965321,57.846352],[54.965778,57.850979],[54.9683,57.866692],[54.96925,57.87114],[54.97163,57.87743],[54.97298,57.884399],[54.97345,57.88818],[54.973621,57.891861],[54.973221,57.896992],[54.971889,57.90617],[54.971489,57.90847],[54.971142,57.910809],[54.971001,57.911911],[54.970871,57.913189],[54.97076,57.914551],[54.97068,57.915878],[54.970631,57.917332],[54.970612,57.918831],[54.970772,57.925819],[54.970879,57.931122],[54.971111,57.93475],[54.970661,57.93922],[54.968941,57.954922],[54.968201,57.96059],[54.967072,57.96685],[54.966282,57.97089],[54.962391,57.982052],[54.959461,57.98822],[54.95628,57.993069],[54.947769,58.001431],[54.94186,58.00684],[54.93618,58.012051],[54.929489,58.01952],[54.922199,58.028999],[54.920761,58.031719],[54.919991,58.035351],[54.918999,58.04007],[54.91861,58.044579],[54.919621,58.05241],[54.919849,58.055222],[54.919689,58.057919],[54.918949,58.061138],[54.91687,58.066639],[54.914459,58.072941],[54.914261,58.07449],[54.914009,58.07719],[54.914108,58.080021],[54.91412,58.083241],[54.913422,58.08646],[54.910488,58.09568],[54.909309,58.099461],[54.90794,58.10371],[54.907349,58.105831],[54.90641,58.109039],[54.905319,58.111012],[54.904041,58.113071],[54.90316,58.115429],[54.90276,58.118912],[54.902111,58.122169],[54.901131,58.125],[54.89925,58.12878],[54.897621,58.13118],[54.896839,58.133331],[54.896439,58.137531],[54.896599,58.142029],[54.89621,58.14418],[54.896099,58.144779],[54.894371,58.152939],[54.8923,58.160568],[54.88839,58.16972],[54.877441,58.192841],[54.87616,58.19817],[54.87537,58.20314],[54.875019,58.205891],[54.872601,58.227779],[54.86969,58.252331],[54.86937,58.25486],[54.868851,58.257912],[54.86615,58.263439],[54.859852,58.274681],[54.85759,58.27953],[54.8568,58.282619],[54.855759,58.28717],[54.855221,58.2901],[54.855209,58.293781],[54.85516,58.296181],[54.854931,58.297989],[54.85429,58.300251],[54.85218,58.303909],[54.851109,58.30648],[54.85067,58.31023],[54.851349,58.315891],[54.852242,58.322498],[54.853432,58.328251],[54.855499,58.334511],[54.857578,58.339748],[54.860001,58.346272],[54.86356,58.359058],[54.864639,58.361889],[54.865711,58.363682],[54.866711,58.365101],[54.868511,58.367081],[54.870312,58.368992],[54.871632,58.370708],[54.87188,58.37104],[54.87233,58.371769],[54.87291,58.372799],[54.873981,58.375439],[54.875271,58.37883],[54.875259,58.378799],[54.87561,58.37991],[54.875881,58.381222],[54.876209,58.38335],[54.876369,58.38538],[54.876419,58.38731],[54.876549,58.388569],[54.876701,58.38958],[54.876888,58.39056],[54.87957,58.398319],[54.88208,58.405579],[54.88253,58.406719],[54.88303,58.407761],[54.883709,58.408772],[54.88446,58.409649],[54.884811,58.410118],[54.885071,58.410519],[54.885342,58.41114],[54.885609,58.41198],[54.88562,58.41209],[54.88588,58.413651],[54.885891,58.413731],[54.885941,58.414082],[54.886341,58.416908],[54.886429,58.4179],[54.886471,58.41938],[54.886478,58.420269],[54.88649,58.420891],[54.88662,58.423191],[54.88681,58.425011],[54.887581,58.43187],[54.88773,58.433399],[54.887829,58.434341],[54.887871,58.434719],[54.887932,58.435169],[54.88805,58.43618],[54.888119,58.43681],[54.888599,58.440239],[54.88921,58.444561],[54.88932,58.44585],[54.88929,58.447071],[54.889229,58.44799],[54.889091,58.44886],[54.888939,58.449711],[54.888691,58.450562],[54.888458,58.451302],[54.88821,58.451981],[54.88789,58.45269],[54.887508,58.453259],[54.886829,58.454208],[54.88588,58.45509],[54.884529,58.456032],[54.882469,58.457481],[54.881641,58.458061],[54.88073,58.458912],[54.88039,58.45937],[54.880058,58.459999],[54.876789,58.467121],[54.87598,58.469059],[54.87574,58.470112],[54.87542,58.47274],[54.875141,58.474892],[54.87492,58.475681],[54.874619,58.47641],[54.87336,58.47868],[54.871059,58.481972],[54.87067,58.482498],[54.869678,58.48386],[54.868858,58.485409],[54.868279,58.48671],[54.867729,58.488331],[54.867222,58.490761],[54.86694,58.492859],[54.866859,58.49493],[54.866859,58.4967],[54.867031,58.498428],[54.867279,58.500332],[54.868,58.505741],[54.86858,58.510281],[54.868698,58.512032],[54.86861,58.513531],[54.868351,58.51495],[54.867569,58.517971],[54.867329,58.519619],[54.867149,58.521931],[54.867031,58.524361],[54.86684,58.526409],[54.86652,58.528271],[54.865879,58.53072],[54.865391,58.532169],[54.864849,58.533569],[54.864231,58.534939],[54.86356,58.536221],[54.862251,58.53828],[54.860821,58.540161],[54.860008,58.54134],[54.859348,58.54269],[54.858711,58.544571],[54.85836,58.545929],[54.858109,58.547569],[54.857948,58.549541],[54.857922,58.558102],[54.858021,58.59304],[54.85812,58.601959],[54.858089,58.603661],[54.858028,58.607029],[54.857792,58.612381],[54.856152,58.65015],[54.856312,58.65461],[54.857529,58.67363],[54.8578,58.677269],[54.858101,58.67989],[54.85878,58.68224],[54.862438,58.69508],[54.86359,58.69994],[54.864601,58.708519],[54.865471,58.714401],[54.86536,58.716499],[54.864891,58.71854],[54.862438,58.724091],[54.8615,58.726311],[54.861301,58.726791],[54.861118,58.727341],[54.86076,58.72858],[54.86063,58.729568],[54.86055,58.730579],[54.860531,58.731232],[54.86055,58.73188],[54.860729,58.733189],[54.860821,58.733551],[54.861,58.734329],[54.861229,58.73505],[54.8615,58.735748],[54.861801,58.736431],[54.8633,58.739399],[54.864861,58.7425],[54.86726,58.747711],[54.86792,58.749409],[54.868431,58.75082],[54.86969,58.754509],[54.87112,58.75959],[54.872021,58.763599],[54.872471,58.766411],[54.873249,58.77142],[54.873669,58.77515],[54.874531,58.78252],[54.87529,58.78838],[54.875992,58.794739],[54.877651,58.804951],[54.87949,58.812359],[54.880798,58.817051],[54.881649,58.820202],[54.88184,58.8209],[54.882408,58.823139],[54.88818,58.84444],[54.889549,58.849411],[54.891258,58.85582],[54.89296,58.862019],[54.894009,58.865898],[54.895599,58.87178],[54.896351,58.874321],[54.897129,58.87656],[54.897869,58.87851],[54.898602,58.88028],[54.900181,58.883518],[54.90126,58.885422],[54.902088,58.886688],[54.90332,58.888519],[54.904209,58.88969],[54.905102,58.890732],[54.906528,58.892269],[54.90789,58.893501],[54.90921,58.894581],[54.916771,58.89999],[54.919979,58.902191],[54.921471,58.903381],[54.922241,58.904099],[54.922901,58.9048],[54.92342,58.905418],[54.923889,58.90612],[54.924431,58.906921],[54.92514,58.908249],[54.925701,58.909481],[54.926109,58.910461],[54.92659,58.911919],[54.926949,58.913349],[54.92717,58.914471],[54.927391,58.91584],[54.92757,58.91724],[54.927689,58.918709],[54.9277,58.92009],[54.927662,58.922642],[54.927521,58.92664],[54.927521,58.928459],[54.92762,58.930641],[54.92783,58.932461],[54.928108,58.93409],[54.928509,58.935711],[54.929001,58.937309],[54.929451,58.938568],[54.92981,58.939369],[54.930222,58.940151],[54.930569,58.94088],[54.93317,58.945461],[54.933681,58.946121],[54.9342,58.946751],[54.93483,58.947361],[54.935421,58.94783],[54.936131,58.948261],[54.93689,58.948669],[54.937778,58.948921],[54.938148,58.949032],[54.939041,58.949299],[54.941181,58.949848],[54.94286,58.950291],[54.948559,58.951759],[54.95015,58.952301],[54.951408,58.95293],[54.952469,58.953609],[54.953579,58.954441],[54.955879,58.95702],[54.956718,58.95816],[54.957458,58.959309],[54.95826,58.96077],[54.958961,58.962231],[54.960209,58.96526],[54.964561,58.97612],[54.966148,58.979691],[54.96846,58.98386],[54.971909,58.99012],[54.980068,59.004581],[54.98201,59.00872],[54.98317,59.011841],[54.984291,59.01524],[54.988029,59.02697],[54.988899,59.02961],[54.989639,59.031521],[54.990528,59.033482],[54.991428,59.03516],[54.992359,59.036671],[54.993172,59.037769],[54.995762,59.04158],[54.996811,59.043549],[54.997601,59.04528],[54.998409,59.047291],[54.998871,59.048698],[54.99931,59.050179],[54.999981,59.053009],[55.000969,59.05806],[55.001591,59.06147],[55.001881,59.063049],[55.002171,59.064411],[55.002541,59.0658],[55.002892,59.066929],[55.00325,59.067959],[55.003639,59.069],[55.004219,59.07024],[55.004688,59.071232],[55.00515,59.072071],[55.005798,59.073101],[55.00671,59.074471],[55.007648,59.075871],[55.009418,59.078602],[55.009991,59.07967],[55.010441,59.080662],[55.010929,59.081841],[55.012039,59.085289],[55.012371,59.08654],[55.012691,59.087978],[55.012901,59.089668],[55.013199,59.092682],[55.013451,59.095551],[55.013618,59.097679],[55.014332,59.106461],[55.014641,59.108871],[55.01498,59.110481],[55.01545,59.112091],[55.015831,59.11319],[55.016281,59.114239],[55.01688,59.115341],[55.017479,59.116329],[55.018269,59.11747],[55.019199,59.11871],[55.02042,59.120419],[55.020988,59.12122],[55.022541,59.123219],[55.02383,59.124649],[55.024811,59.125702],[55.025921,59.12674],[55.027531,59.128071],[55.032501,59.13216],[55.03307,59.132671],[55.034271,59.133629],[55.034901,59.134151],[55.038521,59.137138],[55.04015,59.138451],[55.04047,59.138741],[55.0415,59.139599],[55.04211,59.140049],[55.042591,59.140411],[55.044239,59.141479],[55.048489,59.144131],[55.050339,59.145309],[55.0509,59.145729],[55.0513,59.14603],[55.051731,59.14637],[55.05204,59.146629],[55.052319,59.14687],[55.05254,59.147079],[55.05278,59.147301],[55.053009,59.14753],[55.05452,59.149109],[55.059559,59.15451],[55.059799,59.154812],[55.059978,59.155022],[55.0602,59.155281],[55.06039,59.155529],[55.060558,59.15575],[55.060749,59.15601],[55.060982,59.156349],[55.061241,59.156769],[55.061508,59.157219],[55.062092,59.15831],[55.062199,59.158562],[55.06229,59.158798],[55.062382,59.159039],[55.062721,59.160069],[55.062908,59.16066],[55.06308,59.161221],[55.06321,59.161732],[55.063381,59.16238],[55.063568,59.163151],[55.063931,59.16457],[55.064159,59.16555],[55.064491,59.166882],[55.064751,59.167938],[55.065479,59.17107],[55.066669,59.17609],[55.068981,59.18594],[55.069931,59.18998],[55.07061,59.193001],[55.071239,59.19614],[55.071812,59.19902],[55.07225,59.2015],[55.073051,59.206139],[55.074249,59.21299],[55.07515,59.2183],[55.07552,59.220089],[55.076321,59.223579],[55.077019,59.226261],[55.07766,59.228409],[55.078308,59.230431],[55.078972,59.232281],[55.081261,59.238392],[55.08535,59.249168],[55.087631,59.255032],[55.0886,59.25729],[55.089062,59.258221],[55.089828,59.259731],[55.090889,59.26157],[55.09185,59.262989],[55.09269,59.264252],[55.093651,59.265469],[55.095951,59.26833],[55.096569,59.26907],[55.097462,59.27026],[55.098019,59.27116],[55.098541,59.272079],[55.099072,59.273102],[55.099758,59.27475],[55.100288,59.276279],[55.10078,59.277931],[55.10117,59.279331],[55.101639,59.281368],[55.1022,59.283661],[55.10268,59.285751],[55.102859,59.28648],[55.103088,59.287189],[55.103279,59.287701],[55.103519,59.28817],[55.103828,59.288639],[55.105659,59.29092],[55.105881,59.291321],[55.106079,59.29174],[55.106312,59.292301],[55.107021,59.29454],[55.10857,59.299801],[55.108898,59.30117],[55.10918,59.30238],[55.109459,59.303768],[55.109989,59.307079],[55.110519,59.310341],[55.110611,59.31094],[55.11068,59.311699],[55.110729,59.31263],[55.110748,59.31324],[55.110771,59.31432],[55.110649,59.319199],[55.110519,59.32346],[55.11042,59.326061],[55.110359,59.32769],[55.110298,59.330109],[55.110298,59.331009],[55.110321,59.33194],[55.110359,59.332951],[55.110401,59.333839],[55.110489,59.334721],[55.1106,59.335812],[55.110729,59.33691],[55.110939,59.33815],[55.11116,59.339218],[55.111439,59.34045],[55.111809,59.34206],[55.115021,59.35487],[55.115238,59.355801],[55.11562,59.357689],[55.11581,59.35886],[55.115959,59.360001],[55.116051,59.361031],[55.116119,59.361969],[55.11618,59.36314],[55.116192,59.364391],[55.11618,59.3657],[55.11615,59.36681],[55.116112,59.36787],[55.115879,59.372749],[55.11573,59.37569],[55.115589,59.378368],[55.115589,59.379139],[55.115589,59.379799],[55.11562,59.380531],[55.115688,59.381241],[55.115761,59.381802],[55.115879,59.38242],[55.116951,59.387329],[55.11702,59.38776],[55.117081,59.388271],[55.117142,59.388809],[55.11718,59.389301],[55.11721,59.389919],[55.117161,59.392971],[55.11702,59.396809],[55.11697,59.397652],[55.116909,59.398319],[55.116859,59.398869],[55.11676,59.399422],[55.11652,59.40028],[55.11618,59.401199],[55.11586,59.401741],[55.115501,59.402359],[55.115372,59.402531],[55.11528,59.402649],[55.114738,59.403351],[55.113369,59.40509],[55.113029,59.40559],[55.112659,59.4062],[55.112339,59.40704],[55.112171,59.407681],[55.11203,59.408379],[55.1119,59.409279],[55.111889,59.410118],[55.111919,59.41098],[55.112122,59.413879],[55.112259,59.415508],[55.112492,59.417099],[55.11264,59.417912],[55.112801,59.41848],[55.112968,59.418949],[55.113232,59.419601],[55.11351,59.420078],[55.113861,59.420631],[55.114769,59.421959],[55.11721,59.425442],[55.119701,59.428822],[55.12006,59.429211],[55.120548,59.429661],[55.123482,59.432072],[55.123798,59.432362],[55.124062,59.43261],[55.124298,59.432892],[55.124489,59.43317],[55.12468,59.433472],[55.12487,59.433842],[55.125092,59.43438],[55.125721,59.43589],[55.12719,59.440029],[55.127319,59.44051],[55.127441,59.440941],[55.127571,59.441521],[55.127651,59.442081],[55.127708,59.44273],[55.12772,59.44334],[55.12772,59.443851],[55.12767,59.44434],[55.127609,59.444851],[55.127529,59.445351],[55.127369,59.446049],[55.127171,59.446621],[55.12693,59.447201],[55.126621,59.447781],[55.126202,59.448399],[55.125,59.449959],[55.124748,59.45034],[55.124531,59.45076],[55.12431,59.451248],[55.12331,59.454609],[55.122761,59.456589],[55.12199,59.459351],[55.121761,59.46022],[55.121529,59.46106],[55.12133,59.46196],[55.121208,59.462841],[55.120991,59.46529],[55.12093,59.46587],[55.12085,59.466599],[55.120781,59.467098],[55.120689,59.467541],[55.12056,59.468079],[55.120338,59.468811],[55.120121,59.46944],[55.119888,59.47002],[55.11961,59.470581],[55.117699,59.47393],[55.117489,59.47438],[55.117229,59.47504],[55.117031,59.475651],[55.116879,59.476311],[55.116711,59.477131],[55.11657,59.477951],[55.116161,59.48074],[55.115761,59.483471],[55.11483,59.49308],[55.114189,59.501492],[55.112179,59.51009],[55.110081,59.516941],[55.10947,59.519161],[55.109039,59.52121],[55.10873,59.523621],[55.10865,59.525982],[55.10873,59.528],[55.108952,59.529942],[55.109409,59.532139],[55.10984,59.53363],[55.110432,59.535252],[55.111099,59.53677],[55.113239,59.541359],[55.113789,59.542641],[55.11425,59.543861],[55.114868,59.545769],[55.115292,59.547199],[55.115841,59.549469],[55.11694,59.554329],[55.11747,59.556259],[55.118118,59.558281],[55.11927,59.561562],[55.11972,59.562962],[55.12011,59.56435],[55.12056,59.565922],[55.121151,59.567581],[55.122509,59.571259],[55.122978,59.572731],[55.123299,59.574089],[55.123619,59.575611],[55.123989,59.577789],[55.124439,59.58099],[55.124989,59.584999],[55.12516,59.586498],[55.12524,59.58778],[55.12524,59.588848],[55.125092,59.590099],[55.124939,59.590851],[55.124748,59.591572],[55.124481,59.592289],[55.12418,59.59288],[55.123409,59.59404],[55.123329,59.594139],[55.122601,59.59499],[55.11953,59.59798],[55.117321,59.600151],[55.116501,59.600948],[55.115921,59.601379],[55.115299,59.60165],[55.114639,59.601711],[55.11412,59.601608],[55.11351,59.601299],[55.11026,59.599369],[55.109241,59.59885],[55.108608,59.59866],[55.107189,59.598419],[55.10659,59.598202],[55.105968,59.59779],[55.10545,59.597221],[55.10495,59.59642],[55.103981,59.59449],[55.103279,59.59317],[55.102772,59.592411],[55.102291,59.591862],[55.101688,59.591351],[55.10051,59.590549],[55.09898,59.589611],[55.09766,59.588779],[55.096279,59.58794],[55.094761,59.587158],[55.09462,59.58709],[55.093159,59.586491],[55.09169,59.586109],[55.090179,59.585899],[55.087391,59.585678],[55.08651,59.585609],[55.085659,59.58543],[55.084679,59.585098],[55.083912,59.584839],[55.083149,59.58469],[55.082291,59.584641],[55.07872,59.58461],[55.076729,59.58466],[55.075802,59.584759],[55.075039,59.585018],[55.074181,59.58556],[55.073639,59.586201],[55.072979,59.587341],[55.072472,59.588779],[55.072281,59.589512],[55.07201,59.590611],[55.068249,59.610561],[55.06686,59.617882],[55.066792,59.61824],[55.064869,59.628311],[55.064369,59.630939],[55.063782,59.63372],[55.063171,59.636219],[55.062881,59.63715],[55.062511,59.63834],[55.061649,59.640789],[55.06097,59.6423],[55.060009,59.64397],[55.059361,59.64513],[55.05859,59.646542],[55.05806,59.647812],[55.057621,59.649422],[55.057251,59.651299],[55.05698,59.653542],[55.056862,59.655731],[55.05669,59.6618],[55.05632,59.673031],[55.055679,59.696388],[55.055641,59.697941],[55.05545,59.70269],[55.055229,59.706039],[55.05479,59.70961],[55.054371,59.711731],[55.05373,59.714111],[55.052979,59.71627],[55.052181,59.71796],[55.05088,59.720058],[55.049549,59.721661],[55.048141,59.72298],[55.046951,59.723701],[55.045479,59.724319],[55.044159,59.724628],[55.04253,59.724789],[55.04084,59.724709],[55.039009,59.72438],[55.034672,59.723301],[55.032082,59.72263],[55.031349,59.722511],[55.030609,59.722439],[55.029442,59.722469],[55.02808,59.72274],[55.026699,59.72327],[55.025501,59.723991],[55.024311,59.724892],[55.022549,59.726681],[55.021229,59.72855],[55.019981,59.730789],[55.019112,59.7328],[55.01836,59.734989],[55.017818,59.73703],[55.017281,59.739811],[55.016949,59.742611],[55.016781,59.744831],[55.016548,59.752708],[55.016479,59.758751],[55.016541,59.760941],[55.01675,59.763359],[55.01712,59.765491],[55.01791,59.7687],[55.018188,59.77018],[55.018391,59.771759],[55.018471,59.77317],[55.01844,59.774551],[55.018261,59.776371],[55.017941,59.7784],[55.017021,59.782459],[55.01545,59.78944],[55.014591,59.792622],[55.013741,59.795219],[55.012909,59.797359],[55.011108,59.801861],[55.009972,59.80434],[55.00528,59.814522],[55.001629,59.82243],[54.998661,59.828949],[54.998161,59.83004],[54.99617,59.833672],[54.994751,59.83762],[54.993271,59.845428],[54.990711,59.852638],[54.988449,59.857792],[54.984798,59.864231],[54.983311,59.8666],[54.9762,59.877918],[54.975151,59.879589],[54.972931,59.882938],[54.971111,59.88689],[54.96899,59.892891],[54.966721,59.904572],[54.964111,59.922588],[54.963081,59.928169],[54.961498,59.93375],[54.958889,59.93924],[54.95475,59.948601],[54.953461,59.951599],[54.950409,59.955978],[54.948441,59.959332],[54.946911,59.96328],[54.946072,59.966621],[54.945499,59.96957],[54.945301,59.97123],[54.945251,59.972099],[54.94519,59.972939],[54.945091,59.974689],[54.945049,59.97646],[54.944969,59.983688],[54.944931,59.98642],[54.944809,59.995998],[54.944618,60.010189],[54.944569,60.012428],[54.944439,60.014481],[54.944302,60.017578],[54.94421,60.019371],[54.943981,60.023159],[54.943939,60.024429],[54.94384,60.027279],[54.94389,60.03072],[54.94389,60.031479],[54.944149,60.050861],[54.944229,60.054852],[54.94426,60.057011],[54.944279,60.05846],[54.944649,60.08567],[54.944889,60.102211],[54.944839,60.10564],[54.94466,60.10783],[54.94437,60.109631],[54.94392,60.111649],[54.94326,60.11367],[54.94249,60.11581],[54.941429,60.118179],[54.937809,60.126369],[54.93663,60.12925],[54.93581,60.131908],[54.934238,60.138969],[54.934101,60.13953],[54.932701,60.1455],[54.931992,60.14938],[54.931629,60.151779],[54.931301,60.155849],[54.93108,60.15937],[54.93087,60.165771],[54.930271,60.178749],[54.929359,60.198689],[54.929211,60.19973],[54.926651,60.217232],[54.924358,60.232849],[54.92395,60.235291],[54.923698,60.23925],[54.923599,60.242512],[54.92342,60.259071],[54.92326,60.27956],[54.923092,60.284538],[54.920158,60.315289],[54.92004,60.316509],[54.919449,60.322781],[54.919201,60.325329],[54.9189,60.32843],[54.918819,60.3293],[54.918621,60.33147],[54.916981,60.34874],[54.91441,60.374008],[54.911572,60.402851],[54.91098,60.409698],[54.91048,60.41692],[54.910339,60.42078],[54.910252,60.426491],[54.910351,60.434891],[54.910801,60.455132],[54.911251,60.486462],[54.911621,60.51305],[54.912979,60.534969],[54.91325,60.538929],[54.913342,60.54007],[54.913952,60.54858],[54.916229,60.584351],[54.919479,60.633011],[54.919842,60.638851],[54.920479,60.64851],[54.921619,60.675339],[54.92107,60.67408],[54.921509,60.69199],[54.921612,60.69524],[54.921799,60.69796],[54.922371,60.70192],[54.924622,60.71656],[54.925159,60.7192],[54.927841,60.729431],[54.9282,60.730999],[54.928398,60.73328],[54.92902,60.73719],[54.930241,60.74353],[54.930801,60.745392],[54.932491,60.752548],[54.932629,60.753159],[54.936001,60.767448],[54.936451,60.769508],[54.937248,60.773232],[54.93771,60.775459],[54.938122,60.77766],[54.93803,60.779171],[54.938332,60.78286],[54.939419,60.785549],[54.940842,60.794399],[54.94128,60.7971],[54.941471,60.798279],[54.942089,60.801979],[54.942909,60.807018],[54.94331,60.809681],[54.944839,60.818668],[54.94495,60.819389],[54.945629,60.824699],[54.94928,60.852829],[54.95261,60.882751],[54.954609,60.901951],[54.954708,60.904129],[54.95509,60.906891],[54.955589,60.909828],[54.956261,60.912861],[54.9576,60.917679],[54.958611,60.921341],[54.964859,60.94379],[54.96888,60.958241],[54.969551,60.961021],[54.97187,60.971321],[54.972969,60.976131],[54.977161,60.99435],[54.98082,61.010262],[54.982491,61.017448],[54.983349,61.021061],[54.986229,61.033569],[54.987339,61.038368],[54.988258,61.042351],[54.989109,61.046051],[54.989288,61.046822],[54.989632,61.048321],[54.98996,61.0499],[54.990189,61.05109],[54.990421,61.052479],[54.99057,61.05357],[54.9907,61.054642],[54.99081,61.055851],[54.990898,61.057018],[54.991009,61.058819],[54.991089,61.060139],[54.99128,61.063751],[54.99176,61.071911],[54.992748,61.08934],[54.993912,61.10981],[54.993931,61.110161],[54.99408,61.112862],[54.994148,61.11396],[54.994549,61.121311],[54.99472,61.123779],[54.994831,61.125111],[54.994862,61.125519],[54.994999,61.126659],[54.99522,61.12833],[54.99548,61.12981],[54.995819,61.1315],[54.99609,61.132759],[54.996498,61.134472],[54.996761,61.135448],[54.997131,61.136761],[54.997581,61.138161],[54.998871,61.142101],[54.999329,61.143509],[55.000858,61.148209],[55.001511,61.150211],[55.001968,61.151829],[55.002369,61.153412],[55.00272,61.1548],[55.002941,61.155941],[55.002979,61.156281],[55.002991,61.156651],[55.002991,61.156971],[55.002911,61.15749],[55.002781,61.158169],[55.002171,61.160671],[55.001949,61.161549],[55.00172,61.162239],[55.00148,61.16283],[55.001259,61.16333],[55.0009,61.163971],[55.000141,61.165058],[54.996979,61.168869],[54.993469,61.1731],[54.992802,61.173901],[54.99239,61.174412],[54.991531,61.175449],[54.990662,61.176491],[54.9874,61.180519],[54.98365,61.185501],[54.9804,61.19133],[54.977051,61.19854],[54.974892,61.20438],[54.97282,61.211929],[54.97171,61.217461],[54.971439,61.2188],[54.97065,61.224979],[54.96986,61.23476],[54.969269,61.249008],[54.968681,61.262569],[54.96751,61.29174],[54.967461,61.29483],[54.967461,61.299309],[54.967628,61.32032],[54.967682,61.326801],[54.967682,61.329762],[54.967461,61.33461],[54.967361,61.33614],[54.967041,61.341091],[54.96685,61.345928],[54.966789,61.34951],[54.966759,61.35709],[54.96685,61.360802],[54.96703,61.365589],[54.9673,61.37249],[54.96756,61.37883],[54.9678,61.383862],[54.967819,61.384609],[54.967812,61.385429],[54.96777,61.38623],[54.967701,61.386978],[54.967602,61.387669],[54.967529,61.3881],[54.96735,61.389259],[54.967232,61.38987],[54.967041,61.391029],[54.966961,61.391479],[54.966942,61.39185],[54.966949,61.39222],[54.967018,61.39257],[54.96711,61.39283],[54.967239,61.393101],[54.9674,61.393311],[54.967579,61.39344],[54.96777,61.393509],[54.967979,61.39352],[54.968208,61.393478],[54.968811,61.39325],[54.969051,61.3932],[54.969299,61.3932],[54.969582,61.393242],[54.96981,61.393341],[54.969978,61.393471],[54.970119,61.393631],[54.97057,61.394379],[54.972691,61.39875],[54.973919,61.40144],[54.97477,61.403461],[54.9786,61.413589],[54.97929,61.415291],[54.980492,61.418209],[54.980968,61.419491],[54.9814,61.42099],[54.981701,61.422161],[54.98204,61.42374],[54.982349,61.425129],[54.98278,61.426861],[54.983089,61.42791],[54.983528,61.4291],[54.983879,61.430061],[54.984329,61.431099],[54.988491,61.440079],[54.98954,61.442242],[54.990509,61.443989],[54.991692,61.445782],[54.99292,61.44733],[54.99382,61.448318],[54.994579,61.449471],[54.99509,61.450371],[54.995461,61.451359],[54.995789,61.452339],[54.996151,61.453629],[54.996479,61.454491],[54.997021,61.455688],[54.99786,61.45694],[54.998058,61.457169],[54.99876,61.457989],[54.999859,61.459122],[55.00042,61.459549],[55.00108,61.46006],[55.001888,61.460609],[55.002708,61.461159],[55.00367,61.46183],[55.004639,61.4627],[55.005379,61.46357],[55.00602,61.46452],[55.00666,61.465801],[55.00713,61.466999],[55.007519,61.46833],[55.007858,61.46986],[55.008099,61.471519],[55.008171,61.472672],[55.00824,61.487968],[55.008251,61.4897],[55.00827,61.491631],[55.008282,61.492649],[55.008331,61.495178],[55.00843,61.496571],[55.008659,61.498852],[55.008991,61.501289],[55.009682,61.504978],[55.01041,61.507641],[55.011532,61.511021],[55.012581,61.51416],[55.013309,61.516312],[55.01548,61.522869],[55.016811,61.527439],[55.017639,61.531071],[55.018478,61.53603],[55.019588,61.543861],[55.021111,61.554241],[55.023998,61.57375],[55.024578,61.578789],[55.024818,61.582489],[55.024849,61.58744],[55.02467,61.59557],[55.02454,61.601311],[55.024609,61.60276],[55.024769,61.605431],[55.025021,61.6078],[55.025421,61.61084],[55.026749,61.619942],[55.029579,61.638821],[55.031319,61.65118],[55.034569,61.680481],[55.035259,61.688889],[55.035259,61.69593],[55.034569,61.703819],[55.03339,61.71249],[55.032059,61.723049],[55.032009,61.72665],[55.03231,61.729401],[55.032799,61.731548],[55.03344,61.733521],[55.04266,61.757488],[55.043159,61.758759],[55.04372,61.759941],[55.04438,61.761181],[55.045071,61.762299],[55.04578,61.763302],[55.04644,61.764141],[55.04697,61.764709],[55.047508,61.76524],[55.048679,61.766232],[55.0494,61.766689],[55.050129,61.76709],[55.05154,61.76767],[55.054871,61.768799],[55.06678,61.77285],[55.078411,61.77684],[55.079399,61.7771],[55.080681,61.777309],[55.08197,61.777409],[55.08297,61.77739],[55.084461,61.77729],[55.085041,61.777222],[55.08564,61.777119],[55.087132,61.77673],[55.08857,61.776218],[55.089409,61.77586],[55.09024,61.775459],[55.102551,61.768341],[55.106609,61.765961],[55.107342,61.76545],[55.11039,61.763729],[55.13361,61.750259],[55.137341,61.748631],[55.14967,61.745499],[55.15696,61.743649],[55.163601,61.742901],[55.165352,61.742981],[55.167831,61.743301],[55.170029,61.743801],[55.17173,61.744308],[55.171921,61.744381],[55.17342,61.74498],[55.175461,61.745899],[55.182289,61.74913],[55.186352,61.75108],[55.18853,61.751949],[55.190708,61.75256],[55.198181,61.75436],[55.20409,61.75584],[55.20697,61.756569],[55.208,61.756641],[55.208752,61.756569],[55.20924,61.756451],[55.210201,61.7561],[55.21088,61.75573],[55.211529,61.755268],[55.212528,61.75436],[55.213451,61.75325],[55.21397,61.75246],[55.21537,61.75016],[55.218601,61.7449],[55.221039,61.740891],[55.22345,61.736889],[55.22403,61.73605],[55.224651,61.735291],[55.224831,61.735111],[55.225269,61.734669],[55.22604,61.734032],[55.226971,61.73336],[55.228149,61.732979],[55.228642,61.733219],[55.23011,61.73447],[55.23177,61.73605],[55.232601,61.736912],[55.232922,61.737339],[55.234909,61.743431],[55.236519,61.74818],[55.237141,61.75024],[55.237549,61.751659],[55.240261,61.762218],[55.242809,61.772251],[55.245392,61.782318],[55.2486,61.79491],[55.249069,61.796661],[55.24947,61.798],[55.25161,61.804279],[55.252178,61.805759],[55.252621,61.806992],[55.2551,61.813889],[55.256981,61.819141],[55.257702,61.82119],[55.261089,61.830421],[55.264759,61.840389],[55.26614,61.843891],[55.266972,61.846279],[55.26722,61.847141],[55.267529,61.848389],[55.26783,61.85033],[55.268002,61.853001],[55.26807,61.85487],[55.268059,61.857052],[55.267948,61.858978],[55.267818,61.86047],[55.26495,61.88015],[55.263599,61.888641],[55.26321,61.891022],[55.262878,61.89325],[55.261162,61.904709],[55.260529,61.908791],[55.25972,61.914051],[55.25898,61.91872],[55.25766,61.927021],[55.247292,61.971561],[55.23119,62.039539],[55.230511,62.044521],[55.230061,62.050442],[55.230049,62.055191],[55.230019,62.066662],[55.22987,62.07954],[55.229542,62.082401],[55.229229,62.08503],[55.221161,62.120651],[55.219151,62.130779],[55.218861,62.134121],[55.218761,62.149231],[55.219051,62.221668],[55.219009,62.249611],[55.219002,62.25959],[55.218861,62.359859],[55.21719,62.386688],[55.216511,62.397709],[55.212669,62.458649],[55.212589,62.460918],[55.212551,62.462688],[55.212608,62.466721],[55.21273,62.470371],[55.21286,62.47298],[55.212978,62.474522],[55.213112,62.47604],[55.21339,62.47887],[55.21376,62.48177],[55.214149,62.484749],[55.21566,62.49527],[55.216599,62.501961],[55.219742,62.524139],[55.223789,62.552738],[55.22406,62.555309],[55.22427,62.557701],[55.22443,62.55999],[55.22456,62.56229],[55.224659,62.565819],[55.22467,62.569351],[55.22464,62.572048],[55.224529,62.574848],[55.224239,62.580269],[55.222969,62.603519],[55.222839,62.605961],[55.222801,62.60849],[55.222431,62.62851],[55.22234,62.634449],[55.222141,62.646141],[55.22184,62.6637],[55.221802,62.665722],[55.221828,62.667389],[55.22197,62.669109],[55.222191,62.67083],[55.222462,62.672588],[55.222809,62.6744],[55.22324,62.676208],[55.223721,62.67812],[55.224659,62.68137],[55.225441,62.684299],[55.226212,62.687679],[55.227039,62.691471],[55.227581,62.693821],[55.228748,62.698212],[55.230701,62.705421],[55.231861,62.709789],[55.234619,62.71941],[55.235989,62.72533],[55.236671,62.731159],[55.23682,62.736401],[55.235512,62.767021],[55.23497,62.78035],[55.234951,62.781029],[55.234859,62.783001],[55.234791,62.78511],[55.234329,62.799831],[55.234081,62.829102],[55.234001,62.852989],[55.233929,62.871929],[55.233681,62.929691],[55.233479,62.976898],[55.233459,62.986481],[55.233471,62.988838],[55.233551,62.99118],[55.235119,63.02404],[55.23579,63.037411],[55.23819,63.08873],[55.24054,63.138859],[55.24284,63.165291],[55.244209,63.180828],[55.245461,63.191582],[55.248169,63.214821],[55.253731,63.247841],[55.254421,63.251881],[55.25444,63.252239],[55.254379,63.25293],[55.254311,63.25317],[55.254292,63.253479],[55.254318,63.253819],[55.254391,63.254139],[55.254532,63.25423],[55.25478,63.254688],[55.255001,63.255291],[55.25552,63.258629],[55.25597,63.261429],[55.257401,63.269409],[55.257729,63.270859],[55.258121,63.272518],[55.25856,63.274281],[55.25898,63.27586],[55.259392,63.277309],[55.26033,63.280411],[55.261299,63.28331],[55.26223,63.28582],[55.26289,63.28751],[55.263641,63.28928],[55.26524,63.29282],[55.269779,63.30257],[55.272469,63.308239],[55.289742,63.344082],[55.312511,63.391201],[55.334339,63.437031],[55.33736,63.445621],[55.339611,63.453171],[55.352982,63.506691],[55.361198,63.53952],[55.361931,63.543209],[55.36245,63.547668],[55.36264,63.551231],[55.362099,63.560669],[55.35981,63.590931],[55.357052,63.626511],[55.354858,63.6544],[55.354111,63.664101],[55.352779,63.681179],[55.35252,63.687321],[55.352711,63.724781],[55.352829,63.747829],[55.352982,63.775299],[55.354881,63.7995],[55.35918,63.850399],[55.360851,63.8708],[55.360981,63.872459],[55.361229,63.880951],[55.361519,63.89983],[55.36158,63.900051],[55.361858,63.91151],[55.362202,63.918461],[55.363369,63.92704],[55.36974,63.973782],[55.375999,64.019569],[55.379372,64.044548],[55.379829,64.049911],[55.379879,64.055313],[55.379761,64.058708],[55.379318,64.063507],[55.376541,64.081451],[55.37191,64.109947],[55.37093,64.116043],[55.37001,64.123421],[55.369659,64.128487],[55.369469,64.134583],[55.36961,64.140419],[55.371361,64.170288],[55.37162,64.175087],[55.37418,64.221138],[55.37513,64.237747],[55.37561,64.253632],[55.376541,64.287361],[55.377541,64.322197],[55.377998,64.327454],[55.378731,64.333282],[55.38308,64.359459],[55.387169,64.384857],[55.38763,64.388939],[55.389191,64.41568],[55.38924,64.416542],[55.390659,64.441994],[55.391781,64.46209],[55.392021,64.466301],[55.392231,64.469879],[55.394241,64.505539],[55.395802,64.532097],[55.397911,64.568993],[55.399921,64.603783],[55.401649,64.634758],[55.40313,64.661453],[55.404289,64.682663],[55.404331,64.683434],[55.40469,64.686127],[55.407791,64.702011],[55.415829,64.744667],[55.417759,64.754837],[55.420971,64.771858],[55.42157,64.775002],[55.424469,64.790497],[55.427631,64.807411],[55.428741,64.813278],[55.429642,64.818176],[55.430649,64.823486],[55.43095,64.825287],[55.431149,64.826813],[55.431431,64.829514],[55.431728,64.833153],[55.43198,64.836067],[55.432388,64.840958],[55.432781,64.845383],[55.433781,64.857193],[55.4375,64.902077],[55.441929,64.950661],[55.446789,65.001953],[55.44928,65.028252],[55.45269,65.089447],[55.453121,65.094482],[55.453541,65.098083],[55.453979,65.100883],[55.454521,65.103813],[55.45499,65.105957],[55.455479,65.108009],[55.4561,65.110352],[55.45676,65.112663],[55.45739,65.114647],[55.458172,65.116867],[55.464298,65.13385],[55.472229,65.155891],[55.474258,65.161232],[55.475731,65.165649],[55.476761,65.168533],[55.477951,65.172058],[55.478729,65.174263],[55.47884,65.174583],[55.479229,65.175957],[55.480709,65.180946],[55.481098,65.182266],[55.48172,65.184776],[55.483768,65.191566],[55.484459,65.194237],[55.486099,65.199707],[55.486172,65.199951],[55.486328,65.200493],[55.48645,65.200882],[55.48711,65.20311],[55.489799,65.212097],[55.493038,65.223244],[55.493221,65.223869],[55.493568,65.225082],[55.496841,65.23587],[55.501091,65.24958],[55.50132,65.250618],[55.501362,65.25132],[55.50132,65.251556],[55.50132,65.251862],[55.501381,65.252136],[55.501492,65.252357],[55.501572,65.252441],[55.501701,65.252533],[55.502048,65.253029],[55.50243,65.253777],[55.508209,65.272163],[55.51358,65.289261],[55.513599,65.289337],[55.51458,65.292801],[55.51572,65.29776],[55.51659,65.303421],[55.516941,65.308128],[55.516979,65.31089],[55.51701,65.312027],[55.516911,65.316544],[55.516769,65.31958],[55.516659,65.320442],[55.515739,65.328087],[55.51572,65.328232],[55.51038,65.346527],[55.506351,65.360077],[55.504719,65.36557],[55.503799,65.368629],[55.503262,65.370483],[55.501572,65.376152],[55.500092,65.381126],[55.499531,65.383018],[55.49836,65.386993],[55.497669,65.388397],[55.49757,65.388428],[55.497429,65.38855],[55.497341,65.388687],[55.497269,65.388947],[55.497261,65.389183],[55.49728,65.38942],[55.497318,65.389572],[55.49707,65.390923],[55.495461,65.395638],[55.494221,65.3992],[55.493561,65.401131],[55.493019,65.403038],[55.492779,65.404213],[55.492599,65.40538],[55.492359,65.407806],[55.492359,65.409523],[55.492439,65.411186],[55.492779,65.41362],[55.493252,65.415863],[55.49398,65.4179],[55.49477,65.419724],[55.496449,65.422722],[55.497082,65.424553],[55.49754,65.426537],[55.4977,65.428101],[55.497669,65.429817],[55.497311,65.432121],[55.496719,65.434174],[55.495869,65.435898],[55.495258,65.436653],[55.494282,65.437592],[55.493229,65.438118],[55.4921,65.438217],[55.491268,65.438026],[55.4902,65.437492],[55.489349,65.436729],[55.488659,65.43602],[55.488022,65.435287],[55.487789,65.435051],[55.487331,65.434776],[55.487068,65.434753],[55.48687,65.434776],[55.486629,65.434929],[55.480099,65.443237],[55.477669,65.447357],[55.474899,65.455009],[55.473259,65.459709],[55.468029,65.474663],[55.467461,65.476288],[55.459759,65.498352],[55.4585,65.503067],[55.45787,65.507019],[55.457432,65.512604],[55.455971,65.537918],[55.454269,65.564079],[55.453831,65.573692],[55.453732,65.576553],[55.45319,65.580566],[55.452759,65.583],[55.44976,65.59417],[55.445061,65.611649],[55.44495,65.612061],[55.429741,65.669823],[55.419739,65.707779],[55.394691,65.801437],[55.39352,65.805794],[55.38797,65.828491],[55.387482,65.830513],[55.386089,65.838669],[55.383629,65.853172],[55.382309,65.861343],[55.38002,65.87558],[55.37661,65.896263],[55.374458,65.911629],[55.3708,65.938843],[55.370121,65.945618],[55.369831,65.951973],[55.369781,65.961411],[55.370701,65.972397],[55.377041,66.022263],[55.382309,66.062943],[55.38818,66.089546],[55.389969,66.097618],[55.39669,66.128433],[55.397812,66.136932],[55.40147,66.178818],[55.4062,66.234261],[55.40659,66.248772],[55.40567,66.270103],[55.405609,66.271431],[55.404301,66.3013],[55.402439,66.343353],[55.39996,66.401802],[55.39893,66.433823],[55.39645,66.473557],[55.395969,66.481934],[55.39489,66.500603],[55.391869,66.54969],[55.38982,66.584198],[55.388779,66.599937],[55.38855,66.60041],[55.388321,66.601143],[55.388229,66.601692],[55.388309,66.602173],[55.388512,66.602852],[55.388649,66.603073],[55.388489,66.605331],[55.38826,66.609299],[55.387779,66.616966],[55.387039,66.629768],[55.384701,66.669167],[55.381729,66.717056],[55.381451,66.721474],[55.381241,66.724518],[55.380951,66.727364],[55.38055,66.73053],[55.380138,66.733421],[55.3797,66.73613],[55.379211,66.738777],[55.37851,66.742157],[55.377899,66.744591],[55.376991,66.747993],[55.370651,66.769859],[55.368019,66.778954],[55.360748,66.804863],[55.35627,66.820229],[55.355,66.824783],[55.352791,66.831543],[55.351139,66.835831],[55.34845,66.841583],[55.337379,66.865288],[55.324001,66.894043],[55.310959,66.922279],[55.307251,66.931549],[55.30529,66.939789],[55.303539,66.951118],[55.29982,66.992661],[55.29871,67.004959],[55.29689,67.025284],[55.292389,67.079521],[55.290241,67.089478],[55.28183,67.117592],[55.269909,67.157463],[55.266579,67.169472],[55.25782,67.219833],[55.25647,67.225433],[55.24807,67.253098],[55.244831,67.263847],[55.24469,67.263779],[55.244511,67.263779],[55.244339,67.263893],[55.244202,67.264091],[55.24411,67.264374],[55.24408,67.264687],[55.244122,67.264992],[55.244209,67.265259],[55.24435,67.265457],[55.240101,67.278992],[55.227638,67.317841],[55.214691,67.355843],[55.211689,67.365967],[55.204689,67.397057],[55.196541,67.432419],[55.195518,67.436813],[55.18961,67.463318],[55.188999,67.476341],[55.187962,67.50354],[55.188782,67.511383],[55.192871,67.533623],[55.194649,67.546417],[55.194962,67.553429],[55.19413,67.565613],[55.192741,67.580162],[55.192039,67.602631],[55.191132,67.621902],[55.189522,67.629898],[55.178429,67.668518],[55.174301,67.684967],[55.172569,67.693893],[55.164768,67.734177],[55.163471,67.737984],[55.149719,67.768517],[55.131649,67.807831],[55.12394,67.824364],[55.10191,67.865738],[55.09697,67.875008],[55.094269,67.883163],[55.092571,67.894051],[55.092621,67.918877],[55.092621,67.924637],[55.092609,67.925743],[55.092831,67.976692],[55.093311,67.983856],[55.097321,68.026131],[55.099781,68.05143],[55.104031,68.095139],[55.104511,68.104431],[55.10429,68.114708],[55.103031,68.132607],[55.099152,68.18882],[55.096649,68.203423],[55.092152,68.227898],[55.09082,68.240196],[55.091709,68.253601],[55.0938,68.267563],[55.094559,68.277641],[55.093231,68.286392],[55.087719,68.30201],[55.079151,68.324707],[55.068371,68.35363],[55.054989,68.390182],[55.046741,68.41256],[55.027309,68.466507],[55.014111,68.500633],[54.9939,68.554237],[54.99123,68.560219],[54.98875,68.562553],[54.973499,68.573959],[54.95079,68.59079],[54.924641,68.610069],[54.92448,68.610443],[54.924301,68.611618],[54.923611,68.616402],[54.923111,68.61998],[54.922451,68.624489],[54.92197,68.627922],[54.9212,68.633369],[54.920101,68.640846],[54.919559,68.644333],[54.91917,68.648529],[54.919128,68.653183],[54.919319,68.663483],[54.919361,68.672462],[54.919449,68.681358],[54.91954,68.690643],[54.919628,68.698692],[54.91967,68.706421],[54.919788,68.71479],[54.9198,68.718513],[54.919849,68.724922],[54.919941,68.735184],[54.92001,68.746468],[54.92009,68.758133],[54.920219,68.774109],[54.920429,68.799072],[54.920792,68.843628],[54.920818,68.854874],[54.919331,68.878441],[54.917,68.91478],[54.91502,68.944328],[54.912788,68.978416],[54.910358,69.015228],[54.909859,69.021294],[54.90905,69.034103],[54.908852,69.037292],[54.908489,69.042999],[54.90765,69.055283],[54.90731,69.05954],[54.90712,69.062553],[54.906719,69.065102],[54.906189,69.067772],[54.90509,69.07119],[54.905769,69.073486],[54.905869,69.073723],[54.907501,69.07753],[54.910469,69.085258],[54.911518,69.088371],[54.912521,69.091713],[54.913689,69.094673],[54.914989,69.097481],[54.91534,69.099037],[54.915409,69.100037],[54.915379,69.10125],[54.91354,69.114662],[54.91309,69.117012],[54.912762,69.118294],[54.912628,69.118797],[54.91246,69.119926],[54.912411,69.121162],[54.91267,69.125023],[54.912819,69.127327],[54.912109,69.127617],[54.911671,69.127953],[54.911308,69.128349],[54.911041,69.12896],[54.910751,69.129601],[54.910431,69.130463],[54.910229,69.131439],[54.910198,69.131683],[54.910179,69.131866],[54.910172,69.132111],[54.91016,69.132294],[54.910141,69.132477],[54.910141,69.132881],[54.91016,69.133003],[54.910221,69.133171],[54.9104,69.133217],[54.91058,69.133087],[54.91066,69.132919],[54.910721,69.132637],[54.910801,69.132362],[54.910881,69.132042],[54.910961,69.131866],[54.91153,69.131157],[54.91222,69.130302],[54.912338,69.13015],[54.912861,69.129601],[54.914219,69.128349],[54.915661,69.127457],[54.91748,69.12674],[54.919159,69.126549],[54.92194,69.126427],[54.92292,69.126663],[54.92358,69.12719],[54.924122,69.127861],[54.924679,69.128799],[54.92506,69.129837],[54.926399,69.13607],[54.926281,69.136269],[54.926189,69.136574],[54.926231,69.136848],[54.9263,69.137016],[54.926411,69.137169],[54.926559,69.137253],[54.926628,69.137207],[54.926579,69.137527],[54.924191,69.148048],[54.91798,69.17437],[54.917919,69.174316],[54.917728,69.174271],[54.917542,69.174347],[54.917469,69.174622],[54.91748,69.175148],[54.917549,69.175613],[54.917622,69.175697],[54.91769,69.175789],[54.917992,69.175819],[54.918091,69.175751],[54.91811,69.175591],[54.918251,69.176224],[54.93475,69.219063],[54.93576,69.220993],[54.937019,69.222343],[54.93795,69.222893],[54.945759,69.225929],[54.946678,69.226593],[54.94788,69.228241],[54.948399,69.229248],[54.954651,69.248573],[54.95512,69.250549],[54.955231,69.253548],[54.95219,69.281349],[54.951382,69.285461],[54.914391,69.430771],[54.913651,69.435097],[54.913269,69.439484],[54.913391,69.454674],[54.913952,69.525223],[54.914669,69.599983],[54.914902,69.623459],[54.91605,69.798088],[54.909809,69.909576],[54.90976,69.912453],[54.91502,70.140343],[54.915451,70.190514],[54.917278,70.354233],[54.918461,70.369408],[54.918449,70.374023],[54.918018,70.381271],[54.919399,70.435493],[54.92009,70.462624],[54.919998,70.466408],[54.91975,70.469276],[54.91795,70.480713],[54.91774,70.483856],[54.91927,70.528839],[54.930779,70.631973],[54.940411,70.762863],[54.94083,70.776108],[54.940651,70.779343],[54.93998,70.7827],[54.939251,70.784447],[54.937462,70.787086],[54.921299,70.801826],[54.91959,70.80442],[54.91851,70.807426],[54.91806,70.810226],[54.91798,70.81279],[54.919258,70.882713],[54.921379,70.984528],[54.921398,70.985802],[54.921959,71.016243],[54.92207,71.022346],[54.922741,71.059174],[54.923,71.080643],[54.921589,71.136688],[54.921612,71.140411],[54.922001,71.146027],[54.923069,71.153809],[54.923981,71.157944],[54.92514,71.161377],[54.925671,71.162971],[54.927711,71.167511],[54.929909,71.171478],[54.931171,71.174133],[54.93224,71.176979],[54.937721,71.19474],[54.947842,71.227577],[54.949181,71.232407],[54.950802,71.239929],[54.951969,71.247871],[54.952911,71.25663],[54.955811,71.283669],[54.95607,71.286148],[54.956211,71.287483],[54.973251,71.448219],[54.97401,71.453117],[54.974918,71.457787],[54.976719,71.465149],[54.978142,71.469757],[54.9804,71.476341],[54.981201,71.479446],[54.98233,71.483841],[54.98402,71.492989],[54.99025,71.540962],[54.990749,71.546097],[54.991131,71.555542],[54.987789,71.697289],[54.983429,71.778908],[54.983311,71.78492],[54.983589,71.79248],[54.99284,71.913406],[54.9963,71.958504],[54.996449,71.962212],[54.996399,71.966888],[54.996078,71.97171],[54.978851,72.105797],[54.978149,72.112457],[54.977421,72.122673],[54.972771,72.248459],[54.9659,72.335892],[54.965721,72.33828],[54.965549,72.341904],[54.965488,72.345627],[54.965611,72.34996],[54.96624,72.372711],[54.96669,72.391632],[54.966759,72.395111],[54.966591,72.398827],[54.966301,72.403053],[54.964802,72.419296],[54.963531,72.434708],[54.963501,72.436478],[54.963921,72.454826],[54.964569,72.483093],[54.966141,72.539192],[54.9664,72.543533],[54.96698,72.54879],[54.967319,72.551041],[54.96767,72.552994],[54.968491,72.557251],[54.984421,72.617264],[54.985882,72.625191],[54.98658,72.631699],[54.986809,72.635223],[54.990509,72.690758],[54.990501,72.820793],[54.990311,72.82589],[54.9897,72.831818],[54.98793,72.842369],[54.987728,72.843071],[54.985649,72.850288],[54.976269,72.875366],[54.97007,72.891907],[54.96825,72.896843],[54.96804,72.897087],[54.96788,72.897186],[54.96653,72.897278],[54.965801,72.897331],[54.961491,72.897469],[54.958618,72.897636],[54.956902,72.898079],[54.950729,72.900253],[54.940731,72.903793],[54.935379,72.905693],[54.930721,72.907242],[54.928219,72.908211],[54.92672,72.909103],[54.924301,72.911133],[54.922729,72.912666],[54.913921,72.925461],[54.913521,72.926041],[54.906811,72.935799],[54.904121,72.940048],[54.9016,72.944641],[54.895439,72.955879],[54.887291,72.970757],[54.885941,72.974823],[54.88472,72.978493],[54.883831,72.983292],[54.883438,72.987579],[54.883591,72.994751],[54.883598,72.995728],[54.883911,73.017487],[54.883961,73.024017],[54.88361,73.030411],[54.883308,73.033073],[54.88126,73.045387],[54.877781,73.066292],[54.875408,73.080193],[54.87376,73.090279],[54.87175,73.102318],[54.86882,73.119629],[54.866821,73.131432],[54.866501,73.133957],[54.866371,73.135094],[54.866341,73.135803],[54.866371,73.136703],[54.866741,73.139847],[54.86747,73.146378],[54.867661,73.148499],[54.86784,73.151398],[54.86797,73.156677],[54.867882,73.173286],[54.867519,73.213791],[54.86726,73.237701],[54.867352,73.241989],[54.869431,73.262611],[54.869598,73.264427],[54.869781,73.266312],[54.86998,73.268311],[54.870171,73.270348],[54.870232,73.27092],[54.870258,73.271248],[54.87048,73.273521],[54.870739,73.276932],[54.870739,73.277641],[54.870708,73.278999],[54.87059,73.280632],[54.87038,73.282341],[54.869789,73.285683],[54.86961,73.286743],[54.869431,73.287987],[54.86932,73.288872],[54.86924,73.289886],[54.86916,73.2911],[54.86916,73.292717],[54.869209,73.295464],[54.869141,73.296242],[54.869061,73.296532],[54.868969,73.296753],[54.868969,73.296951],[54.869011,73.29718],[54.869148,73.297836],[54.869148,73.299477],[54.869221,73.300499],[54.869221,73.30645],[54.869251,73.316261],[54.86927,73.321907],[54.869289,73.322884],[54.869301,73.323563],[54.86935,73.324303],[54.869438,73.325089],[54.86953,73.325798],[54.86969,73.326767],[54.869949,73.328011],[54.870258,73.329247],[54.87059,73.330307],[54.87093,73.331169],[54.87138,73.332222],[54.872211,73.33371],[54.873138,73.335159],[54.874279,73.336884],[54.875111,73.338219],[54.875809,73.339592],[54.87616,73.340462],[54.876678,73.342049],[54.87764,73.345131],[54.877991,73.346313],[54.878899,73.349327],[54.880051,73.353203],[54.879929,73.353333],[54.879822,73.353561],[54.879768,73.353767],[54.879749,73.353928],[54.879749,73.354073],[54.879768,73.354309],[54.879829,73.354507],[54.879959,73.354736],[54.880119,73.354889],[54.88031,73.354919],[54.880482,73.354843],[54.880611,73.355293],[54.88126,73.357567],[54.88139,73.358124],[54.881481,73.358727],[54.881741,73.36132],[54.881889,73.363533],[54.88192,73.365334],[54.881729,73.371681],[54.881451,73.379997],[54.881481,73.382294],[54.881592,73.384979],[54.881802,73.388153],[54.88195,73.389641],[54.882149,73.391228],[54.882778,73.395287],[54.883202,73.397476],[54.883801,73.400017],[54.884659,73.403008],[54.887199,73.410408],[54.887531,73.411636],[54.887829,73.412773],[54.887951,73.413879],[54.88802,73.414963],[54.888062,73.420387],[54.888081,73.420929],[54.888142,73.421219],[54.88821,73.421471],[54.88829,73.421638],[54.88842,73.421829],[54.888569,73.421951],[54.888809,73.422203],[54.889042,73.422394],[54.888618,73.423233],[54.88821,73.424088],[54.88789,73.424751],[54.887329,73.425941],[54.88715,73.426353],[54.88644,73.427856],[54.884941,73.431084],[54.882381,73.436417],[54.880909,73.439507],[54.880482,73.440399],[54.868172,73.466171],[54.86668,73.469353],[54.866322,73.470123],[54.866039,73.47081],[54.865761,73.471573],[54.86517,73.473412],[54.85984,73.490753],[54.85368,73.510521],[54.85284,73.512589],[54.8466,73.526047],[54.83498,73.548721],[54.83453,73.549553],[54.834049,73.550377],[54.833618,73.55098],[54.83321,73.551537],[54.832729,73.552147],[54.830601,73.55468],[54.827888,73.557899],[54.822762,73.564011],[54.820751,73.566383],[54.819462,73.567703],[54.817711,73.569542],[54.814739,73.572647],[54.81332,73.574203],[54.811901,73.57592],[54.808929,73.579613],[54.80759,73.581291],[54.80563,73.583649],[54.804951,73.584381],[54.802879,73.586372],[54.801941,73.587173],[54.800018,73.588654],[54.797569,73.590477],[54.792831,73.594032],[54.790249,73.595993],[54.785229,73.599648],[54.783138,73.601173],[54.7789,73.604309],[54.777069,73.605827],[54.775532,73.607147],[54.773121,73.609169],[54.770748,73.611153],[54.769341,73.612419],[54.768372,73.613197],[54.767658,73.613731],[54.766941,73.614067],[54.765961,73.614388],[54.765011,73.614693],[54.762569,73.615463],[54.761711,73.615753],[54.756569,73.617012],[54.754822,73.617607],[54.75317,73.61837],[54.75164,73.61927],[54.74894,73.621391],[54.745152,73.625214],[54.74316,73.62812],[54.741089,73.63163],[54.73513,73.641647],[54.730511,73.64946],[54.728809,73.652367],[54.721882,73.664207],[54.718559,73.669907],[54.71759,73.671562],[54.71666,73.673203],[54.715672,73.674896],[54.71521,73.67569],[54.71471,73.676537],[54.714008,73.677742],[54.713322,73.678917],[54.712662,73.680054],[54.712009,73.68116],[54.71133,73.68232],[54.710011,73.684593],[54.709129,73.686089],[54.708408,73.687332],[54.70797,73.688103],[54.706661,73.690353],[54.705219,73.692848],[54.704529,73.694031],[54.70319,73.69635],[54.697128,73.706757],[54.689751,73.717232],[54.689121,73.718262],[54.688412,73.719704],[54.685791,73.725609],[54.682621,73.732887],[54.681629,73.735649],[54.678638,73.74453],[54.676231,73.752121],[54.675499,73.754539],[54.67506,73.756592],[54.67461,73.759506],[54.669811,73.787872],[54.669552,73.789726],[54.66946,73.790932],[54.66943,73.793213],[54.669441,73.796127],[54.669491,73.80822],[54.669498,73.813004],[54.66938,73.815773],[54.669189,73.818489],[54.66906,73.819817],[54.66888,73.821373],[54.66692,73.835472],[54.664951,73.849541],[54.66441,73.853378],[54.664131,73.856163],[54.66404,73.859467],[54.664108,73.868423],[54.664131,73.870811],[54.664131,73.872337],[54.664139,73.874138],[54.664139,73.875427],[54.664082,73.876633],[54.66396,73.877777],[54.66383,73.878563],[54.663601,73.879478],[54.661869,73.884644],[54.661739,73.884933],[54.661201,73.886253],[54.66032,73.887688],[54.658298,73.890327],[54.657089,73.891907],[54.653198,73.896843],[54.65168,73.8992],[54.650318,73.901703],[54.648449,73.905403],[54.64526,73.911743],[54.637871,73.926323],[54.63044,73.941048],[54.626869,73.948608],[54.625771,73.951218],[54.624969,73.953522],[54.624229,73.956398],[54.623772,73.958412],[54.623428,73.960419],[54.623169,73.962578],[54.622849,73.966873],[54.621651,73.982079],[54.621319,73.984642],[54.62075,73.987991],[54.619888,73.991478],[54.61832,73.99633],[54.6152,74.003807],[54.614269,74.005737],[54.613159,74.007507],[54.61132,74.009789],[54.610828,74.010269],[54.609489,74.011414],[54.607498,74.012581],[54.604549,74.013771],[54.60173,74.014954],[54.5989,74.016251],[54.597881,74.01693],[54.597019,74.017609],[54.595379,74.019257],[54.59425,74.020737],[54.59322,74.022461],[54.59129,74.02655],[54.588409,74.032707],[54.587582,74.034554],[54.587109,74.035896],[54.586449,74.038002],[54.56488,74.108017],[54.564659,74.109169],[54.564449,74.110786],[54.564301,74.112923],[54.56377,74.130463],[54.563648,74.134773],[54.563492,74.136871],[54.563049,74.14006],[54.561069,74.153923],[54.560181,74.160744],[54.560211,74.16169],[54.560322,74.162651],[54.560509,74.163544],[54.567749,74.19046],[54.56805,74.191902],[54.568218,74.193542],[54.568199,74.194687],[54.567101,74.211533],[54.566978,74.212936],[54.5667,74.214546],[54.566319,74.215927],[54.562851,74.228378],[54.559299,74.240852],[54.552349,74.265221],[54.548969,74.276917],[54.54813,74.279793],[54.547531,74.281807],[54.546871,74.283401],[54.546299,74.28463],[54.545761,74.285744],[54.544842,74.287163],[54.54385,74.288544],[54.541809,74.290909],[54.538528,74.294937],[54.536869,74.297394],[54.536251,74.298447],[54.508018,74.353081],[54.506748,74.355583],[54.505489,74.358482],[54.504688,74.360657],[54.501949,74.369324],[54.496738,74.385857],[54.495602,74.389122],[54.494999,74.39032],[54.493629,74.392097],[54.493038,74.392776],[54.492298,74.393509],[54.491581,74.394119],[54.490971,74.394417],[54.49036,74.394653],[54.482731,74.396332],[54.481281,74.396652],[54.47961,74.397217],[54.47773,74.398064],[54.47562,74.399193],[54.474232,74.400238],[54.472851,74.401466],[54.471191,74.403214],[54.465809,74.409119],[54.45887,74.417],[54.445148,74.432838],[54.443569,74.434883],[54.44215,74.43718],[54.438179,74.444542],[54.43362,74.453758],[54.431332,74.458389],[54.429119,74.462929],[54.428329,74.464737],[54.42783,74.46611],[54.427052,74.468918],[54.413139,74.523643],[54.408821,74.545128],[54.4081,74.548126],[54.407089,74.55146],[54.405781,74.555069],[54.404621,74.557716],[54.40308,74.560806],[54.397282,74.571693],[54.395721,74.574806],[54.394821,74.577019],[54.393589,74.580391],[54.390739,74.589546],[54.386841,74.602287],[54.384472,74.608887],[54.381611,74.616341],[54.380341,74.619423],[54.378719,74.622581],[54.377731,74.624138],[54.373112,74.630463],[54.372139,74.631493],[54.370991,74.632347],[54.368649,74.633347],[54.364368,74.634827],[54.361431,74.635269],[54.357738,74.635162],[54.354401,74.635063],[54.350929,74.635101],[54.35017,74.635292],[54.34927,74.635674],[54.347839,74.636597],[54.346142,74.638138],[54.343109,74.641037],[54.340832,74.643372],[54.338032,74.646744],[54.332062,74.654007],[54.330589,74.655312],[54.329369,74.655983],[54.32576,74.657303],[54.32243,74.658546],[54.31868,74.659607],[54.29874,74.664368],[54.28014,74.66861],[54.278061,74.669518],[54.277,74.670227],[54.27573,74.671837],[54.27396,74.674751],[54.270531,74.681053],[54.266659,74.687439],[54.265072,74.68988],[54.26413,74.69091],[54.263069,74.69165],[54.26123,74.69252],[54.258911,74.692818],[54.256908,74.692574],[54.252628,74.692329],[54.243259,74.69162],[54.242008,74.691994],[54.24091,74.692574],[54.23978,74.693321],[54.23801,74.695251],[54.232651,74.700867],[54.230331,74.703293],[54.228249,74.705643],[54.226002,74.708588],[54.217861,74.718651],[54.209229,74.729713],[54.208382,74.731133],[54.205688,74.735611],[54.204262,74.737709],[54.20097,74.741524],[54.1954,74.747887],[54.190639,74.753242],[54.1852,74.759453],[54.17564,74.770332],[54.17469,74.771637],[54.173908,74.773117],[54.173279,74.774544],[54.172661,74.776466],[54.17202,74.77993],[54.17197,74.781616],[54.171879,74.783997],[54.17141,74.797913],[54.1712,74.802879],[54.170959,74.805511],[54.170601,74.80851],[54.170292,74.810463],[54.169842,74.812538],[54.16922,74.815399],[54.16898,74.816101],[54.168621,74.817009],[54.168159,74.818069],[54.167782,74.81871],[54.167339,74.819366],[54.166931,74.819893],[54.166618,74.820236],[54.16618,74.820663],[54.164379,74.822258],[54.163761,74.8228],[54.16143,74.824837],[54.157959,74.828072],[54.15588,74.830551],[54.15414,74.833023],[54.14859,74.841667],[54.145859,74.846199],[54.143539,74.850693],[54.126171,74.884651],[54.124008,74.888924],[54.12291,74.891113],[54.121391,74.893867],[54.119881,74.896347],[54.118961,74.897758],[54.11771,74.89959],[54.114922,74.90313],[54.112419,74.906281],[54.107731,74.912079],[54.095638,74.927193],[54.082512,74.94352],[54.079971,74.946693],[54.07436,74.953697],[54.071671,74.957077],[54.07008,74.958763],[54.06942,74.959419],[54.06868,74.960037],[54.06826,74.960327],[54.0672,74.961037],[54.06625,74.96151],[54.065159,74.961899],[54.06414,74.962181],[54.06308,74.96244],[54.062809,74.962463],[54.06152,74.962547],[54.052841,74.96302],[54.042881,74.963631],[54.03878,74.963852],[54.036629,74.963966],[54.034752,74.964188],[54.032211,74.964867],[54.029732,74.965874],[54.029461,74.966057],[54.02747,74.967407],[54.025749,74.96875],[54.018269,74.976044],[54.003441,74.990593],[53.999821,74.994102],[53.99894,74.995117],[53.998291,74.99604],[53.997601,74.997261],[53.996941,74.998703],[53.984928,75.026604],[53.981758,75.034012],[53.978291,75.04216],[53.970989,75.059402],[53.969181,75.063629],[53.966042,75.071037],[53.96199,75.080719],[53.961559,75.081619],[53.961201,75.082138],[53.96077,75.082573],[53.9603,75.082916],[53.959782,75.083122],[53.958988,75.083282],[53.952808,75.083763],[53.9506,75.083946],[53.93763,75.085129],[53.922729,75.086388],[53.92065,75.086517],[53.919949,75.086433],[53.91959,75.086357],[53.919189,75.08625],[53.918758,75.086113],[53.917461,75.085457],[53.91608,75.084793],[53.89254,75.073143],[53.886509,75.070107],[53.885971,75.069847],[53.885059,75.069397],[53.85207,75.053047],[53.845581,75.049728],[53.84314,75.048271],[53.841831,75.047333],[53.84074,75.046448],[53.840061,75.04612],[53.83939,75.045952],[53.834179,75.045486],[53.827469,75.045013],[53.822979,75.044693],[53.816269,75.044777],[53.814781,75.044838],[53.81382,75.044991],[53.809139,75.046387],[53.80328,75.048576],[53.797321,75.051277],[53.79525,75.052208],[53.790722,75.054222],[53.789162,75.054916],[53.788269,75.055367],[53.78756,75.055847],[53.786701,75.056519],[53.78455,75.058311],[53.778759,75.063278],[53.770481,75.070412],[53.757198,75.081909],[53.743389,75.093674],[53.73756,75.098572],[53.73172,75.103493],[53.720261,75.113182],[53.71302,75.11937],[53.707291,75.124252],[53.701962,75.128807],[53.69809,75.131989],[53.696869,75.132973],[53.69524,75.133926],[53.694248,75.134338],[53.69186,75.135223],[53.68578,75.13723],[53.677029,75.140228],[53.668419,75.143494],[53.659451,75.147034],[53.655479,75.148529],[53.653591,75.149269],[53.652241,75.150063],[53.65065,75.151268],[53.649139,75.152771],[53.64782,75.154587],[53.64653,75.156967],[53.645119,75.159668],[53.64109,75.167503],[53.617321,75.213669],[53.616631,75.214951],[53.615372,75.21682],[53.614319,75.218132],[53.61301,75.219513],[53.609341,75.223221],[53.604671,75.22805],[53.600021,75.232803],[53.596169,75.236603],[53.593948,75.239014],[53.59288,75.240448],[53.591839,75.242027],[53.58976,75.245743],[53.581951,75.260193],[53.58073,75.262482],[53.579708,75.264648],[53.57502,75.274643],[53.563271,75.299721],[53.562321,75.301727],[53.56139,75.303436],[53.56044,75.304993],[53.559071,75.306717],[53.55759,75.308319],[53.555511,75.310303],[53.553242,75.312363],[53.541851,75.323303],[53.537479,75.327553],[53.536171,75.32901],[53.53511,75.330566],[53.534489,75.331772],[53.534012,75.33287],[53.53347,75.334244],[53.53289,75.33622],[53.53075,75.345459],[53.528622,75.355003],[53.528259,75.356331],[53.52763,75.357857],[53.526871,75.359642],[53.519531,75.37545],[53.511829,75.391869],[53.507961,75.400261],[53.50388,75.409187],[53.496349,75.425369],[53.49411,75.429611],[53.487141,75.440918],[53.481949,75.449371],[53.480419,75.451622],[53.47884,75.453377],[53.477699,75.454468],[53.471352,75.459686],[53.45953,75.469933],[53.45129,75.47657],[53.4426,75.484047],[53.423809,75.499657],[53.405899,75.514816],[53.403011,75.517319],[53.400982,75.519676],[53.39257,75.529907],[53.379131,75.546082],[53.376369,75.549454],[53.373638,75.552551],[53.368839,75.557251],[53.361271,75.564484],[53.354622,75.57151],[53.346741,75.579842],[53.33374,75.593536],[53.332199,75.59507],[53.33054,75.596237],[53.32309,75.600822],[53.313171,75.60701],[53.303429,75.614983],[53.292061,75.625847],[53.28054,75.636963],[53.274841,75.642403],[53.269409,75.647438],[53.257622,75.658234],[53.25679,75.659019],[53.256062,75.659882],[53.25528,75.661018],[53.236881,75.692253],[53.224159,75.71373],[53.210369,75.737007],[53.184189,75.781197],[53.1828,75.783539],[53.18124,75.786362],[53.179989,75.7892],[53.178551,75.792747],[53.144051,75.880463],[53.13903,75.893288],[53.137718,75.896294],[53.121521,75.928673],[53.104469,75.962639],[53.103729,75.964798],[53.103119,75.967133],[53.098629,75.986427],[53.093159,76.010643],[53.08239,76.056717],[53.080021,76.06707],[53.079861,76.068283],[53.079788,76.06926],[53.079781,76.070702],[53.080002,76.072983],[53.083778,76.089394],[53.084011,76.092072],[53.083801,76.095413],[53.083351,76.098213],[53.081211,76.11013],[53.08083,76.112244],[53.079491,76.12011],[53.07848,76.123863],[53.077518,76.126373],[53.07658,76.128304],[53.075481,76.130173],[53.074551,76.131371],[53.073181,76.132782],[53.066799,76.138641],[53.060459,76.144562],[53.059891,76.145302],[53.058708,76.147507],[53.057671,76.150543],[53.046391,76.198189],[53.033669,76.251053],[53.03017,76.261673],[53.023602,76.281303],[53.01313,76.312683],[53.0103,76.321152],[52.99239,76.374603],[52.99131,76.377548],[52.988701,76.383408],[52.975609,76.412643],[52.959789,76.447762],[52.92849,76.517548],[52.927078,76.520401],[52.92522,76.523666],[52.923599,76.526367],[52.920731,76.531143],[52.912281,76.545067],[52.895981,76.571693],[52.894341,76.573639],[52.892899,76.575043],[52.89151,76.576134],[52.889301,76.577538],[52.879879,76.583122],[52.865108,76.59198],[52.838959,76.607697],[52.810711,76.624588],[52.79121,76.636238],[52.78701,76.638847],[52.78595,76.63945],[52.784939,76.640167],[52.736191,76.680183],[52.68597,76.721161],[52.684212,76.722443],[52.672199,76.730026],[52.656841,76.739647],[52.62907,76.757202],[52.618359,76.763992],[52.605968,76.771767],[52.58215,76.78669],[52.5345,76.816727],[52.52211,76.821098],[52.50993,76.825706],[52.485432,76.834663],[52.466202,76.84169],[52.40942,76.862663],[52.396179,76.868889],[52.37986,76.876846],[52.35146,76.890556],[52.35067,76.890938],[52.34148,76.89537],[52.329899,76.900993],[52.329559,76.901169],[52.32811,76.901947],[52.327049,76.902847],[52.326469,76.903397],[52.32436,76.90583],[52.313049,76.919693],[52.310089,76.923309],[52.309891,76.928452],[52.309071,76.94117],[52.308632,76.947121],[52.308498,76.949203],[52.308369,76.951317],[52.308079,76.955162],[52.307919,76.957283],[52.307789,76.958031],[52.307579,76.958633],[52.304588,76.960541],[52.302189,76.962097],[52.300522,76.963142],[52.29739,76.965118],[52.296429,76.965652],[52.296188,76.965668],[52.293209,76.965912],[52.291851,76.965919],[52.291389,76.965927],[52.290791,76.965988],[52.287601,76.966316],[52.285809,76.966431],[52.285671,76.966454],[52.28458,76.966713],[52.284031,76.967018],[52.28352,76.967438],[52.28307,76.967552],[52.275909,76.968437],[52.270489,76.96904],[52.268452,76.969261],[52.26461,76.969704],[52.264389,76.969749],[52.256741,76.970581],[52.25338,76.971031],[52.2528,76.97126],[52.252251,76.971741],[52.249111,76.976593],[52.24733,76.979172],[52.245079,76.982422],[52.245258,76.982758],[52.246681,76.985359],[52.245049,76.987846],[52.243629,76.985168],[52.24118,76.988808],[52.23851,76.992683],[52.23737,76.994247],[52.236721,76.995132],[52.232681,77.00103],[52.231129,77.003418],[52.22633,77.009827],[52.224651,77.011932],[52.223228,77.01329],[52.22081,77.014862],[52.20134,77.027008],[52.192451,77.033051],[52.155258,77.060623],[52.128948,77.078407],[52.120579,77.085007],[52.115608,77.089149],[52.114368,77.090462],[52.110329,77.095573],[52.087749,77.126488],[52.02565,77.220383],[52.017818,77.23365],[52.014431,77.238632],[52.009892,77.244614],[52.008942,77.245781],[52.003288,77.252037],[51.994431,77.26181],[51.987881,77.268944],[51.926472,77.334503],[51.91893,77.343452],[51.913319,77.350563],[51.91114,77.354134],[51.909191,77.358391],[51.90554,77.370628],[51.902649,77.381416],[51.90229,77.38253],[51.901718,77.384003],[51.900742,77.38607],[51.891979,77.400917],[51.8848,77.414436],[51.882252,77.419601],[51.881031,77.421867],[51.876968,77.426117],[51.86919,77.435799],[51.863548,77.443611],[51.861462,77.446404],[51.859451,77.448517],[51.856781,77.450691],[51.854179,77.452042],[51.828972,77.461777],[51.824478,77.463768],[51.820309,77.466713],[51.811329,77.473358],[51.805752,77.477402],[51.80146,77.480957],[51.79636,77.485367],[51.789841,77.490677],[51.770279,77.50605],[51.768761,77.507408],[51.76709,77.509178],[51.765709,77.510872],[51.73035,77.557549],[51.729481,77.558502],[51.728081,77.559578],[51.726379,77.560402],[51.725151,77.560593],[51.723949,77.560516],[51.722801,77.560226],[51.701229,77.551262],[51.70013,77.55098],[51.698509,77.550873],[51.697948,77.550949],[51.696819,77.5513],[51.681561,77.556793],[51.67968,77.557678],[51.67807,77.558594],[51.67651,77.559669],[51.65694,77.573929],[51.654819,77.5756],[51.6525,77.577698],[51.650768,77.579529],[51.637829,77.594147],[51.637039,77.594841],[51.635929,77.595558],[51.634789,77.5961],[51.633911,77.596329],[51.615162,77.599907],[51.614288,77.600143],[51.612862,77.600708],[51.61203,77.601196],[51.61095,77.60202],[51.597519,77.613213],[51.594929,77.615112],[51.5923,77.616814],[51.589958,77.61821],[51.54343,77.643517],[51.540958,77.644943],[51.539619,77.645889],[51.537781,77.647423],[51.53088,77.653717],[51.527859,77.656578],[51.52644,77.658257],[51.52536,77.659866],[51.522968,77.663757],[51.507431,77.6903],[51.5005,77.706619],[51.49971,77.708763],[51.491711,77.729446],[51.48793,77.741676],[51.487179,77.746033],[51.479191,77.798149],[51.477859,77.808937],[51.478561,77.820137],[51.47921,77.829269],[51.47839,77.838791],[51.473591,77.889008],[51.472099,77.898453],[51.47068,77.90657],[51.469509,77.91227],[51.468201,77.917809],[51.465511,77.928558],[51.46513,77.931038],[51.465,77.93309],[51.464909,77.935493],[51.464779,77.937134],[51.464298,77.945389],[51.463741,77.956268],[51.461029,77.989197],[51.460812,77.991142],[51.458012,78.012352],[51.45776,78.014717],[51.448521,78.092888],[51.44817,78.096573],[51.448158,78.098442],[51.4487,78.141037],[51.448662,78.141899],[51.447891,78.145554],[51.427341,78.207191],[51.418861,78.225723],[51.41803,78.22789],[51.40752,78.26239],[51.396679,78.298233],[51.39542,78.302254],[51.394371,78.304718],[51.394211,78.304947],[51.39386,78.305511],[51.393478,78.306084],[51.366341,78.342201],[51.358009,78.354073],[51.35482,78.360786],[51.233669,78.603119],[51.220341,78.630928],[51.188259,78.696838],[51.18729,78.69886],[51.186729,78.700058],[51.18626,78.701118],[51.124222,78.829292],[51.12355,78.830757],[51.12236,78.833801],[51.121422,78.837013],[51.12114,78.838249],[51.12051,78.841789],[51.095852,79.064957],[51.095509,79.068718],[51.095379,79.069504],[51.095032,79.071701],[51.09404,79.073753],[51.09264,79.075302],[51.079861,79.086357],[51.078751,79.087646],[51.07251,79.098297],[51.071159,79.100227],[51.05582,79.115723],[51.049122,79.122276],[51.046509,79.123253],[51.041889,79.123398],[51.039131,79.123734],[51.037231,79.125229],[51.035229,79.12896],[51.027439,79.144852],[51.026489,79.147476],[51.02626,79.148773],[51.02179,79.177223],[51.021488,79.178841],[51.020741,79.18203],[51.01981,79.187233],[51.01717,79.20491],[51.016891,79.206558],[51.016541,79.208183],[51.016029,79.210136],[51.015579,79.211617],[51.007591,79.234901],[51.005562,79.242317],[51.003342,79.251389],[51.003021,79.252533],[51.002659,79.253593],[51.001808,79.255669],[50.98951,79.284027],[50.98748,79.287827],[50.962818,79.324883],[50.962559,79.325447],[50.962379,79.326103],[50.962212,79.327141],[50.959042,79.355682],[50.958809,79.356934],[50.958149,79.358727],[50.957802,79.359367],[50.953659,79.365479],[50.930439,79.399277],[50.926579,79.403992],[50.918289,79.412323],[50.916969,79.413887],[50.913879,79.419724],[50.893089,79.460503],[50.872532,79.485619],[50.866772,79.489517],[50.82011,79.513809],[50.816929,79.5168],[50.814468,79.520363],[50.80534,79.535316],[50.795849,79.544861],[50.793091,79.548866],[50.770229,79.570343],[50.766281,79.576218],[50.758541,79.596062],[50.746498,79.631073],[50.731331,79.676567],[50.720749,79.708328],[50.703209,79.74054],[50.69994,79.747147],[50.69088,79.768768],[50.683689,79.79467],[50.67292,79.832642],[50.670799,79.840111],[50.662849,79.868134],[50.661018,79.872467],[50.65765,79.878677],[50.655571,79.882507],[50.63998,79.910912],[50.636139,79.916557],[50.620838,79.939331],[50.61507,79.951691],[50.600399,79.982117],[50.585468,80.013718],[50.580212,80.02227],[50.577808,80.02652],[50.57518,80.034264],[50.573009,80.041977],[50.57056,80.050537],[50.56884,80.056877],[50.566608,80.062363],[50.559872,80.072617],[50.553612,80.081573],[50.54895,80.091049],[50.54501,80.096603],[50.542839,80.097717],[50.533352,80.099632],[50.530899,80.100929],[50.525398,80.104149],[50.522221,80.105339],[50.51479,80.106903],[50.508839,80.10836],[50.507149,80.109169],[50.50613,80.109894],[50.505871,80.110092],[50.505508,80.110397],[50.499519,80.118111],[50.49921,80.118668],[50.498772,80.119797],[50.49789,80.123573],[50.49752,80.124908],[50.496269,80.129204],[50.495819,80.130363],[50.495411,80.131073],[50.49308,80.133904],[50.491718,80.135551],[50.490509,80.136971],[50.490189,80.137268],[50.486549,80.139992],[50.485451,80.140953],[50.481461,80.144653],[50.480961,80.14537],[50.480141,80.147072],[50.479561,80.148903],[50.479019,80.150627],[50.47871,80.151627],[50.478321,80.152977],[50.4776,80.156029],[50.477539,80.156303],[50.474152,80.174263],[50.473228,80.17939],[50.472271,80.184387],[50.47208,80.185463],[50.47179,80.187027],[50.47139,80.18969],[50.470718,80.196457],[50.470322,80.200493],[50.470058,80.202507],[50.469769,80.20388],[50.469521,80.204887],[50.469299,80.205589],[50.46806,80.20974],[50.46624,80.216202],[50.465012,80.21991],[50.46447,80.221497],[50.464031,80.222557],[50.463169,80.224312],[50.461349,80.227753],[50.460651,80.228928],[50.45948,80.230789],[50.458599,80.232033],[50.458118,80.232437],[50.456772,80.233307],[50.453121,80.235207],[50.448212,80.237793],[50.447819,80.237923],[50.447571,80.23793],[50.44733,80.237831],[50.447201,80.237694],[50.4459,80.236343],[50.44566,80.23613],[50.445492,80.235977],[50.445301,80.235924],[50.444969,80.23587],[50.444519,80.236481],[50.443932,80.237343],[50.443802,80.237633],[50.443722,80.237961],[50.443378,80.24015],[50.443199,80.241318],[50.44313,80.242111],[50.443039,80.243042],[50.442871,80.243759],[50.44278,80.244011],[50.442669,80.244308],[50.44231,80.24485],[50.441528,80.245911],[50.440762,80.24691],[50.440552,80.247276],[50.440559,80.251106],[50.440559,80.251862],[50.440571,80.255997],[50.44059,80.259911],[50.439892,80.258827],[50.438789,80.257118],[50.437721,80.25544],[50.437061,80.254433],[50.436649,80.253639],[50.436298,80.253082],[50.435532,80.251907],[50.434078,80.249634],[50.4338,80.249153],[50.432331,80.246696],[50.430851,80.244049],[50.429489,80.241982],[50.427849,80.239441],[50.426769,80.237717],[50.425671,80.235977],[50.424549,80.234207],[50.42345,80.232437],[50.422421,80.230797],[50.422329,80.230598],[50.422291,80.230423],[50.422272,80.230331],[50.422272,80.230019],[50.422218,80.229637],[50.422138,80.229317],[50.421902,80.228851],[50.4217,80.228592],[50.4216,80.228523],[50.42128,80.228302],[50.420979,80.228241],[50.420738,80.228401],[50.420589,80.228691],[50.42046,80.228798],[50.420231,80.228882],[50.419559,80.228821],[50.418201,80.228569],[50.41748,80.228432],[50.416191,80.22805],[50.415661,80.227791],[50.414989,80.227432],[50.414131,80.226929],[50.4053,80.221863],[50.40469,80.221527],[50.403019,80.221031],[50.402401,80.220863],[50.401581,80.220741],[50.401031,80.220657],[50.399311,80.22039],[50.39875,80.220543],[50.398548,80.220642],[50.398361,80.220787],[50.398159,80.220871],[50.397999,80.220901],[50.397629,80.220718],[50.3974,80.220711],[50.397072,80.220772],[50.396671,80.221039],[50.396351,80.221352],[50.395809,80.221992],[50.395439,80.222527],[50.395168,80.223038],[50.39502,80.223373],[50.39489,80.223763],[50.394798,80.223953],[50.394661,80.224113],[50.39455,80.224182],[50.394402,80.224228],[50.39402,80.224243],[50.39362,80.224319],[50.393101,80.224457],[50.392429,80.224716],[50.391159,80.225403],[50.390282,80.226082],[50.389118,80.22702],[50.385971,80.229622],[50.38485,80.23037],[50.38287,80.231682],[50.38155,80.232513],[50.380508,80.233391],[50.37973,80.234268],[50.37862,80.235771],[50.378281,80.236259],[50.378132,80.236458],[50.37574,80.239532],[50.37561,80.239922],[50.374352,80.241722],[50.37109,80.24633],[50.370972,80.246513],[50.368279,80.250412],[50.366982,80.252296],[50.36483,80.254951],[50.364552,80.255524],[50.363361,80.256828],[50.363029,80.256187],[50.36293,80.256058],[50.36277,80.255997],[50.36264,80.256119],[50.362091,80.25679],[50.361591,80.25737],[50.36013,80.259033],[50.359909,80.259407],[50.359852,80.25985],[50.359909,80.260277],[50.35997,80.260773],[50.3601,80.26178],[50.360271,80.263077],[50.36031,80.263931],[50.360378,80.265427],[50.360409,80.266212],[50.360451,80.267143],[50.360451,80.267761],[50.360378,80.268303],[50.36002,80.269943],[50.359829,80.27034],[50.359718,80.270462],[50.35952,80.270691],[50.358528,80.271301],[50.358398,80.271477],[50.357769,80.272652],[50.355282,80.276718],[50.353569,80.279518],[50.352551,80.281174],[50.349991,80.285347],[50.348801,80.287376],[50.34771,80.28933],[50.34613,80.292107],[50.344971,80.294273],[50.34164,80.300957],[50.339989,80.30381],[50.31815,80.339973],[50.317699,80.3405],[50.3097,80.352638],[50.29863,80.370323],[50.288872,80.387657],[50.254799,80.438637],[50.1786,80.543793],[50.147369,80.586998],[50.140499,80.595627],[50.129791,80.608902],[50.12748,80.611763],[50.125332,80.61425],[50.048908,80.68779],[50.013439,80.721893],[49.99485,80.740593],[49.99086,80.744957],[49.980228,80.756561],[49.977631,80.759216],[49.964771,80.772614],[49.960129,80.776558],[49.954281,80.780327],[49.948589,80.782913],[49.837891,80.833717],[49.83419,80.835533],[49.832191,80.837158],[49.80888,80.859039],[49.806938,80.860931],[49.797581,80.872002],[49.795361,80.87458],[49.794201,80.875519],[49.792919,80.875862],[49.782131,80.879662],[49.781448,80.879898],[49.77985,80.880836],[49.77879,80.882042],[49.777302,80.88385],[49.736259,80.945213],[49.733879,80.948143],[49.73111,80.950974],[49.673931,81.008041],[49.668369,81.014137],[49.662201,81.021088],[49.65498,81.028976],[49.646358,81.037537],[49.632919,81.050873],[49.631248,81.052078],[49.62986,81.052513],[49.625141,81.053543],[49.62352,81.054222],[49.621738,81.055252],[49.620129,81.056877],[49.605228,81.073448],[49.603111,81.076279],[49.59388,81.089241],[49.553799,81.14563],[49.5425,81.163139],[49.537991,81.17009],[49.53754,81.17112],[49.536152,81.171982],[49.532249,81.178162],[49.53075,81.180733],[49.523109,81.196442],[49.52261,81.198761],[49.52261,81.200989],[49.523109,81.203651],[49.52306,81.205711],[49.519772,81.231293],[49.5191,81.234207],[49.51704,81.241158],[49.509689,81.271461],[49.500149,81.299011],[49.499371,81.300636],[49.498089,81.302361],[49.48444,81.315964],[49.477909,81.323692],[49.474449,81.328407],[49.4725,81.331413],[49.470879,81.334503],[49.469261,81.338371],[49.455101,81.372704],[49.45393,81.374329],[49.45314,81.375107],[49.452301,81.37545],[49.445,81.376297],[49.443039,81.376823],[49.441429,81.377678],[49.44009,81.378883],[49.436741,81.383087],[49.435452,81.38472],[49.434219,81.38652],[49.433159,81.388237],[49.42725,81.401108],[49.421219,81.414253],[49.418541,81.419479],[49.411678,81.429916],[49.400391,81.447113],[49.39827,81.450287],[49.39156,81.461533],[49.38866,81.466682],[49.382511,81.47673],[49.380718,81.480247],[49.372341,81.49939],[49.37133,81.502136],[49.37072,81.504883],[49.36927,81.512001],[49.368649,81.514236],[49.367981,81.516037],[49.36647,81.518959],[49.364799,81.521713],[49.362339,81.525047],[49.356628,81.532257],[49.35479,81.53389],[49.34597,81.540771],[49.344952,81.541206],[49.343632,81.541473],[49.34333,81.541527],[49.340672,81.541313],[49.33812,81.541054],[49.335979,81.540817],[49.33514,81.540771],[49.334141,81.540863],[49.333038,81.54113],[49.332169,81.54155],[49.331421,81.542183],[49.329498,81.544533],[49.328152,81.546356],[49.32795,81.546631],[49.324299,81.551483],[49.322681,81.553627],[49.321751,81.554893],[49.321259,81.555237],[49.321011,81.555313],[49.32069,81.555267],[49.320511,81.555206],[49.320339,81.555031],[49.320141,81.554764],[49.32,81.554527],[49.319931,81.554253],[49.31987,81.553459],[49.319889,81.551407],[49.320042,81.544144],[49.320061,81.54332],[49.320091,81.541809],[49.320278,81.532089],[49.320541,81.520844],[49.321339,81.486343],[49.321339,81.484283],[49.321331,81.481621],[49.321308,81.47982],[49.32077,81.477058],[49.318619,81.468513],[49.318211,81.467102],[49.317501,81.464767],[49.31506,81.459068],[49.313931,81.456322],[49.29652,81.414993],[49.275181,81.364922],[49.254799,81.316856],[49.235931,81.271873],[49.23465,81.269058],[49.23217,81.264801],[49.230999,81.263184],[49.22913,81.261017],[49.226669,81.258499],[49.218109,81.250893],[49.19363,81.229141],[49.190189,81.22509],[49.189041,81.222366],[49.188091,81.219749],[49.187592,81.217003],[49.187149,81.214172],[49.187019,81.210899],[49.187302,81.204613],[49.187271,81.202583],[49.187061,81.200394],[49.186401,81.197197],[49.185638,81.195068],[49.18441,81.192802],[49.182369,81.190697],[49.179611,81.188919],[49.176208,81.187088],[49.174641,81.186363],[49.173618,81.185463],[49.172539,81.184052],[49.171612,81.182587],[49.17041,81.180519],[49.167099,81.174347],[49.16547,81.171173],[49.160641,81.158813],[49.15929,81.156151],[49.158119,81.154266],[49.1511,81.144478],[49.14925,81.141388],[49.147961,81.138901],[49.14621,81.134613],[49.145481,81.133408],[49.144531,81.132378],[49.142342,81.130493],[49.141048,81.128937],[49.140091,81.127403],[49.129929,81.109627],[49.128189,81.107323],[49.099369,81.076927],[49.09729,81.074699],[49.09594,81.072723],[49.09499,81.070839],[49.094372,81.069122],[49.09425,81.067413],[49.094372,81.065514],[49.0942,81.06337],[49.09351,81.059097],[49.091969,81.054367],[49.091129,81.052399],[49.089951,81.050339],[49.088772,81.048798],[49.071232,81.026314],[49.069771,81.024513],[49.068298,81.023216],[49.06707,81.02253],[49.059021,81.019096],[49.05661,81.017982],[49.048618,81.012573],[49.047379,81.011276],[49.037762,80.998329],[49.03619,80.996353],[49.03511,80.995407],[49.03371,80.994461],[49.020882,80.985367],[49.019501,80.984467],[49.014061,80.979347],[49.012428,80.978073],[49.01086,80.977211],[49.008888,80.976097],[49.00737,80.97464],[49.000839,80.966827],[48.999088,80.965027],[48.997849,80.963913],[48.99498,80.96199],[48.993118,80.960442],[48.99165,80.958298],[48.988419,80.95253],[48.987301,80.950897],[48.985722,80.94944],[48.984138,80.948486],[48.980709,80.947212],[48.978569,80.945923],[48.976822,80.944473],[48.95203,80.920937],[48.950581,80.919563],[48.94915,80.917877],[48.946911,80.913948],[48.913811,80.859528],[48.912689,80.8573],[48.9119,80.855164],[48.91127,80.852921],[48.910431,80.848801],[48.909691,80.846657],[48.903042,80.833443],[48.901741,80.831551],[48.900612,80.830002],[48.898918,80.828293],[48.89711,80.827003],[48.89357,80.825073],[48.887291,80.82206],[48.882999,80.819962],[48.881439,80.819473],[48.867081,80.817131],[48.866169,80.816963],[48.865391,80.816933],[48.864559,80.817062],[48.826309,80.825882],[48.824501,80.82666],[48.82275,80.827507],[48.82127,80.828537],[48.819519,80.830093],[48.80703,80.84082],[48.805389,80.84211],[48.803699,80.842957],[48.80172,80.843483],[48.798328,80.844597],[48.784302,80.850937],[48.783058,80.851288],[48.77718,80.851967],[48.775928,80.851967],[48.773079,80.85186],[48.76965,80.851547],[48.75919,80.850693],[48.756359,80.85054],[48.75177,80.848717],[48.739208,80.843727],[48.73711,80.842453],[48.735809,80.841164],[48.72823,80.829567],[48.726398,80.827591],[48.72459,80.826653],[48.722832,80.826393],[48.715981,80.82486],[48.71294,80.823891],[48.697102,80.817177],[48.691078,80.81456],[48.688881,80.813606],[48.687199,80.81292],[48.685501,80.812332],[48.683559,80.811493],[48.682331,80.810928],[48.68079,80.809769],[48.674721,80.80381],[48.670029,80.798843],[48.654549,80.782288],[48.652519,80.779533],[48.56625,80.656357],[48.562111,80.650528],[48.56052,80.649063],[48.558701,80.648117],[48.521759,80.631844],[48.514252,80.626694],[48.506981,80.62014],[48.470058,80.584862],[48.451328,80.564262],[48.445351,80.558434],[48.431862,80.544952],[48.428841,80.542213],[48.386341,80.499123],[48.384232,80.496117],[48.381611,80.492157],[48.36536,80.463501],[48.36467,80.462471],[48.36404,80.461952],[48.363251,80.4617],[48.359138,80.461868],[48.358231,80.461609],[48.35714,80.460922],[48.335468,80.440071],[48.334209,80.439377],[48.332901,80.43895],[48.33136,80.438698],[48.329479,80.438522],[48.303791,80.436546],[48.282089,80.435089],[48.280609,80.435013],[48.278839,80.435089],[48.276951,80.435349],[48.2565,80.442299],[48.218819,80.454918],[48.201778,80.461182],[48.199951,80.4617],[48.189301,80.464272],[48.18261,80.467102],[48.180321,80.467621],[48.178551,80.467789],[48.175289,80.467697],[48.151119,80.465637],[48.140419,80.464531],[48.138809,80.464012],[48.137661,80.463074],[48.13583,80.462547],[48.133202,80.462044],[48.129929,80.46067],[48.127239,80.459549],[48.125061,80.458183],[48.123798,80.457657],[48.120941,80.457237],[48.11853,80.456459],[48.114059,80.453888],[48.112919,80.453712],[48.110909,80.453712],[48.108559,80.454491],[48.102139,80.455261],[48.100361,80.455261],[48.094521,80.454659],[48.087639,80.453369],[48.082821,80.451309],[48.081959,80.450706],[48.0802,80.448807],[48.078949,80.446602],[48.07795,80.444893],[48.07597,80.443291],[48.073978,80.442009],[48.069759,80.440331],[48.068878,80.439133],[48.067829,80.436317],[48.066292,80.434669],[48.06041,80.433647],[48.05928,80.43306],[48.057381,80.43177],[48.05444,80.429626],[48.053261,80.428909],[48.051949,80.428711],[48.0438,80.429039],[48.0415,80.428818],[48.040199,80.428123],[48.03611,80.425949],[48.032051,80.423782],[48.030571,80.422501],[48.029652,80.421471],[48.02541,80.419167],[48.021198,80.416908],[48.019539,80.416183],[48.018749,80.4161],[48.017658,80.41629],[47.991871,80.420624],[47.99033,80.420883],[47.987949,80.420197],[47.987068,80.419563],[47.984379,80.416069],[47.98214,80.413673],[47.974831,80.406982],[47.963409,80.398438],[47.961182,80.397171],[47.958969,80.396156],[47.957169,80.395592],[47.955151,80.39521],[47.952431,80.394997],[47.948669,80.395233],[47.945518,80.395798],[47.940239,80.396606],[47.92968,80.398376],[47.927811,80.398933],[47.926281,80.399696],[47.924911,80.400841],[47.923679,80.402428],[47.92281,80.403801],[47.92189,80.405907],[47.921028,80.408737],[47.920361,80.413338],[47.920189,80.414627],[47.919071,80.421181],[47.917919,80.424767],[47.916519,80.42717],[47.915371,80.428757],[47.91367,80.430153],[47.912231,80.431068],[47.91,80.431641],[47.90947,80.431587],[47.908821,80.431511],[47.90741,80.43129],[47.90609,80.431107],[47.9039,80.430817],[47.901539,80.430519],[47.901409,80.430496],[47.901131,80.430527],[47.900841,80.430603],[47.9007,80.430649],[47.900421,80.430794],[47.900139,80.430977],[47.899738,80.43132],[47.89922,80.4319],[47.89888,80.432373],[47.89835,80.433281],[47.89814,80.433678],[47.897732,80.434517],[47.897449,80.43515],[47.897202,80.43576],[47.89706,80.436172],[47.896961,80.436607],[47.89687,80.437271],[47.896801,80.43882],[47.896111,80.441483],[47.8895,80.466629],[47.888458,80.469467],[47.88308,80.481781],[47.88253,80.484047],[47.88242,80.485947],[47.884239,80.498688],[47.884121,80.500748],[47.883259,80.503113],[47.872631,80.519592],[47.87114,80.521431],[47.86964,80.522461],[47.868599,80.523232],[47.867851,80.524094],[47.867081,80.525513],[47.865028,80.529671],[47.860371,80.535767],[47.846722,80.551987],[47.84539,80.552849],[47.843552,80.553879],[47.8428,80.554573],[47.84193,80.555679],[47.838188,80.558769],[47.824478,80.568977],[47.81485,80.57679],[47.79208,80.597733],[47.79047,80.599449],[47.788731,80.601768],[47.78735,80.603996],[47.785561,80.606148],[47.782742,80.608887],[47.762951,80.62709],[47.759609,80.629578],[47.752739,80.634468],[47.751869,80.635406],[47.75037,80.637993],[47.749512,80.639267],[47.748291,80.640556],[47.737209,80.650352],[47.735249,80.651627],[47.733231,80.652321],[47.730869,80.652496],[47.71777,80.652618],[47.71574,80.652786],[47.713951,80.653442],[47.71117,80.654472],[47.69194,80.662369],[47.684441,80.665321],[47.681252,80.667],[47.67836,80.667343],[47.67588,80.667603],[47.673679,80.668213],[47.672119,80.66906],[47.668591,80.671379],[47.66703,80.671982],[47.665409,80.671982],[47.66021,80.671204],[47.65744,80.670433],[47.655472,80.669144],[47.653679,80.667603],[47.650089,80.663834],[47.648769,80.661926],[47.64645,80.657806],[47.645531,80.656616],[47.644371,80.655586],[47.638119,80.650703],[47.636971,80.64949],[47.636341,80.648239],[47.635181,80.646782],[47.634201,80.645752],[47.632408,80.64489],[47.63055,80.644043],[47.628189,80.643257],[47.609489,80.641586],[47.595901,80.638283],[47.589649,80.636833],[47.587109,80.635887],[47.58363,80.633636],[47.578072,80.629959],[47.568802,80.623444],[47.56736,80.622231],[47.566078,80.621803],[47.564869,80.621628],[47.55537,80.622414],[47.549568,80.623093],[47.546799,80.623444],[47.543732,80.62336],[47.539551,80.622658],[47.532768,80.622917],[47.529751,80.623001],[47.526279,80.622147],[47.510658,80.61721],[47.487869,80.608543],[47.485722,80.607773],[47.480671,80.605751],[47.47731,80.604637],[47.43161,80.593521],[47.42905,80.592323],[47.421242,80.586311],[47.418598,80.584167],[47.416599,80.582916],[47.396759,80.579399],[47.392311,80.578667],[47.389759,80.579742],[47.387699,80.580429],[47.374851,80.580688],[47.372471,80.581078],[47.363312,80.584846],[47.360371,80.586273],[47.35825,80.586739],[47.352638,80.586647],[47.349819,80.587341],[47.34119,80.59259],[47.331879,80.597717],[47.319569,80.605148],[47.314831,80.610023],[47.300751,80.622543],[47.298939,80.623947],[47.296761,80.625023],[47.295071,80.626427],[47.292019,80.630363],[47.272099,80.654472],[47.270119,80.656708],[47.267269,80.658943],[47.260921,80.663689],[47.257599,80.666351],[47.25127,80.675407],[47.247211,80.683594],[47.246471,80.684959],[47.244949,80.686447],[47.243061,80.68705],[47.239849,80.687317],[47.233131,80.687828],[47.189499,80.691467],[47.144661,80.694481],[47.07082,80.699287],[47.052109,80.699966],[46.981419,80.698601],[46.977669,80.698257],[46.97451,80.696716],[46.971809,80.695],[46.969471,80.692078],[46.967251,80.688477],[46.935261,80.630463],[46.93327,80.626846],[46.930679,80.623589],[46.92189,80.6138],[46.89727,80.5858],[46.892929,80.58168],[46.890121,80.579361],[46.887299,80.57756],[46.861721,80.563393],[46.85849,80.562187],[46.85614,80.561417],[46.853561,80.560738],[46.839649,80.561081],[46.806992,80.561958],[46.728088,80.562302],[46.72385,80.56282],[46.721378,80.564018],[46.717739,80.56694],[46.714088,80.57106],[46.711262,80.575348],[46.709259,80.578957],[46.708199,80.581703],[46.706791,80.58342],[46.703732,80.583588],[46.68948,80.58342],[46.686069,80.583763],[46.683949,80.584793],[46.680531,80.588387],[46.678532,80.590446],[46.676289,80.591827],[46.674171,80.592346],[46.671822,80.59166],[46.666519,80.587883],[46.63953,80.570541],[46.635288,80.568657],[46.631519,80.568138],[46.628571,80.568481],[46.62513,80.569603],[46.557652,80.610458],[46.524948,80.630287],[46.49506,80.64814],[46.45723,80.670799],[46.428841,80.687798],[46.414989,80.696037],[46.413479,80.696259],[46.411678,80.696121],[46.41032,80.695602],[46.409321,80.695183],[46.40836,80.694923],[46.407001,80.694923],[46.405579,80.695351],[46.404751,80.695953],[46.402981,80.697411],[46.396648,80.703484],[46.384979,80.714737],[46.342571,80.749603],[46.303871,80.781372],[46.22459,80.846413],[46.207008,80.860657],[46.204029,80.863136],[46.19865,80.867607],[46.198219,80.868042],[46.197861,80.868729],[46.197861,80.869667],[46.198341,80.870354],[46.199711,80.87233],[46.200661,80.873878],[46.20298,80.880402],[46.203388,80.881767],[46.203449,80.883583],[46.20285,80.889503],[46.202621,80.89164],[46.201191,80.901688],[46.200062,80.904427],[46.19846,80.907349],[46.196499,80.910439],[46.190979,80.928886],[46.186642,80.939537],[46.185211,80.943008],[46.183781,80.947128],[46.182949,80.951332],[46.182598,80.955193],[46.182419,80.971069],[46.180462,80.972443],[46.176182,80.974503],[46.122959,81.002571],[46.11903,81.004288],[46.1157,81.006767],[46.086899,81.024117],[46.085949,81.024971],[46.085411,81.02626],[46.085171,81.027718],[46.084808,81.029182],[46.06403,81.067802],[46.061291,81.072441],[46.05891,81.075699],[46.01363,81.126251],[46.011719,81.128754],[46.010529,81.131401],[45.999378,81.170197],[45.99699,81.176643],[45.98489,81.20359],[45.983398,81.207283],[45.98209,81.2108],[45.974869,81.251556],[45.966999,81.295174],[45.96574,81.300751],[45.952202,81.352943],[45.92617,81.46151],[45.92474,81.467003],[45.923431,81.471207],[45.907719,81.513351],[45.884838,81.574379],[45.883888,81.576439],[45.88311,81.577553],[45.87851,81.58287],[45.841572,81.624672],[45.83918,81.627853],[45.82835,81.650421],[45.82291,81.661407],[45.782639,81.745087],[45.770489,81.775818],[45.711369,81.934608],[45.706032,81.947403],[45.701962,81.955116],[45.697521,81.961212],[45.695599,81.962929],[45.69392,81.963867],[45.69212,81.963959],[45.691051,81.963707],[45.686371,81.962837],[45.683491,81.962761],[45.682468,81.963188],[45.68079,81.964821],[45.58416,82.071327],[45.53891,82.121536],[45.502449,82.168114],[45.47237,82.206497],[45.435539,82.253471],[45.43288,82.256813],[45.352539,82.358437],[45.34301,82.370888],[45.295689,82.430367],[45.287159,82.441269],[45.282871,82.446083],[45.276649,82.452087],[45.258049,82.468567],[45.257339,82.469673],[45.256802,82.471046],[45.25655,82.472603],[45.256371,82.474907],[45.255772,82.476196],[45.255081,82.476967],[45.24276,82.492943],[45.24107,82.495087],[45.23835,82.500153],[45.23605,82.505562],[45.235748,82.50676],[45.235748,82.508476],[45.236408,82.513367],[45.23629,82.51474],[45.235691,82.516289],[45.234779,82.517754],[45.221298,82.542213],[45.217979,82.546928],[45.21302,82.553284],[45.21175,82.554398],[45.210171,82.555344],[45.208,82.556198],[45.2057,82.556969],[45.204491,82.557907],[45.200378,82.561691],[45.197479,82.564438],[45.195782,82.565468],[45.19421,82.56633],[45.19318,82.566406],[45.189789,82.565552],[45.17136,82.560516],[45.166561,82.559196],[45.163719,82.55809],[45.158691,82.556969],[45.152882,82.556717],[45.084499,82.560577],[45.081108,82.560997],[45.071529,82.563843],[45.0508,82.570007],[45.04612,82.571747],[45.04187,82.574661],[45.039688,82.57827],[45.01506,82.595444],[45.01239,82.597504],[45.005718,82.605743],[45.002682,82.608307],[44.99564,82.617073],[44.978771,82.627373],[44.958,82.636978],[44.947311,82.640244],[44.94281,82.639549],[44.936371,82.637833],[44.931629,82.632507],[44.93111,82.630547],[44.9258,82.610367],[44.903549,82.542389],[44.844742,82.543419],[44.835861,82.53981],[44.834709,82.554497],[44.825001,82.547546],[44.808102,82.535461],[44.803349,82.525513],[44.802368,82.523788],[44.798359,82.516747],[44.798481,82.514],[44.79129,82.502159],[44.78569,82.496147],[44.778252,82.493919],[44.77277,82.48774],[44.765209,82.48774],[44.7616,82.496841],[44.755459,82.512283],[44.755829,82.539062],[44.74157,82.540092],[44.725101,82.544388],[44.70644,82.549362],[44.700699,82.548683],[44.683128,82.544563],[44.676418,82.539917],[44.664211,82.517776],[44.65704,82.51091],[44.653099,82.507133],[44.595058,82.5037],[44.58345,82.503532],[44.582352,82.522926],[44.580879,82.523453],[44.557529,82.522873],[44.534039,82.522293],[44.52557,82.522072],[44.52927,82.554169],[44.5313,82.571716],[44.534229,82.594208],[44.53619,82.611549],[44.536442,82.617043],[44.536678,82.620987],[44.544998,82.64502],[44.546589,82.650337],[44.547451,82.655663],[44.548061,82.671463],[44.547199,82.679176],[44.547699,82.683823],[44.547699,82.686737],[44.546959,82.691711],[44.547451,82.696007],[44.547329,82.702187],[44.547569,82.705963],[44.545731,82.742699],[44.546101,82.745613],[44.554199,82.764877],[44.55444,82.765709],[44.557529,82.773193],[44.558979,82.777283],[44.56015,82.781342],[44.568581,82.81691],[44.569359,82.820198],[44.57032,82.823631],[44.571289,82.826576],[44.582081,82.85862],[44.582989,82.861427],[44.584259,82.865913],[44.585281,82.870201],[44.589359,82.889977],[44.590691,82.896233],[44.590988,82.897942],[44.59103,82.898331],[44.591629,82.901283],[44.592972,82.907463],[44.593128,82.908318],[44.594398,82.914139],[44.5956,82.919319],[44.595772,82.919952],[44.596539,82.921898],[44.597641,82.923813],[44.599129,82.92556],[44.59964,82.926018],[44.60025,82.926498],[44.601158,82.927078],[44.602718,82.927742],[44.608871,82.929962],[44.613121,82.931633],[44.61327,82.931717],[44.613789,82.93187],[44.617851,82.933357],[44.619282,82.933968],[44.628521,82.937401],[44.633331,82.93927],[44.63562,82.940033],[44.63689,82.940529],[44.637329,82.94075],[44.637859,82.940918],[44.641899,82.942482],[44.643261,82.943153],[44.643501,82.943359],[44.644581,82.944077],[44.645691,82.945137],[44.64632,82.945908],[44.647072,82.947403],[44.64753,82.948624],[44.647732,82.949257],[44.648071,82.950394],[44.648041,82.952026],[44.648121,82.954086],[44.647881,82.957283],[44.646622,82.960457],[44.645519,82.962517],[44.64283,82.96595],[44.640511,82.969559],[44.638519,82.972366],[44.63554,82.978752],[44.633381,82.985313],[44.632469,82.990089],[44.629028,83.018311],[44.627201,83.026718],[44.621578,83.048523],[44.615349,83.086113],[44.614861,83.091438],[44.615471,83.154221],[44.615681,83.190536],[44.61544,83.220917],[44.612629,83.238258],[44.601631,83.288887],[44.595638,83.3004],[44.59034,83.305893],[44.58234,83.314774],[44.57122,83.328331],[44.569988,83.330223],[44.565102,83.345497],[44.560581,83.365227],[44.551159,83.38755],[44.543209,83.426353],[44.542961,83.428749],[44.542839,83.452782],[44.549931,83.520592],[44.55006,83.523163],[44.549931,83.525574],[44.549568,83.527802],[44.54847,83.530891],[44.522888,83.596626],[44.51738,83.607964],[44.515301,83.610542],[44.493999,83.625816],[44.492531,83.626503],[44.49033,83.626678],[44.482121,83.626846],[44.480289,83.627708],[44.476238,83.630623],[44.474899,83.632339],[44.474159,83.634064],[44.473431,83.637154],[44.46228,83.72023],[44.46032,83.748039],[44.460442,83.753021],[44.464611,83.786148],[44.464851,83.791473],[44.462521,83.859108],[44.453579,83.898933],[44.43998,83.961418],[44.438141,83.967079],[44.41766,84.027496],[44.415581,84.031113],[44.38406,84.079178],[44.382961,84.081062],[44.381969,84.083122],[44.381359,84.086037],[44.379848,84.10498],[44.374119,84.176682],[44.371559,84.24231],[44.37125,84.250366],[44.371029,84.255867],[44.36956,84.293549],[44.369381,84.298866],[44.369419,84.305313],[44.369339,84.310707],[44.36924,84.314056],[44.368771,84.329811],[44.36895,84.336533],[44.369949,84.346283],[44.373421,84.381859],[44.374149,84.38546],[44.401112,84.488602],[44.401451,84.489929],[44.401489,84.49025],[44.401718,84.491364],[44.401939,84.492889],[44.402012,84.49366],[44.40205,84.494843],[44.40202,84.496437],[44.401958,84.497253],[44.401669,84.499237],[44.401421,84.500412],[44.401112,84.501549],[44.40057,84.503014],[44.399769,84.504753],[44.399059,84.506104],[44.39526,84.512733],[44.38364,84.533234],[44.382381,84.535522],[44.381882,84.536552],[44.381409,84.537643],[44.38113,84.538383],[44.38063,84.539909],[44.38044,84.54071],[44.38015,84.542343],[44.37999,84.543556],[44.379902,84.544807],[44.37986,84.546066],[44.37989,84.548592],[44.380539,84.571327],[44.38081,84.584824],[44.38163,84.621742],[44.38187,84.631577],[44.38195,84.634491],[44.38224,84.646912],[44.382339,84.648911],[44.382622,84.652283],[44.382851,84.654289],[44.383221,84.656693],[44.383591,84.65873],[44.38401,84.660812],[44.384491,84.662949],[44.38493,84.66465],[44.387989,84.675621],[44.395012,84.701317],[44.39798,84.712379],[44.398918,84.716614],[44.399319,84.718773],[44.399849,84.722267],[44.40015,84.724907],[44.400311,84.726669],[44.400551,84.730438],[44.401211,84.745941],[44.401871,84.761391],[44.40197,84.763748],[44.402451,84.774986],[44.40266,84.779877],[44.403,84.787857],[44.403179,84.791451],[44.40366,84.803093],[44.40369,84.805023],[44.40366,84.806641],[44.403519,84.809212],[44.403332,84.811028],[44.403172,84.812218],[44.40279,84.814468],[44.402401,84.816269],[44.401421,84.820137],[44.401199,84.821136],[44.400791,84.822662],[44.399288,84.828644],[44.399052,84.829597],[44.397511,84.835991],[44.396,84.842293],[44.39402,84.850548],[44.393211,84.855598],[44.392689,84.859741],[44.392189,84.865494],[44.39209,84.872017],[44.392109,84.87764],[44.39323,84.896751],[44.393291,84.902847],[44.393311,84.907852],[44.39307,84.916458],[44.393051,84.917793],[44.391701,84.944908],[44.391331,84.952461],[44.390469,84.958641],[44.38924,84.965851],[44.37661,85.01683],[44.373291,85.02816],[44.36483,85.052711],[44.36237,85.062317],[44.361019,85.069527],[44.360161,85.077087],[44.359669,85.083946],[44.359299,85.09185],[44.359669,85.099747],[44.36372,85.137863],[44.36433,85.146263],[44.36446,85.15313],[44.36433,85.160858],[44.36348,85.168922],[44.362,85.177849],[44.360039,85.184891],[44.357342,85.192963],[44.33942,85.237083],[44.33696,85.244797],[44.335121,85.251839],[44.333771,85.259743],[44.33316,85.267632],[44.333031,85.275528],[44.333889,85.284798],[44.334751,85.292862],[44.335121,85.299042],[44.335121,85.304192],[44.334511,85.310028],[44.334511,85.314323],[44.334869,85.322731],[44.336349,85.331833],[44.33831,85.342819],[44.338799,85.347282],[44.339169,85.352432],[44.339291,85.359642],[44.33905,85.365479],[44.337582,85.375954],[44.336472,85.384697],[44.335979,85.392601],[44.335979,85.403236],[44.33672,85.415077],[44.33979,85.453369],[44.340279,85.458],[44.341999,85.468483],[44.342731,85.474312],[44.343102,85.478783],[44.34322,85.484093],[44.343102,85.489243],[44.342491,85.495422],[44.338558,85.521858],[44.33794,85.528381],[44.337818,85.53405],[44.33807,85.545891],[44.33807,85.551041],[44.33733,85.556534],[44.336102,85.56237],[44.333771,85.568733],[44.33131,85.573883],[44.327141,85.579369],[44.322109,85.584343],[44.316212,85.588814],[44.312401,85.592758],[44.309212,85.596878],[44.306019,85.602028],[44.30331,85.607857],[44.30085,85.614899],[44.299011,85.622627],[44.298271,85.630524],[44.298149,85.639961],[44.29987,85.69558],[44.299381,85.703308],[44.298401,85.710693],[44.296799,85.718071],[44.28685,85.761147],[44.28574,85.768539],[44.284882,85.776947],[44.283161,85.799103],[44.282051,85.807854],[44.280331,85.816597],[44.27763,85.826042],[44.258949,85.880463],[44.256611,85.889732],[44.255131,85.898483],[44.25415,85.906563],[44.25354,85.914108],[44.25243,85.949982],[44.251942,85.956497],[44.25071,85.965431],[44.247509,85.98243],[44.246769,85.989639],[44.246399,85.995819],[44.246399,86.00354],[44.247021,86.009903],[44.25095,86.031181],[44.25563,86.052467],[44.25956,86.063797],[44.265461,86.077187],[44.26952,86.086113],[44.272099,86.093491],[44.273941,86.101387],[44.275169,86.109123],[44.275539,86.114433],[44.275661,86.120956],[44.275421,86.126793],[44.274681,86.133148],[44.273201,86.141037],[44.26226,86.187561],[44.246159,86.230133],[44.243328,86.239059],[44.24136,86.247993],[44.239891,86.257263],[44.23521,86.288498],[44.23312,86.298447],[44.2314,86.306183],[44.221561,86.339653],[44.216511,86.356651],[44.21455,86.363518],[44.21307,86.370728],[44.21233,86.377251],[44.21196,86.384277],[44.21233,86.39064],[44.212818,86.39682],[44.21418,86.403168],[44.216881,86.412613],[44.217991,86.418793],[44.218479,86.425659],[44.218479,86.432693],[44.217621,86.439217],[44.216019,86.445572],[44.213558,86.452606],[44.20052,86.483513],[44.198429,86.490196],[44.196701,86.497917],[44.195591,86.506851],[44.195221,86.515953],[44.195251,86.543556],[44.19471,86.554619],[44.19352,86.564163],[44.190159,86.588669],[44.189831,86.596909],[44.189831,86.604279],[44.19178,86.646683],[44.19178,86.655891],[44.1908,86.66391],[44.189499,86.671829],[44.186901,86.679314],[44.18372,86.68718],[44.18166,86.691147],[44.18071,86.692917],[44.178638,86.696259],[44.17778,86.697723],[44.176701,86.699837],[44.17556,86.702438],[44.174561,86.70517],[44.17395,86.70713],[44.17337,86.709412],[44.17284,86.71209],[44.172352,86.715782],[44.172249,86.71701],[44.17215,86.71917],[44.172009,86.728439],[44.171959,86.746559],[44.171791,86.759918],[44.171539,86.764847],[44.171219,86.768806],[44.17086,86.772324],[44.170589,86.774559],[44.1702,86.777046],[44.169151,86.782753],[44.16835,86.786324],[44.167511,86.789742],[44.166519,86.793556],[44.164181,86.802719],[44.16357,86.805313],[44.162861,86.808769],[44.16214,86.812958],[44.16148,86.818092],[44.161091,86.822517],[44.16058,86.831001],[44.160439,86.832359],[44.16008,86.834793],[44.159649,86.837013],[44.158669,86.840912],[44.157921,86.843369],[44.15683,86.846336],[44.155701,86.848953],[44.154442,86.851357],[44.153419,86.853218],[44.151951,86.855492],[44.15044,86.858032],[44.14957,86.859619],[44.148289,86.862106],[44.146641,86.865753],[44.145729,86.867897],[44.143909,86.872673],[44.14275,86.875504],[44.141731,86.877777],[44.1404,86.88047],[44.139519,86.882133],[44.13802,86.884773],[44.136848,86.886597],[44.13483,86.889458],[44.133209,86.891541],[44.131359,86.89373],[44.129169,86.896019],[44.119942,86.904999],[44.11771,86.907303],[44.114632,86.910797],[44.111851,86.914253],[44.109699,86.917122],[44.1073,86.920486],[44.105091,86.923759],[44.101471,86.928864],[44.097431,86.934837],[44.092442,86.942001],[44.091,86.944183],[44.08979,86.946167],[44.087761,86.949821],[44.086342,86.952797],[44.085121,86.955643],[44.083771,86.959244],[44.08276,86.962158],[44.08242,86.96331],[44.081749,86.96566],[44.08078,86.969597],[44.080059,86.973022],[44.076771,86.989891],[44.076229,86.992317],[44.07518,86.996613],[44.074291,86.999908],[44.072842,87.004631],[44.070599,87.010902],[44.069149,87.014557],[44.067589,87.018158],[44.066078,87.021446],[44.064331,87.024857],[44.06308,87.027153],[44.060379,87.031731],[44.053638,87.042503],[44.04911,87.049896],[44.046768,87.053978],[44.045158,87.056976],[44.043751,87.059807],[44.042549,87.062439],[44.037979,87.073174],[44.032749,87.085258],[44.03149,87.087898],[44.028469,87.093567],[44.027111,87.095787],[44.024738,87.099281],[44.022659,87.102112],[44.020248,87.105118],[44.017658,87.107986],[44.01181,87.113861],[44.006989,87.118851],[44.00354,87.122307],[44.0014,87.124702],[43.999149,87.127373],[43.995361,87.132362],[43.992489,87.136711],[43.990841,87.139389],[43.974121,87.167473],[43.972591,87.170227],[43.9706,87.174049],[43.969471,87.176369],[43.967602,87.180603],[43.966541,87.183228],[43.965569,87.185707],[43.96439,87.188911],[43.963001,87.192917],[43.954929,87.21653],[43.954769,87.216988],[43.953381,87.221046],[43.951832,87.226028],[43.950878,87.229561],[43.94986,87.233673],[43.9491,87.237152],[43.948372,87.240967],[43.94772,87.244904],[43.946381,87.25338],[43.945599,87.258263],[43.943878,87.26899],[43.943729,87.269943],[43.943661,87.270348],[43.94339,87.272049],[43.943081,87.273956],[43.94278,87.275772],[43.941769,87.280762],[43.941509,87.281837],[43.94083,87.284477],[43.940159,87.287323],[43.939629,87.289253],[43.939541,87.289574],[43.938251,87.293716],[43.93816,87.294029],[43.93755,87.295952],[43.935711,87.301018],[43.93557,87.301392],[43.93351,87.30648],[43.933399,87.306717],[43.9277,87.320503],[43.924629,87.327827],[43.924469,87.328171],[43.922958,87.331383],[43.92083,87.335472],[43.917881,87.340439],[43.915852,87.343498],[43.914989,87.344727],[43.9133,87.346977],[43.911129,87.349716],[43.908119,87.353493],[43.90696,87.35508],[43.905602,87.357002],[43.9044,87.358856],[43.90316,87.360962],[43.901939,87.36319],[43.900761,87.365501],[43.899651,87.367943],[43.898571,87.370491],[43.897621,87.373047],[43.89674,87.375633],[43.89579,87.37886],[43.895031,87.381783],[43.894871,87.382446],[43.894279,87.385109],[43.893951,87.386879],[43.893879,87.387268],[43.893501,87.389687],[43.893108,87.392593],[43.892899,87.394691],[43.892689,87.397362],[43.892529,87.400497],[43.892509,87.400887],[43.892479,87.404518],[43.89249,87.407967],[43.89249,87.411003],[43.89246,87.414047],[43.892361,87.415756],[43.892189,87.417381],[43.89196,87.419029],[43.891548,87.42086],[43.891022,87.422783],[43.8904,87.424583],[43.88958,87.426697],[43.88855,87.429367],[43.888359,87.42984],[43.88744,87.43222],[43.887341,87.43248],[43.886429,87.434799],[43.886311,87.435089],[43.88559,87.436859],[43.88485,87.438332],[43.884232,87.439407],[43.883789,87.440033],[43.883591,87.440277],[43.882641,87.441483],[43.881592,87.442558],[43.880539,87.443443],[43.879509,87.444138],[43.878349,87.444763],[43.87767,87.44503],[43.877491,87.445091],[43.876438,87.445389],[43.875191,87.445633],[43.873199,87.445862],[43.87233,87.446022],[43.871521,87.446297],[43.8708,87.446678],[43.86998,87.447144],[43.869301,87.447701],[43.868549,87.44841],[43.867981,87.449081],[43.86739,87.449913],[43.866821,87.450859],[43.866261,87.452019],[43.865822,87.453217],[43.864849,87.456688],[43.86478,87.456963],[43.86433,87.458298],[43.863811,87.459641],[43.863071,87.461128],[43.862381,87.462318],[43.861549,87.463501],[43.860691,87.464523],[43.85965,87.465569],[43.859409,87.465797],[43.85841,87.466583],[43.85751,87.467148],[43.85651,87.467682],[43.855469,87.468079],[43.854439,87.468384],[43.853588,87.46859],[43.853081,87.468727],[43.851749,87.469116],[43.8503,87.469673],[43.849232,87.470154],[43.848011,87.470772],[43.847389,87.471123],[43.84705,87.471336],[43.8461,87.47197],[43.844799,87.472923],[43.84341,87.474068],[43.842701,87.474693],[43.84201,87.475243],[43.84111,87.475983],[43.83971,87.476959],[43.83831,87.477814],[43.83717,87.478394],[43.8358,87.478996],[43.83424,87.479584],[43.832649,87.480026],[43.832432,87.480072],[43.830681,87.480377],[43.814949,87.482323],[43.813801,87.482513],[43.81266,87.482819],[43.81208,87.482986],[43.811771,87.483124],[43.810558,87.483627],[43.809471,87.4842],[43.808338,87.48494],[43.807209,87.485786],[43.806221,87.486656],[43.80513,87.487793],[43.804131,87.489014],[43.803341,87.490128],[43.802521,87.491386],[43.801628,87.492851],[43.80098,87.493896],[43.800289,87.494873],[43.79995,87.495247],[43.799122,87.496063],[43.798279,87.496712],[43.797352,87.497269],[43.796452,87.497643],[43.79562,87.497864],[43.79528,87.497917],[43.794739,87.497971],[43.79393,87.497971],[43.793282,87.497902],[43.792622,87.497749],[43.79195,87.497513],[43.79126,87.497223],[43.790421,87.496727],[43.78997,87.496391],[43.789669,87.496162],[43.78923,87.495773],[43.788609,87.495148],[43.786831,87.492996],[43.784351,87.489883],[43.78339,87.4888],[43.78244,87.487953],[43.781559,87.487282],[43.780479,87.486618],[43.779621,87.486221],[43.778622,87.485832],[43.777359,87.485489],[43.768581,87.484177],[43.7672,87.483994],[43.765968,87.483688],[43.76461,87.483208],[43.763302,87.482597],[43.762199,87.481934],[43.760948,87.481003],[43.759979,87.480133],[43.75798,87.478256],[43.75629,87.476753],[43.755219,87.475883],[43.75386,87.475052],[43.752739,87.474487],[43.751438,87.473969],[43.750031,87.473557],[43.749001,87.473343],[43.747791,87.473244],[43.74649,87.47319],[43.745319,87.473297],[43.744019,87.473534],[43.742809,87.473877],[43.741699,87.474297],[43.74049,87.474876],[43.739391,87.47554],[43.738281,87.476303],[43.73737,87.477051],[43.73629,87.478119],[43.735081,87.479286],[43.733238,87.481216],[43.72575,87.488892],[43.72366,87.490959],[43.722832,87.491814],[43.722229,87.492439],[43.721432,87.493263],[43.719742,87.494972],[43.717701,87.497032],[43.715801,87.499092],[43.713329,87.501373],[43.711281,87.503128],[43.708069,87.505676],[43.705551,87.507523],[43.702839,87.509422],[43.70277,87.509468],[43.688221,87.519676],[43.686871,87.520798],[43.685829,87.521828],[43.68462,87.523239],[43.683552,87.524712],[43.682499,87.526443],[43.68145,87.528549],[43.680691,87.530472],[43.68005,87.532501],[43.679531,87.534561],[43.679199,87.536484],[43.678959,87.538696],[43.6786,87.543793],[43.67857,87.544243],[43.67757,87.558968],[43.67749,87.560387],[43.677399,87.561157],[43.67728,87.562157],[43.677139,87.563583],[43.67701,87.564293],[43.67683,87.564903],[43.676601,87.565376],[43.676239,87.56588],[43.675919,87.566231],[43.675499,87.566544],[43.674992,87.56675],[43.674511,87.566833],[43.67387,87.566788],[43.67218,87.566673],[43.67149,87.566566],[43.667702,87.566078],[43.66563,87.565826],[43.664051,87.56575],[43.662689,87.565804],[43.661449,87.565971],[43.660259,87.566231],[43.659241,87.566559],[43.65818,87.566978],[43.657131,87.567467],[43.655708,87.568199],[43.649658,87.571487],[43.639301,87.577278],[43.637989,87.578117],[43.636768,87.579117],[43.635891,87.580017],[43.635071,87.58107],[43.634281,87.582336],[43.633598,87.583778],[43.633041,87.585251],[43.63274,87.586411],[43.632462,87.587967],[43.63224,87.589622],[43.632118,87.591454],[43.631851,87.597633],[43.63166,87.602814],[43.631641,87.603279],[43.631451,87.607712],[43.631241,87.612137],[43.631008,87.615463],[43.630951,87.616127],[43.630699,87.618637],[43.630329,87.621849],[43.62991,87.62468],[43.629162,87.629738],[43.627029,87.64415],[43.626369,87.648972],[43.626221,87.650948],[43.626209,87.652649],[43.626259,87.654282],[43.626381,87.655884],[43.626579,87.657341],[43.626831,87.658737],[43.627178,87.6605],[43.628189,87.664627],[43.62838,87.665329],[43.629429,87.669518],[43.629879,87.671638],[43.630192,87.673363],[43.63036,87.674721],[43.630501,87.676178],[43.630569,87.677811],[43.63055,87.679382],[43.630421,87.681129],[43.63026,87.682762],[43.630001,87.684677],[43.62574,87.709663],[43.62455,87.716537],[43.624481,87.717003],[43.624031,87.719711],[43.623959,87.720032],[43.62365,87.721848],[43.62323,87.724319],[43.619122,87.748306],[43.618641,87.750763],[43.618141,87.753036],[43.617962,87.754066],[43.60783,87.790024],[43.606331,87.79483],[43.604469,87.798782],[43.598629,87.809593],[43.5658,87.868134],[43.56356,87.873283],[43.562561,87.877747],[43.553478,87.936623],[43.550369,87.947952],[43.548012,87.953453],[43.545639,87.958076],[43.54229,87.962029],[43.51017,87.990517],[43.5047,87.995667],[43.501419,87.997803],[43.498638,87.998932],[43.49448,88],[43.492001,88.000366],[43.490589,88.001099],[43.48933,88.002701],[43.487259,88.007523],[43.485432,88.01181],[43.473808,88.040779],[43.471821,88.044037],[43.451771,88.064278],[43.42305,88.092621],[43.421719,88.094742],[43.418388,88.102074],[43.41431,88.110977],[43.40517,88.127991],[43.40303,88.132248],[43.401909,88.137573],[43.401039,88.144524],[43.401039,88.14724],[43.401409,88.150192],[43.40102,88.15242],[43.398079,88.160744],[43.39703,88.162621],[43.395271,88.164429],[43.388039,88.171944],[43.386688,88.174652],[43.37188,88.212837],[43.369881,88.215889],[43.367619,88.218224],[43.363781,88.220337],[43.352619,88.226151],[43.350868,88.227867],[43.350121,88.229424],[43.348751,88.233704],[43.346882,88.247093],[43.347191,88.253166],[43.347919,88.274597],[43.347969,88.280197],[43.3475,88.284607],[43.343578,88.307373],[43.343201,88.309288],[43.342369,88.311203],[43.34161,88.312332],[43.340641,88.313347],[43.336269,88.316933],[43.335411,88.31813],[43.333851,88.322166],[43.332958,88.323196],[43.331371,88.325027],[43.329269,88.329193],[43.328281,88.330704],[43.32671,88.331947],[43.324421,88.333443],[43.31831,88.337143],[43.317211,88.338058],[43.316551,88.338982],[43.316002,88.339928],[43.312481,88.348618],[43.311829,88.349541],[43.308739,88.353241],[43.307331,88.3545],[43.305771,88.355309],[43.304501,88.35553],[43.303329,88.355553],[43.302132,88.355293],[43.301041,88.354797],[43.299999,88.354073],[43.299019,88.352921],[43.29567,88.347366],[43.294922,88.34639],[43.29427,88.345863],[43.293468,88.345444],[43.292549,88.345306],[43.286049,88.345741],[43.28421,88.346138],[43.279449,88.348213],[43.278389,88.348846],[43.277592,88.349823],[43.275612,88.354141],[43.275002,88.354927],[43.27446,88.355331],[43.273899,88.355469],[43.273232,88.355362],[43.272732,88.355019],[43.27166,88.353889],[43.270939,88.353447],[43.27021,88.353317],[43.26955,88.35347],[43.268181,88.354393],[43.264778,88.35762],[43.263809,88.358849],[43.263401,88.360359],[43.26244,88.370163],[43.261951,88.37146],[43.261261,88.372208],[43.26041,88.372498],[43.25938,88.372566],[43.256512,88.372383],[43.255489,88.372543],[43.25478,88.372917],[43.24931,88.377213],[43.246029,88.379967],[43.244301,88.382111],[43.23455,88.400726],[43.232761,88.408127],[43.232342,88.411072],[43.232262,88.423782],[43.231758,88.42601],[43.227589,88.431534],[43.22604,88.433823],[43.224918,88.436653],[43.222912,88.445251],[43.222118,88.44709],[43.220909,88.448799],[43.217781,88.45314],[43.21653,88.454224],[43.214489,88.455139],[43.21336,88.455887],[43.211441,88.458023],[43.2104,88.458809],[43.206848,88.46019],[43.20443,88.461479],[43.199009,88.465073],[43.196541,88.467239],[43.19408,88.470032],[43.192829,88.471207],[43.191368,88.472076],[43.189159,88.473167],[43.188202,88.473831],[43.186279,88.47554],[43.185108,88.476303],[43.183319,88.476707],[43.180149,88.477287],[43.17802,88.477966],[43.174019,88.479759],[43.172951,88.480476],[43.172161,88.481453],[43.169781,88.484947],[43.168968,88.485672],[43.168079,88.486183],[43.167301,88.486397],[43.16626,88.48629],[43.162991,88.485527],[43.161709,88.485367],[43.16024,88.485497],[43.158871,88.485817],[43.157822,88.486397],[43.15678,88.487129],[43.15575,88.488297],[43.15485,88.489777],[43.15295,88.493713],[43.151932,88.495148],[43.150249,88.497177],[43.147289,88.499817],[43.145618,88.500908],[43.11911,88.508789],[43.113972,88.510857],[43.10878,88.514526],[43.104771,88.516747],[43.095871,88.520363],[43.08585,88.524307],[43.085049,88.52462],[43.084221,88.527397],[43.083469,88.533073],[43.064529,88.645844],[43.063782,88.650993],[43.06353,88.655983],[43.064659,88.704552],[43.062901,88.758797],[43.062149,88.766693],[43.061272,88.770302],[43.060139,88.773048],[43.054749,88.780937],[43.034679,88.809776],[43.031158,88.816467],[43.022129,88.835701],[43.020741,88.840851],[43.01685,88.861969],[43.01511,88.895157],[43.014431,88.903923],[43.01189,88.944511],[43.010181,88.985939],[43.008678,89.023689],[43.00766,89.051407],[43.006378,89.084343],[43.00621,89.086533],[43.00592,89.088699],[43.005348,89.091614],[43.004471,89.094673],[42.995232,89.121597],[42.994888,89.122597],[42.993141,89.127441],[42.986832,89.144073],[42.986031,89.1464],[42.983082,89.154968],[42.980911,89.161613],[42.97858,89.169212],[42.975029,89.179268],[42.974419,89.18145],[42.974018,89.182877],[42.970001,89.211029],[42.96912,89.214462],[42.968922,89.214996],[42.967739,89.218063],[42.957939,89.240379],[42.949902,89.258751],[42.931519,89.301567],[42.922131,89.323463],[42.92075,89.327423],[42.919739,89.332222],[42.919361,89.336693],[42.920872,89.430923],[42.92112,89.450844],[42.920872,89.456848],[42.91634,89.50766],[42.91534,89.513321],[42.912819,89.523277],[42.912071,89.528427],[42.91132,89.550583],[42.91169,89.55246],[42.912701,89.55452],[42.916729,89.560028],[42.917099,89.560532],[42.91848,89.563278],[42.919609,89.566368],[42.921749,89.569633],[42.924389,89.571167],[42.926029,89.572372],[42.929161,89.573227],[42.93055,89.574257],[42.931801,89.575813],[42.93243,89.578209],[42.93243,89.584053],[42.93306,89.586617],[42.935951,89.593658],[42.93721,89.597092],[42.937969,89.6007],[42.938339,89.604637],[42.938091,89.609283],[42.936081,89.6213],[42.934952,89.625237],[42.933819,89.628853],[42.933441,89.632111],[42.933441,89.634857],[42.933941,89.645332],[42.933689,89.64962],[42.931801,89.66198],[42.92263,89.702316],[42.921879,89.705238],[42.921879,89.708328],[42.922249,89.711418],[42.924259,89.721718],[42.9245,89.722847],[42.925522,89.727898],[42.926029,89.730988],[42.926029,89.734077],[42.92577,89.736481],[42.901379,89.832443],[42.900501,89.836906],[42.900249,89.841187],[42.900249,89.845154],[42.902519,89.868317],[42.903271,89.875359],[42.903271,89.879303],[42.902889,89.882736],[42.90189,89.887199],[42.89333,89.916039],[42.882519,89.957413],[42.879749,89.968567],[42.87484,89.992432],[42.875099,90.001534],[42.876228,90.003593],[42.877361,90.007881],[42.87812,90.013542],[42.87849,90.033287],[42.87925,90.038597],[42.880501,90.043587],[42.883518,90.048897],[42.8839,90.050797],[42.883518,90.052513],[42.882019,90.064011],[42.882389,90.07534],[42.885159,90.088043],[42.887299,90.107613],[42.887299,90.111557],[42.885658,90.118088],[42.884529,90.125473],[42.884529,90.155167],[42.884781,90.160141],[42.88755,90.178169],[42.89032,90.194313],[42.891571,90.202888],[42.892578,90.218163],[42.89283,90.225548],[42.894341,90.255417],[42.89547,90.257637],[42.897228,90.260223],[42.91433,90.276871],[42.916088,90.278587],[42.92572,90.286217],[42.926281,90.286659],[42.928669,90.289574],[42.954681,90.325447],[42.965561,90.339417],[42.969109,90.352364],[42.96933,90.354347],[42.97477,90.391518],[42.975849,90.398308],[42.976601,90.404121],[42.976608,90.404427],[42.979778,90.425003],[42.980309,90.428658],[42.981098,90.434731],[42.983521,90.450653],[42.98632,90.469856],[42.986919,90.474617],[42.987289,90.476891],[42.98819,90.483231],[42.98856,90.485153],[42.98893,90.486382],[42.989491,90.487823],[42.998089,90.50766],[42.998421,90.508636],[42.998821,90.510246],[42.999931,90.518677],[43.000271,90.520767],[43.000511,90.522957],[43.001389,90.528778],[43.00177,90.531792],[43.001911,90.532593],[43.002289,90.5355],[43.003151,90.540283],[43.00349,90.541817],[43.00515,90.55069],[43.005402,90.551743],[43.005741,90.553596],[43.00655,90.559807],[43.006821,90.561119],[43.010551,90.585213],[43.010761,90.586189],[43.01086,90.586868],[43.011879,90.59243],[43.012051,90.593674],[43.014481,90.607651],[43.015041,90.611397],[43.01532,90.612556],[43.016499,90.6185],[43.016621,90.618858],[43.01749,90.624069],[43.017841,90.625748],[43.01783,90.625999],[43.01865,90.62989],[43.019321,90.633347],[43.019691,90.634842],[43.019711,90.635452],[43.020451,90.639526],[43.023109,90.652611],[43.0243,90.659431],[43.025982,90.66787],[43.026249,90.669579],[43.027802,90.678146],[43.028332,90.680779],[43.028751,90.683296],[43.028961,90.684067],[43.029202,90.685738],[43.02927,90.686523],[43.030109,90.691254],[43.030991,90.695862],[43.031811,90.700508],[43.03191,90.701439],[43.033859,90.712013],[43.034119,90.713043],[43.034389,90.713882],[43.034821,90.714951],[43.035488,90.716331],[43.037731,90.720207],[43.038509,90.721474],[43.03936,90.722672],[43.039669,90.723244],[43.039711,90.723442],[43.041012,90.7258],[43.049889,90.741318],[43.078011,90.789993],[43.079781,90.793114],[43.091789,90.813927],[43.094238,90.818253],[43.105728,90.83815],[43.127251,90.875664],[43.128132,90.877113],[43.129059,90.878807],[43.152161,90.918983],[43.15641,90.926468],[43.15712,90.927567],[43.15815,90.928741],[43.160381,90.930939],[43.16106,90.931686],[43.161839,90.932793],[43.162491,90.934036],[43.162708,90.934593],[43.163059,90.935707],[43.167259,90.954353],[43.174629,90.9879],[43.177311,90.999687],[43.186829,91.042557],[43.18734,91.045181],[43.193069,91.070633],[43.197281,91.089661],[43.198051,91.092934],[43.200958,91.105988],[43.201221,91.106888],[43.201569,91.107857],[43.2425,91.200439],[43.247059,91.210648],[43.26371,91.248741],[43.269489,91.261757],[43.271019,91.265343],[43.275181,91.274818],[43.277649,91.280586],[43.28059,91.287086],[43.282509,91.291519],[43.285599,91.298424],[43.296082,91.322212],[43.296822,91.323753],[43.297359,91.324638],[43.303131,91.333267],[43.309929,91.343613],[43.311359,91.345619],[43.315521,91.3517],[43.31625,91.352943],[43.31702,91.354584],[43.32486,91.374878],[43.32983,91.387619],[43.33807,91.410332],[43.343979,91.426453],[43.347961,91.437576],[43.348209,91.438461],[43.348942,91.440407],[43.3494,91.441437],[43.352039,91.44873],[43.352589,91.451378],[43.3535,91.460182],[43.354031,91.465851],[43.354301,91.468117],[43.355129,91.476349],[43.355499,91.478973],[43.361481,91.501579],[43.363602,91.509407],[43.364449,91.512863],[43.37183,91.539879],[43.3741,91.548363],[43.374298,91.548882],[43.374851,91.549858],[43.375061,91.550453],[43.375771,91.553467],[43.37603,91.555138],[43.375938,91.555389],[43.37709,91.559853],[43.377621,91.562492],[43.380009,91.581299],[43.381809,91.596481],[43.382011,91.597931],[43.382099,91.598396],[43.382301,91.598907],[43.382561,91.601357],[43.382629,91.602577],[43.382641,91.604263],[43.382542,91.606644],[43.382259,91.609413],[43.381939,91.611397],[43.37965,91.621933],[43.378841,91.625473],[43.3764,91.634987],[43.37545,91.637947],[43.37505,91.639877],[43.374619,91.641647],[43.370998,91.655388],[43.37027,91.658417],[43.365871,91.675323],[43.365059,91.678452],[43.364731,91.67955],[43.363499,91.684471],[43.361439,91.692139],[43.359531,91.699547],[43.359241,91.701263],[43.359169,91.702637],[43.35928,91.703987],[43.359509,91.705276],[43.359982,91.707161],[43.36982,91.742973],[43.372631,91.753021],[43.37392,91.757812],[43.37442,91.759483],[43.375198,91.762428],[43.375401,91.763397],[43.375561,91.764717],[43.375599,91.765999],[43.375408,91.768929],[43.37521,91.770554],[43.374908,91.772171],[43.37463,91.773232],[43.374088,91.774811],[43.373291,91.776604],[43.364761,91.792717],[43.364399,91.793503],[43.363998,91.794601],[43.36359,91.796387],[43.36343,91.797989],[43.363441,91.799316],[43.363579,91.800652],[43.364021,91.802567],[43.366032,91.808868],[43.37429,91.834282],[43.375271,91.837433],[43.381149,91.855637],[43.382408,91.8592],[43.38306,91.861214],[43.393181,91.890991],[43.394131,91.893608],[43.404839,91.925247],[43.407921,91.934532],[43.408772,91.936867],[43.410931,91.943413],[43.411652,91.945847],[43.41333,91.951942],[43.41539,91.959442],[43.4156,91.960617],[43.415649,91.961197],[43.415649,91.961807],[43.415539,91.963013],[43.415421,91.963593],[43.41518,91.964447],[43.413719,91.968903],[43.408131,91.984978],[43.38829,92.04274],[43.38768,92.044403],[43.384071,92.055069],[43.383888,92.055931],[43.383739,92.062576],[43.383549,92.063652],[43.383751,92.077217],[43.383621,92.07988],[43.379551,92.111923],[43.3783,92.121323],[43.37817,92.12278],[43.378181,92.123451],[43.378139,92.123787],[43.37804,92.124077],[43.378078,92.124092],[43.377602,92.12693],[43.376678,92.134521],[43.37648,92.134933],[43.37635,92.13591],[43.376438,92.136101],[43.37492,92.146538],[43.3741,92.150238],[43.373829,92.150787],[43.373161,92.151619],[43.371979,92.152588],[43.371311,92.152802],[43.368759,92.1539],[43.343491,92.165489],[43.336319,92.16864],[43.33614,92.16864],[43.333519,92.169991],[43.322121,92.175133],[43.315922,92.177841],[43.315189,92.178223],[43.31448,92.17868],[43.31414,92.178963],[43.313519,92.179672],[43.31295,92.180489],[43.311031,92.183868],[43.309029,92.187683],[43.308578,92.188721],[43.308182,92.190086],[43.30558,92.201569],[43.305191,92.203537],[43.305031,92.204117],[43.304661,92.205032],[43.304211,92.205818],[43.303791,92.206337],[43.300419,92.209373],[43.29726,92.213799],[43.29509,92.219322],[43.293221,92.224327],[43.29282,92.225693],[43.29261,92.226868],[43.29121,92.236771],[43.290798,92.238876],[43.290199,92.241379],[43.290039,92.241692],[43.289768,92.243027],[43.289742,92.243393],[43.289631,92.243736],[43.289581,92.245827],[43.2896,92.249359],[43.28965,92.249733],[43.28944,92.251373],[43.28904,92.253258],[43.288872,92.253853],[43.288399,92.254959],[43.28759,92.2565],[43.286591,92.257843],[43.28548,92.259117],[43.266258,92.280243],[43.26268,92.284241],[43.258411,92.288857],[43.257809,92.289658],[43.25742,92.290321],[43.256969,92.29129],[43.256691,92.292053],[43.256378,92.293137],[43.2561,92.294647],[43.25592,92.296593],[43.255692,92.301987],[43.255619,92.306412],[43.255081,92.324226],[43.254978,92.326187],[43.254929,92.3265],[43.25465,92.327293],[43.25452,92.328056],[43.254539,92.331291],[43.254822,92.3321],[43.25502,92.332977],[43.25502,92.33429],[43.255081,92.334824],[43.255112,92.336983],[43.25491,92.351593],[43.25494,92.351967],[43.255192,92.352547],[43.255161,92.358383],[43.255341,92.369583],[43.255348,92.373428],[43.25544,92.37973],[43.255489,92.381088],[43.25544,92.38237],[43.255562,92.386459],[43.255569,92.38871],[43.255501,92.3909],[43.255562,92.41449],[43.255508,92.41684],[43.25544,92.417953],[43.255112,92.442863],[43.255032,92.44442],[43.254902,92.451012],[43.254879,92.455528],[43.254799,92.458504],[43.254829,92.460274],[43.254902,92.460899],[43.255131,92.46122],[43.255089,92.468697],[43.25489,92.477119],[43.254978,92.48597],[43.25494,92.488167],[43.25486,92.489609],[43.254711,92.507919],[43.25457,92.517036],[43.254532,92.517326],[43.254589,92.518883],[43.25581,92.530167],[43.25584,92.53196],[43.25576,92.533012],[43.255421,92.53582],[43.253208,92.549698],[43.252701,92.552528],[43.252499,92.553307],[43.251751,92.555443],[43.250801,92.557281],[43.250229,92.55851],[43.243992,92.570717],[43.242409,92.573624],[43.242149,92.574242],[43.236401,92.585487],[43.230221,92.597183],[43.22961,92.598503],[43.228851,92.599838],[43.2285,92.600647],[43.227299,92.602959],[43.22636,92.604622],[43.225151,92.607018],[43.222401,92.612137],[43.221802,92.61338],[43.219791,92.61718],[43.218559,92.61972],[43.2174,92.62175],[43.216888,92.622757],[43.2164,92.624069],[43.214039,92.628708],[43.213139,92.630333],[43.2122,92.632301],[43.212051,92.632523],[43.211658,92.63279],[43.210991,92.632889],[43.21035,92.633072],[43.210129,92.633209],[43.20993,92.633461],[43.207069,92.639236],[43.206989,92.639481],[43.205688,92.641998],[43.20525,92.64299],[43.204369,92.644783],[43.20388,92.645653],[43.19825,92.65416],[43.197201,92.655479],[43.196789,92.656464],[43.196609,92.657181],[43.19635,92.6577],[43.196079,92.65802],[43.190941,92.662827],[43.190338,92.663452],[43.188599,92.665031],[43.186859,92.666748],[43.185692,92.668007],[43.184761,92.669159],[43.183418,92.670967],[43.180092,92.676376],[43.172909,92.687592],[43.17234,92.688583],[43.169239,92.693604],[43.168331,92.695328],[43.167881,92.696358],[43.167221,92.698227],[43.166851,92.6996],[43.165169,92.706772],[43.16357,92.714363],[43.163559,92.714729],[43.161999,92.72184],[43.16135,92.722961],[43.15799,92.729736],[43.156681,92.732277],[43.155411,92.734993],[43.154388,92.737671],[43.153999,92.739197],[43.15382,92.740334],[43.153301,92.742409],[43.152962,92.744377],[43.15284,92.745354],[43.152012,92.750618],[43.151588,92.752319],[43.15163,92.752579],[43.151291,92.753853],[43.150669,92.755867],[43.150249,92.757011],[43.14949,92.75869],[43.14801,92.761574],[43.14732,92.762558],[43.145931,92.7649],[43.144001,92.767769],[43.1413,92.771973],[43.139622,92.77475],[43.138191,92.777542],[43.13784,92.778351],[43.136761,92.78141],[43.133678,92.791237],[43.133209,92.792923],[43.132771,92.79425],[43.132648,92.794487],[43.13208,92.796402],[43.130611,92.801697],[43.130001,92.804459],[43.129471,92.807159],[43.12764,92.815422],[43.12764,92.815628],[43.127708,92.816093],[43.128059,92.817108],[43.12809,92.817642],[43.127239,92.822151],[43.124889,92.833717],[43.12468,92.834572],[43.124001,92.836807],[43.123409,92.83847],[43.121769,92.843559],[43.117249,92.856644],[43.116928,92.857742],[43.097961,92.913582],[43.09219,92.930397],[43.091251,92.932861],[43.089909,92.936729],[43.08939,92.938499],[43.088219,92.941933],[43.085678,92.949699],[43.08448,92.953049],[43.084339,92.95372],[43.083939,92.954758],[43.081841,92.961029],[43.081139,92.962883],[43.077202,92.974609],[43.073639,92.984818],[43.07309,92.986237],[43.072651,92.98764],[43.071579,92.990761],[43.070629,92.993958],[43.06773,93.002113],[43.06179,93.019722],[43.059059,93.027451],[43.05798,93.03083],[43.05611,93.036209],[43.055599,93.037857],[43.054531,93.040833],[43.0536,93.043671],[43.050701,93.051971],[43.048828,93.05748],[43.04847,93.058357],[43.04398,93.071747],[43.04361,93.072983],[43.036949,93.0923],[43.030769,93.110497],[43.030392,93.111504],[43.02821,93.117996],[43.02644,93.122902],[43.02552,93.125717],[43.021511,93.137383],[43.020081,93.141777],[43.019531,93.143211],[43.018318,93.146812],[43.014252,93.158577],[43.012951,93.162216],[43.012581,93.163368],[43.012489,93.163933],[43.011021,93.167953],[43.01017,93.170631],[43.009911,93.171303],[42.956379,93.327377],[42.943939,93.363609],[42.93602,93.384903],[42.923698,93.417068],[42.914711,93.439667],[42.90744,93.457962],[42.906872,93.459129],[42.90659,93.460068],[42.90519,93.464157],[42.90258,93.470917],[42.902351,93.471611],[42.90118,93.474586],[42.89896,93.47998],[42.897121,93.484833],[42.895458,93.488991],[42.89336,93.494431],[42.892899,93.495789],[42.892529,93.496559],[42.88739,93.512894],[42.887272,93.517189],[42.888271,93.531914],[42.862091,93.564423],[42.861511,93.564209],[42.861229,93.564102],[42.86145,93.564613],[42.861591,93.565399],[42.861431,93.566383],[42.86108,93.567436],[42.860889,93.568802],[42.860519,93.574074],[42.860298,93.582787],[42.859718,93.588753],[42.859089,93.594093],[42.858608,93.596024],[42.858109,93.597328],[42.85775,93.598083],[42.844662,93.621597],[42.833488,93.641823],[42.828079,93.651497],[42.825699,93.655746],[42.824928,93.657333],[42.82415,93.659142],[42.823341,93.661308],[42.82259,93.663757],[42.821941,93.666389],[42.821411,93.669212],[42.82106,93.672157],[42.820869,93.675217],[42.820148,93.715927],[42.819351,93.749474],[42.819149,93.751984],[42.81884,93.754433],[42.81839,93.756721],[42.817348,93.760773],[42.816341,93.763344],[42.815842,93.763969],[42.81535,93.764908],[42.814701,93.766747],[42.812519,93.771149],[42.812069,93.772324],[42.811932,93.773102],[42.727871,93.941811],[42.721931,93.953537],[42.720589,93.955933],[42.719109,93.958252],[42.717548,93.960472],[42.699131,93.982513],[42.699059,93.983383],[42.698891,93.983681],[42.698071,93.984612],[42.696949,93.986053],[42.695301,93.987839],[42.69413,93.989487],[42.69381,93.99012],[42.69331,93.990646],[42.692101,93.991898],[42.69136,93.992996],[42.69014,93.994179],[42.687519,93.99733],[42.687038,93.997597],[42.686771,93.99736],[42.686432,93.997581],[42.65414,94.036118],[42.646832,94.044739],[42.645691,94.045403],[42.644489,94.046288],[42.644058,94.046982],[42.643921,94.047897],[42.64352,94.048683],[42.615822,94.081642],[42.615479,94.082474],[42.61515,94.083054],[42.61348,94.085068],[42.613319,94.085991],[42.612419,94.087349],[42.611771,94.087723],[42.610729,94.087997],[42.610352,94.088097],[42.5938,94.107742],[42.591869,94.110123],[42.591282,94.110817],[42.576759,94.127983],[42.57444,94.130577],[42.574371,94.130829],[42.55592,94.152588],[42.5546,94.153893],[42.552959,94.1549],[42.55114,94.155441],[42.549179,94.155487],[42.511021,94.154877],[42.50568,94.154716],[42.48864,94.154488],[42.479259,94.154243],[42.455231,94.153893],[42.45348,94.15358],[42.452808,94.153816],[42.416431,94.153236],[42.404751,94.152946],[42.390621,94.152786],[42.387569,94.152687],[42.38446,94.152702],[42.37709,94.15255],[42.375671,94.152588],[42.374401,94.152344],[42.37154,94.150558],[42.36993,94.14994],[42.368191,94.150368],[42.36639,94.151428],[42.364391,94.152222],[42.36224,94.152328],[42.34985,94.15213],[42.347618,94.152443],[42.345421,94.153099],[42.343281,94.154137],[42.341251,94.155533],[42.33934,94.15728],[42.33762,94.159363],[42.323891,94.17894],[42.299648,94.213142],[42.29924,94.213348],[42.29882,94.213783],[42.292431,94.222908],[42.292061,94.223824],[42.291611,94.224564],[42.26054,94.268501],[42.259979,94.269096],[42.258591,94.268639],[42.25832,94.269371],[42.258259,94.271477],[42.25798,94.272148],[42.221859,94.32328],[42.21785,94.328712],[42.201809,94.351463],[42.186401,94.3731],[42.18565,94.374268],[42.182468,94.378754],[42.17992,94.382103],[42.07518,94.501556],[42.07399,94.503014],[42.071751,94.506172],[42.070728,94.507843],[42.069248,94.510452],[42.05822,94.531387],[42.05555,94.536324],[42.034328,94.57663],[42.028992,94.586594],[42.01165,94.619476],[42.006409,94.629227],[42.002441,94.636864],[41.996479,94.647957],[41.97168,94.694656],[41.970669,94.696457],[41.96846,94.699707],[41.964611,94.704811],[41.961651,94.708549],[41.953011,94.719757],[41.951698,94.721367],[41.93182,94.747139],[41.928169,94.751717],[41.92601,94.754211],[41.917702,94.764259],[41.907219,94.776627],[41.906189,94.778198],[41.905659,94.779518],[41.90535,94.780724],[41.905182,94.781952],[41.905979,94.819061],[41.905891,94.82193],[41.904789,94.824211],[41.896778,94.833511],[41.889599,94.842018],[41.88821,94.843773],[41.886959,94.845734],[41.885899,94.847763],[41.872711,94.87912],[41.87204,94.881699],[41.871601,94.88427],[41.87085,94.886482],[41.86935,94.887657],[41.86618,94.889374],[41.864529,94.890427],[41.854229,94.897636],[41.853321,94.898354],[41.850658,94.900124],[41.845459,94.90377],[41.843231,94.905518],[41.84193,94.906731],[41.834141,94.91481],[41.83263,94.916656],[41.831348,94.918793],[41.830341,94.921066],[41.822659,94.947006],[41.822681,94.946938],[41.821529,94.950897],[41.811859,94.981277],[41.811451,94.982964],[41.811062,94.987167],[41.80801,95.009956],[41.807579,95.012787],[41.803242,95.035828],[41.80278,95.037987],[41.801811,95.039459],[41.800449,95.040283],[41.79937,95.041672],[41.798981,95.043709],[41.798931,95.046043],[41.79929,95.048683],[41.801491,95.056557],[41.807201,95.081543],[41.807819,95.084007],[41.808601,95.086418],[41.81176,95.094139],[41.812141,95.095657],[41.813389,95.102814],[41.81377,95.104523],[41.813801,95.106232],[41.81308,95.107803],[41.805882,95.116547],[41.79686,95.127617],[41.795639,95.128998],[41.795818,95.128799],[41.795311,95.129143],[41.795021,95.12973],[41.794418,95.130508],[41.793739,95.131241],[41.792912,95.131813],[41.791931,95.132187],[41.787621,95.133377],[41.785759,95.134048],[41.783821,95.13443],[41.77948,95.133087],[41.777401,95.133003],[41.769032,95.136383],[41.767269,95.13694],[41.761452,95.13842],[41.759869,95.138908],[41.758209,95.139793],[41.725281,95.170288],[41.716209,95.178574],[41.713089,95.181328],[41.7062,95.186333],[41.70443,95.187531],[41.702549,95.188553],[41.69426,95.191917],[41.69257,95.192741],[41.69117,95.193787],[41.690331,95.194557],[41.685749,95.199341],[41.67609,95.209084],[41.674431,95.210327],[41.67263,95.21125],[41.670658,95.211891],[41.66626,95.213074],[41.664299,95.214027],[41.662991,95.215828],[41.660839,95.219803],[41.65979,95.221008],[41.65844,95.221863],[41.648361,95.225349],[41.646259,95.226189],[41.644218,95.227188],[41.608528,95.247704],[41.60677,95.248993],[41.605129,95.250458],[41.603642,95.25209],[41.55867,95.303436],[41.557178,95.304878],[41.55547,95.306084],[41.5536,95.306976],[41.537659,95.313148],[41.521111,95.319687],[41.503269,95.326576],[41.499722,95.327744],[41.486279,95.331001],[41.483829,95.33149],[41.48151,95.331749],[41.418961,95.336037],[41.41769,95.336189],[41.34993,95.340813],[41.348049,95.341026],[41.346149,95.341423],[41.309109,95.351532],[41.299801,95.353996],[41.295872,95.355118],[41.286308,95.357643],[41.27911,95.359596],[41.267288,95.36293],[41.239849,95.370354],[41.235882,95.371529],[41.23431,95.371887],[41.230549,95.372963],[41.227638,95.37355],[41.210209,95.375168],[41.1908,95.376801],[41.1786,95.377998],[41.171768,95.378571],[41.170151,95.37912],[41.145889,95.396797],[41.144199,95.398277],[41.142658,95.39991],[41.14127,95.401672],[41.125759,95.42276],[41.12434,95.424553],[41.122841,95.426117],[41.121288,95.427467],[41.112598,95.434418],[41.11095,95.435333],[41.107349,95.436142],[41.10556,95.436951],[41.09116,95.448433],[41.089539,95.449463],[41.084831,95.452087],[41.083542,95.45327],[41.082561,95.454788],[41.078522,95.461853],[41.077301,95.463303],[41.075081,95.464668],[41.07473,95.464867],[41.073681,95.465584],[41.072338,95.466461],[41.06773,95.469482],[41.06414,95.472038],[41.061741,95.472977],[41.059601,95.473038],[41.05727,95.472641],[41.04948,95.469711],[41.047211,95.468109],[41.045151,95.467041],[41.043018,95.467041],[41.04055,95.467773],[41.037159,95.469513],[41.035561,95.469711],[41.033291,95.469711],[41.030491,95.469437],[41.028629,95.469437],[41.024899,95.470383],[41.021969,95.470909],[41.020901,95.470711],[41.019501,95.469383],[41.01804,95.468109],[41.015301,95.466637],[41.013241,95.466309],[41.008911,95.465981],[41.00671,95.466309],[41.004841,95.467308],[41.003052,95.468842],[41.000679,95.471848],[40.997429,95.475533],[40.993698,95.478722],[40.941299,95.523643],[40.882931,95.57193],[40.860771,95.59272],[40.852169,95.60096],[40.85096,95.601868],[40.849178,95.602623],[40.84457,95.604057],[40.84127,95.604858],[40.835602,95.606003],[40.832191,95.606857],[40.827271,95.608528],[40.824211,95.60997],[40.818081,95.613297],[40.815659,95.614197],[40.794498,95.620667],[40.79213,95.62159],[40.790161,95.622757],[40.739639,95.653053],[40.683159,95.68631],[40.560768,95.758293],[40.559139,95.75927],[40.557941,95.760551],[40.55727,95.761803],[40.556862,95.763359],[40.55566,95.769852],[40.55521,95.773392],[40.550732,95.791092],[40.5439,95.818512],[40.54306,95.821533],[40.543018,95.821587],[40.540649,95.831047],[40.53907,95.837341],[40.530319,95.872833],[40.529411,95.877419],[40.528881,95.881477],[40.528851,95.881737],[40.528599,95.886452],[40.528671,95.890549],[40.528831,95.892937],[40.529091,95.895401],[40.531139,95.913231],[40.531509,95.916992],[40.532009,95.922897],[40.532108,95.924156],[40.532829,95.935677],[40.533211,95.940323],[40.533291,95.941277],[40.533428,95.942421],[40.533798,95.945557],[40.534019,95.947113],[40.535252,95.954674],[40.53624,95.964233],[40.537189,95.976349],[40.539242,95.992767],[40.539989,96.005859],[40.54044,96.010193],[40.541,96.01384],[40.542919,96.026047],[40.543171,96.028214],[40.54752,96.070686],[40.54813,96.076599],[40.548721,96.084511],[40.549389,96.096077],[40.550598,96.11734],[40.55098,96.121567],[40.551849,96.128128],[40.556881,96.156647],[40.557098,96.158058],[40.557629,96.161926],[40.557949,96.165993],[40.55872,96.179993],[40.560951,96.199028],[40.563648,96.226624],[40.568291,96.274063],[40.56879,96.278961],[40.569698,96.285233],[40.57069,96.290207],[40.571339,96.292847],[40.57394,96.302109],[40.57439,96.30407],[40.574661,96.305313],[40.575359,96.308998],[40.57552,96.309914],[40.575581,96.310371],[40.575699,96.31115],[40.575871,96.312462],[40.576149,96.314682],[40.576519,96.319397],[40.576649,96.32518],[40.576401,96.338333],[40.57526,96.417137],[40.575562,96.426323],[40.576611,96.438957],[40.57682,96.443626],[40.576698,96.448219],[40.576618,96.451401],[40.576591,96.453537],[40.575729,96.465378],[40.575241,96.483818],[40.574841,96.488899],[40.573952,96.494553],[40.570702,96.510117],[40.569939,96.516006],[40.569469,96.522537],[40.569019,96.527107],[40.568401,96.531517],[40.567451,96.536507],[40.566219,96.54361],[40.565731,96.550591],[40.565731,96.553001],[40.566029,96.558853],[40.566509,96.568413],[40.566341,96.575249],[40.565929,96.582329],[40.565948,96.586288],[40.5662,96.590271],[40.566681,96.594307],[40.56736,96.599838],[40.567348,96.608368],[40.56723,96.61602],[40.567322,96.618179],[40.56736,96.618927],[40.56749,96.620659],[40.56765,96.622299],[40.5686,96.630157],[40.568958,96.634697],[40.571991,96.703812],[40.572929,96.710403],[40.575539,96.721573],[40.576149,96.725319],[40.576641,96.731293],[40.576611,96.736549],[40.576099,96.742088],[40.574718,96.750931],[40.574219,96.758362],[40.57423,96.758377],[40.574219,96.758362],[40.574409,96.762466],[40.575451,96.787216],[40.575531,96.792084],[40.5755,96.794434],[40.57523,96.799507],[40.574692,96.804893],[40.574379,96.807129],[40.570881,96.826408],[40.56163,96.876579],[40.559639,96.891777],[40.558578,96.896599],[40.558071,96.89843],[40.556839,96.9021],[40.555069,96.906273],[40.55328,96.909668],[40.540058,96.932861],[40.537289,96.936836],[40.536251,96.938164],[40.53344,96.941261],[40.530682,96.943817],[40.528179,96.94577],[40.5242,96.948303],[40.504028,96.959183],[40.497231,96.96241],[40.477169,96.971222],[40.476452,96.97155],[40.47179,96.973953],[40.467999,96.976357],[40.460899,96.981567],[40.451939,96.988083],[40.448231,96.990463],[40.44437,96.99221],[40.433559,96.996193],[40.428959,96.998672],[40.425781,97.000961],[40.424198,97.002312],[40.406921,97.019852],[40.404881,97.021606],[40.402088,97.023651],[40.40044,97.024658],[40.396702,97.026466],[40.391609,97.028053],[40.38802,97.028587],[40.381908,97.028717],[40.378609,97.02903],[40.375011,97.029701],[40.372089,97.03054],[40.359791,97.034866],[40.35503,97.03727],[40.35025,97.040588],[40.345829,97.044617],[40.341431,97.049957],[40.333191,97.061417],[40.330521,97.06485],[40.327141,97.068367],[40.323559,97.071114],[40.317268,97.075447],[40.31308,97.077667],[40.30891,97.079277],[40.305,97.080132],[40.30098,97.080467],[40.2971,97.080467],[40.293091,97.080917],[40.288311,97.082108],[40.26688,97.089203],[40.261761,97.091362],[40.257099,97.094933],[40.254799,97.097038],[40.237301,97.113998],[40.235271,97.116211],[40.232948,97.119034],[40.22443,97.130653],[40.220871,97.135269],[40.219921,97.136414],[40.217701,97.138802],[40.205471,97.150963],[40.202042,97.154533],[40.200539,97.156303],[40.198158,97.159508],[40.19643,97.162216],[40.194881,97.164932],[40.189041,97.176514],[40.188332,97.177803],[40.186069,97.181587],[40.185371,97.182716],[40.18232,97.18705],[40.175079,97.196701],[40.172459,97.200439],[40.17054,97.203568],[40.164322,97.214851],[40.157082,97.225838],[40.156799,97.226334],[40.155731,97.228149],[40.154251,97.23082],[40.154121,97.231056],[40.153229,97.232811],[40.151112,97.237022],[40.151009,97.237213],[40.150982,97.237267],[40.15041,97.238358],[40.148998,97.240868],[40.148609,97.241547],[40.146091,97.245667],[40.13966,97.255379],[40.138168,97.257477],[40.134159,97.262863],[40.132679,97.264732],[40.132481,97.264969],[40.131519,97.266159],[40.130619,97.26725],[40.125278,97.273499],[40.12468,97.274246],[40.124599,97.274353],[40.12376,97.275459],[40.123138,97.276314],[40.12138,97.278954],[40.11932,97.282463],[40.11787,97.285347],[40.11655,97.2883],[40.11364,97.29567],[40.112259,97.298973],[40.11026,97.303169],[40.108639,97.30616],[40.105339,97.311546],[40.103359,97.314743],[40.102581,97.315987],[40.0993,97.32074],[40.09594,97.324959],[40.0928,97.328407],[40.06662,97.353867],[40.065639,97.354958],[40.064789,97.355988],[40.063549,97.357536],[40.061871,97.359947],[40.06131,97.360832],[40.05941,97.364128],[40.058689,97.36557],[40.057331,97.368607],[40.05637,97.371147],[40.055241,97.374786],[40.05481,97.376282],[40.053959,97.380447],[40.05278,97.388863],[40.05191,97.393333],[40.050781,97.397476],[40.049431,97.401314],[40.047131,97.406311],[40.045422,97.409241],[40.042198,97.414253],[40.040081,97.417473],[40.037971,97.421021],[40.036121,97.424217],[40.034519,97.427292],[40.034119,97.428253],[40.03228,97.431709],[40.032021,97.43222],[40.029869,97.437187],[40.028511,97.441032],[40.025341,97.452019],[40.024109,97.455811],[40.023418,97.457764],[40.022968,97.458961],[40.02103,97.463692],[40.02071,97.464432],[40.013981,97.47892],[40.0061,97.496628],[40.00304,97.503929],[40.000721,97.509857],[39.995461,97.523727],[39.993599,97.52903],[39.990631,97.53772],[39.989929,97.539772],[39.98962,97.540733],[39.98864,97.543823],[39.988411,97.544548],[39.986259,97.552422],[39.98164,97.571747],[39.97945,97.579453],[39.979401,97.57962],[39.979351,97.579788],[39.979118,97.580513],[39.97887,97.581322],[39.976971,97.587341],[39.97562,97.59185],[39.974819,97.594749],[39.96983,97.615303],[39.96867,97.621437],[39.967949,97.626289],[39.96727,97.630531],[39.967091,97.631401],[39.96701,97.631737],[39.966751,97.63295],[39.966461,97.634132],[39.965889,97.6362],[39.964611,97.64003],[39.96413,97.641243],[39.96328,97.643227],[39.961391,97.647102],[39.95739,97.655563],[39.956459,97.657761],[39.952839,97.667587],[39.951511,97.671204],[39.950329,97.673973],[39.94931,97.676064],[39.948441,97.677696],[39.947762,97.678322],[39.947701,97.679047],[39.945889,97.682449],[39.945339,97.683403],[39.942699,97.687782],[39.940701,97.691788],[39.940109,97.693176],[39.93856,97.697433],[39.937222,97.702263],[39.93539,97.708588],[39.93507,97.709503],[39.933929,97.712547],[39.931839,97.717484],[39.92952,97.723167],[39.926521,97.73188],[39.922089,97.748093],[39.920631,97.752792],[39.920231,97.753883],[39.918991,97.757027],[39.916229,97.762711],[39.9146,97.765404],[39.905449,97.779282],[39.90078,97.786346],[39.90041,97.786903],[39.900028,97.787529],[39.899231,97.788834],[39.897919,97.791153],[39.897499,97.791946],[39.896629,97.793671],[39.896309,97.794373],[39.896091,97.794868],[39.894321,97.799217],[39.891281,97.808968],[39.889759,97.813011],[39.88876,97.81517],[39.886631,97.819153],[39.883789,97.823463],[39.883369,97.824059],[39.879879,97.829247],[39.87809,97.832474],[39.876228,97.836693],[39.875481,97.838623],[39.875309,97.839104],[39.874962,97.840103],[39.874771,97.840714],[39.874722,97.840858],[39.874321,97.842209],[39.87315,97.847214],[39.872742,97.849541],[39.872719,97.849663],[39.871429,97.857353],[39.870522,97.862541],[39.87038,97.863327],[39.869308,97.869034],[39.86927,97.869331],[39.868679,97.872292],[39.868259,97.874458],[39.868149,97.875038],[39.867668,97.877579],[39.867458,97.878647],[39.867161,97.880318],[39.86507,97.893143],[39.864841,97.894348],[39.86422,97.897163],[39.863911,97.898407],[39.863331,97.900642],[39.862461,97.903877],[39.861549,97.907227],[39.860451,97.910782],[39.859531,97.913383],[39.859241,97.914131],[39.85743,97.918419],[39.854691,97.92511],[39.85107,97.93644],[39.84874,97.942169],[39.842659,97.954224],[39.840599,97.958992],[39.839581,97.961853],[39.839069,97.963516],[39.838879,97.964233],[39.8386,97.965218],[39.838329,97.966293],[39.837719,97.969017],[39.83675,97.975533],[39.836411,97.980408],[39.835941,97.993233],[39.835751,97.995903],[39.835651,97.996964],[39.835098,98.001427],[39.83408,98.007278],[39.831661,98.019257],[39.830971,98.021942],[39.830681,98.022926],[39.830608,98.023193],[39.829281,98.027473],[39.827961,98.031921],[39.82518,98.042007],[39.825031,98.042557],[39.824108,98.045792],[39.823841,98.046638],[39.823441,98.047951],[39.82259,98.050499],[39.821659,98.053322],[39.821201,98.054817],[39.821121,98.055061],[39.8181,98.065804],[39.81255,98.082474],[39.808788,98.093147],[39.802261,98.115982],[39.801849,98.117073],[39.80143,98.118294],[39.800541,98.119141],[39.79985,98.119301],[39.799099,98.119057],[39.79842,98.118523],[39.796982,98.117729],[39.797039,98.118134],[39.79652,98.124336],[39.795589,98.126411],[39.795639,98.127251],[39.79586,98.127724],[39.796619,98.128571],[39.797409,98.129433],[39.798111,98.130386],[39.798328,98.130989],[39.798359,98.131729],[39.798031,98.133743],[39.79755,98.134857],[39.797009,98.135643],[39.796982,98.135674],[39.795631,98.137154],[39.793541,98.139603],[39.792252,98.141647],[39.791519,98.143112],[39.790741,98.145149],[39.79002,98.147614],[39.78804,98.154617],[39.780701,98.180634],[39.780441,98.182091],[39.780369,98.184196],[39.780418,98.184914],[39.78051,98.18557],[39.780621,98.186218],[39.780739,98.186783],[39.780972,98.187592],[39.781261,98.188377],[39.78223,98.190567],[39.783298,98.192757],[39.78352,98.193237],[39.784309,98.195053],[39.784859,98.196823],[39.785831,98.202904],[39.786282,98.204277],[39.78849,98.208946],[39.789669,98.211243],[39.790169,98.212196],[39.790649,98.213097],[39.795959,98.22258],[39.796169,98.223091],[39.79623,98.223351],[39.796291,98.223663],[39.79631,98.224037],[39.79631,98.224358],[39.796169,98.225693],[39.796021,98.227623],[39.795841,98.230141],[39.795841,98.23053],[39.79583,98.230713],[39.79578,98.231667],[39.795582,98.233299],[39.795071,98.242218],[39.794651,98.248848],[39.794151,98.250504],[39.79324,98.256889],[39.791481,98.268311],[39.788021,98.290779],[39.787079,98.297058],[39.786751,98.299362],[39.786461,98.301552],[39.786091,98.303917],[39.78603,98.304298],[39.785851,98.305321],[39.785561,98.306793],[39.785389,98.307648],[39.785061,98.309273],[39.784409,98.312523],[39.783039,98.321411],[39.782021,98.326538],[39.78178,98.327927],[39.78056,98.335876],[39.780079,98.339653],[39.779881,98.340431],[39.77956,98.34304],[39.77919,98.345444],[39.779011,98.347023],[39.778999,98.347427],[39.778149,98.352997],[39.777851,98.354439],[39.777699,98.356102],[39.776501,98.364517],[39.77597,98.367798],[39.77401,98.378723],[39.773579,98.380791],[39.770519,98.391006],[39.769279,98.395576],[39.76878,98.397713],[39.768452,98.39946],[39.767502,98.403862],[39.766529,98.408043],[39.765881,98.410362],[39.765621,98.41169],[39.76543,98.413017],[39.765171,98.415977],[39.76498,98.417648],[39.764271,98.422722],[39.764061,98.424698],[39.763851,98.427673],[39.763199,98.432503],[39.76268,98.440178],[39.76162,98.446182],[39.76141,98.447723],[39.761269,98.451622],[39.761139,98.452782],[39.760559,98.456367],[39.760319,98.458473],[39.76017,98.463516],[39.760139,98.469017],[39.759861,98.482643],[39.759819,98.487099],[39.759769,98.487679],[39.759571,98.488739],[39.7593,98.489487],[39.75909,98.489853],[39.75882,98.490143],[39.752739,98.493233],[39.752029,98.493523],[39.748878,98.495064],[39.738289,98.500366],[39.737671,98.500641],[39.736931,98.500282],[39.736752,98.500252],[39.73658,98.500671],[39.73679,98.50193],[39.736031,98.507088],[39.736031,98.507393],[39.735859,98.508347],[39.735641,98.50882],[39.7356,98.509163],[39.735699,98.509377],[39.735691,98.509933],[39.734879,98.515533],[39.734459,98.517387],[39.73423,98.518143],[39.73349,98.519363],[39.731339,98.522148],[39.7281,98.52726],[39.726971,98.529518],[39.72406,98.536087],[39.723068,98.540077],[39.71999,98.550377],[39.716782,98.56115],[39.71537,98.565041],[39.714031,98.566704],[39.713058,98.567459],[39.712219,98.569153],[39.71146,98.570107],[39.710419,98.571487],[39.70673,98.576279],[39.702721,98.58242],[39.69894,98.586761],[39.697819,98.588203],[39.684139,98.604286],[39.683121,98.605476],[39.68119,98.608124],[39.64846,98.658203],[39.644569,98.662773],[39.643269,98.664513],[39.643261,98.664833],[39.640518,98.667847],[39.607601,98.703133],[39.603149,98.708679],[39.601139,98.711227],[39.600971,98.711632],[39.59441,98.719849],[39.593201,98.721451],[39.59219,98.723343],[39.58913,98.733551],[39.587379,98.740196],[39.585281,98.747566],[39.586021,98.747627],[39.58485,98.749229],[39.582649,98.756844],[39.5784,98.772346],[39.576038,98.780312],[39.576111,98.780357],[39.574329,98.787033],[39.571388,98.82679],[39.571251,98.831139],[39.571301,98.872383],[39.571121,98.874039],[39.566021,98.892883],[39.565189,98.89576],[39.564991,98.895973],[39.562901,98.903687],[39.562199,98.905434],[39.561409,98.907211],[39.55806,98.91468],[39.55444,98.923119],[39.551739,98.928078],[39.550549,98.929718],[39.549809,98.930473],[39.543041,98.936996],[39.538151,98.939117],[39.5303,98.942497],[39.52425,98.944443],[39.522961,98.944969],[39.503269,98.959221],[39.49918,98.962677],[39.491112,98.96904],[39.488869,98.970703],[39.48769,98.971458],[39.474831,98.977982],[39.465591,98.982658],[39.464249,98.982803],[39.463219,98.98259],[39.44043,98.976547],[39.435268,98.975197],[39.430759,98.975433],[39.425461,98.975754],[39.419109,98.976158],[39.41626,98.976799],[39.41169,98.978249],[39.4104,98.978859],[39.409111,98.979713],[39.4021,98.985313],[39.380379,99.001549],[39.378712,99.00293],[39.372959,99.013206],[39.37006,99.019577],[39.368221,99.028664],[39.36755,99.030533],[39.365459,99.035042],[39.364899,99.036003],[39.363689,99.03862],[39.363079,99.040916],[39.363289,99.041077],[39.36293,99.042053],[39.363091,99.042236],[39.361801,99.045723],[39.359161,99.054321],[39.357269,99.060623],[39.356419,99.063431],[39.355801,99.069542],[39.35556,99.072449],[39.35223,99.082733],[39.35083,99.087013],[39.350349,99.089203],[39.349941,99.091743],[39.34956,99.092812],[39.348621,99.093613],[39.34539,99.09465],[39.344879,99.094971],[39.34433,99.095482],[39.343491,99.09729],[39.341419,99.103348],[39.341179,99.104057],[39.34127,99.104378],[39.340809,99.105591],[39.340618,99.106758],[39.34029,99.111366],[39.339458,99.122627],[39.339291,99.125473],[39.339031,99.125504],[39.339062,99.128487],[39.338871,99.13018],[39.33667,99.143822],[39.336281,99.145317],[39.32988,99.160294],[39.322922,99.176064],[39.321411,99.179459],[39.320782,99.180527],[39.318958,99.183006],[39.318039,99.184242],[39.317589,99.185204],[39.317451,99.185966],[39.317371,99.193848],[39.317188,99.195152],[39.31657,99.19735],[39.316299,99.198288],[39.315861,99.19986],[39.308239,99.227097],[39.296791,99.268066],[39.28944,99.29332],[39.28841,99.296143],[39.28421,99.303787],[39.280941,99.309776],[39.279888,99.311493],[39.275028,99.316841],[39.27433,99.318031],[39.272221,99.323334],[39.268768,99.333458],[39.26857,99.333878],[39.267639,99.335373],[39.26635,99.336998],[39.257931,99.347504],[39.257141,99.34848],[39.255829,99.350327],[39.254318,99.353149],[39.253361,99.35553],[39.23188,99.428017],[39.229439,99.436272],[39.22887,99.43763],[39.22739,99.439957],[39.227379,99.439842],[39.227371,99.440033],[39.224831,99.45179],[39.224781,99.453484],[39.22506,99.455002],[39.226871,99.460564],[39.2272,99.461502],[39.23122,99.469063],[39.232792,99.472069],[39.235748,99.478867],[39.235939,99.479828],[39.236271,99.48394],[39.236511,99.485748],[39.236938,99.48687],[39.237652,99.487846],[39.238331,99.488426],[39.238541,99.488548],[39.243401,99.489937],[39.24633,99.490753],[39.248489,99.491364],[39.249229,99.491653],[39.250969,99.492699],[39.25309,99.494164],[39.25983,99.497643],[39.261341,99.498772],[39.26313,99.498993],[39.263592,99.499229],[39.263969,99.499763],[39.264339,99.502136],[39.264141,99.505539],[39.26405,99.506943],[39.263851,99.509521],[39.263149,99.512421],[39.263081,99.513512],[39.26321,99.529457],[39.26326,99.543068],[39.265942,99.56086],[39.26627,99.562759],[39.266659,99.563828],[39.273312,99.579262],[39.276791,99.585587],[39.278049,99.588112],[39.27961,99.591179],[39.281841,99.596123],[39.28392,99.60022],[39.284031,99.600441],[39.284969,99.602753],[39.28653,99.607536],[39.292389,99.616859],[39.295189,99.621613],[39.296101,99.62326],[39.298328,99.627823],[39.3046,99.639008],[39.306141,99.642014],[39.30703,99.6437],[39.308552,99.646027],[39.309608,99.647614],[39.310169,99.648857],[39.311272,99.651543],[39.311722,99.653023],[39.314941,99.665878],[39.317089,99.671997],[39.325272,99.695152],[39.32645,99.698471],[39.329399,99.706573],[39.33012,99.709038],[39.330921,99.713821],[39.331009,99.715332],[39.330898,99.717041],[39.330791,99.718712],[39.330509,99.720238],[39.32444,99.733963],[39.321629,99.743492],[39.321362,99.745087],[39.32066,99.749489],[39.320358,99.750679],[39.319859,99.75238],[39.318211,99.756866],[39.315269,99.763817],[39.314651,99.765297],[39.3125,99.77124],[39.31179,99.773804],[39.307232,99.798157],[39.30724,99.798363],[39.30624,99.802261],[39.30579,99.803619],[39.304039,99.806503],[39.303089,99.808601],[39.301231,99.813339],[39.29937,99.818626],[39.29678,99.824249],[39.296059,99.825783],[39.293911,99.835258],[39.292961,99.837967],[39.29208,99.841263],[39.290489,99.84359],[39.289532,99.846039],[39.289379,99.847412],[39.289509,99.847923],[39.28949,99.851601],[39.289471,99.851898],[39.289619,99.854874],[39.289989,99.858093],[39.29121,99.868439],[39.29097,99.882759],[39.290371,99.885643],[39.289841,99.887009],[39.287552,99.891113],[39.286179,99.893799],[39.280209,99.907257],[39.279621,99.90831],[39.278042,99.910347],[39.275551,99.913368],[39.26358,99.931847],[39.247608,99.94902],[39.23772,99.959663],[39.233768,99.964027],[39.23381,99.964043],[39.232891,99.964813],[39.231831,99.965424],[39.229019,99.966759],[39.225101,99.967987],[39.223831,99.968613],[39.22287,99.969307],[39.221859,99.970322],[39.219028,99.973518],[39.217831,99.97477],[39.21484,99.977562],[39.21381,99.978691],[39.212311,99.981117],[39.211529,99.982117],[39.19817,99.993927],[39.19735,99.994827],[39.196949,99.995842],[39.196239,100.002251],[39.195889,100.00692],[39.19577,100.009262],[39.195641,100.010391],[39.19548,100.011673],[39.195061,100.01268],[39.193489,100.014412],[39.19268,100.015167],[39.192551,100.015137],[39.19252,100.01532],[39.19136,100.016487],[39.188541,100.019142],[39.18771,100.019958],[39.186081,100.02076],[39.182491,100.021347],[39.181751,100.021812],[39.181061,100.022751],[39.179779,100.025513],[39.17931,100.026199],[39.177872,100.028793],[39.177399,100.029953],[39.177029,100.031303],[39.176819,100.033096],[39.17691,100.037521],[39.176941,100.039017],[39.176842,100.043663],[39.175491,100.048759],[39.1749,100.050201],[39.174461,100.051987],[39.173759,100.055367],[39.172501,100.060173],[39.172588,100.060211],[39.172401,100.06073],[39.173038,100.069504],[39.17247,100.071899],[39.17226,100.073692],[39.17321,100.080002],[39.173149,100.081558],[39.173031,100.082077],[39.17268,100.083633],[39.172081,100.086273],[39.172218,100.086403],[39.171829,100.086838],[39.169621,100.091873],[39.1684,100.095497],[39.167149,100.098007],[39.16608,100.099167],[39.164761,100.100052],[39.16383,100.100693],[39.161388,100.10215],[39.16087,100.102692],[39.160172,100.103897],[39.157539,100.112488],[39.156929,100.113617],[39.156281,100.11451],[39.154079,100.11734],[39.153561,100.118408],[39.15316,100.119682],[39.15292,100.122673],[39.153061,100.123978],[39.154091,100.125526],[39.15649,100.128166],[39.157162,100.129143],[39.157452,100.130127],[39.156582,100.138634],[39.15657,100.138817],[39.156021,100.142693],[39.15493,100.14962],[39.15379,100.154404],[39.152962,100.157829],[39.151051,100.167427],[39.150871,100.167763],[39.147491,100.171143],[39.14727,100.171333],[39.14608,100.172897],[39.145721,100.173111],[39.143879,100.175812],[39.139511,100.181587],[39.138802,100.182419],[39.136372,100.184402],[39.135288,100.185448],[39.131851,100.192169],[39.131569,100.193153],[39.131149,100.197807],[39.130459,100.201263],[39.130039,100.202682],[39.127258,100.208557],[39.125149,100.213287],[39.121849,100.219254],[39.12056,100.221153],[39.117352,100.224907],[39.1129,100.232071],[39.112129,100.233353],[39.111488,100.234528],[39.110161,100.238693],[39.108261,100.24482],[39.106621,100.253532],[39.10601,100.255219],[39.099529,100.265472],[39.097809,100.267929],[39.09132,100.274979],[39.08886,100.278084],[39.08638,100.282143],[39.085449,100.283142],[39.083241,100.285378],[39.08152,100.287308],[39.079159,100.29039],[39.07848,100.290787],[39.077999,100.291763],[39.07642,100.293739],[39.074471,100.296593],[39.072319,100.299248],[39.07132,100.300247],[39.06966,100.301903],[39.057961,100.314529],[39.05022,100.322197],[39.04755,100.324883],[39.046558,100.325798],[39.043289,100.327919],[39.042301,100.328537],[39.041359,100.329247],[39.04044,100.330383],[39.03764,100.336403],[39.037201,100.337173],[39.031891,100.344978],[39.03001,100.347763],[39.01815,100.358269],[39.017208,100.359367],[39.014439,100.363419],[39.011909,100.366524],[39.011131,100.367569],[39.009892,100.370148],[39.009491,100.371307],[39.009411,100.37294],[39.009701,100.374458],[39.009899,100.376793],[39.009682,100.378067],[39.009171,100.379158],[39.00856,100.379959],[39.00684,100.381622],[39.006271,100.382782],[39.003311,100.390747],[39.000702,100.395638],[38.99966,100.398117],[38.99839,100.401466],[38.997978,100.402969],[38.997711,100.404762],[38.997398,100.406532],[38.996571,100.408501],[38.995571,100.410332],[38.995041,100.411652],[38.994362,100.414619],[38.994259,100.416],[38.994469,100.417084],[38.996239,100.421806],[38.996651,100.423264],[38.996609,100.428879],[38.996151,100.43045],[38.99585,100.430832],[38.991089,100.435509],[38.99017,100.435982],[38.989288,100.435959],[38.985409,100.434433],[38.980579,100.432991],[38.979401,100.433357],[38.97773,100.434357],[38.975861,100.437202],[38.974949,100.437912],[38.972141,100.438797],[38.960949,100.43602],[38.95298,100.433403],[38.95216,100.433128],[38.95126,100.432938],[38.95063,100.433144],[38.94836,100.434303],[38.942612,100.437157],[38.941761,100.437927],[38.938251,100.44165],[38.93692,100.443031],[38.9352,100.443413],[38.93541,100.444107],[38.935711,100.44725],[38.93644,100.452507],[38.93647,100.453751],[38.936588,100.45488],[38.936989,100.461548],[38.937401,100.465958],[38.937389,100.467453],[38.937469,100.468674],[38.937469,100.470398],[38.937439,100.472549],[38.937401,100.47464],[38.93734,100.477226],[38.937359,100.480133],[38.937489,100.482933],[38.937889,100.488083],[38.937908,100.488579],[38.93792,100.488907],[38.937729,100.488991],[38.934582,100.488632],[38.927471,100.487907],[38.92429,100.487694],[38.92131,100.487503],[38.918362,100.487297],[38.915371,100.487099],[38.911781,100.486893],[38.9081,100.486671],[38.906281,100.486549],[38.905769,100.486267],[38.905651,100.486282],[38.905361,100.486313],[38.905312,100.486366],[38.90453,100.487389],[38.903542,100.4888],[38.897739,100.496407],[38.894131,100.499657],[38.89225,100.500999],[38.888939,100.503441],[38.885078,100.50631],[38.878761,100.511673],[38.877159,100.51358],[38.87524,100.515968],[38.87027,100.52195],[38.860298,100.534897],[38.85957,100.537666],[38.85746,100.541687],[38.85574,100.54493],[38.854431,100.547401],[38.853851,100.548477],[38.853451,100.54921],[38.8521,100.551849],[38.851349,100.553253],[38.85001,100.555794],[38.84811,100.559349],[38.846142,100.563026],[38.84539,100.564133],[38.8442,100.565521],[38.839249,100.569122],[38.83136,100.571358],[38.83297,100.576851],[38.82534,100.582687],[38.81625,100.590927],[38.796181,100.60878],[38.763531,100.63195],[38.754429,100.637619],[38.725109,100.655472],[38.708359,100.664742],[38.70488,100.667488],[38.702068,100.670227],[38.688271,100.686203],[38.687061,100.687569],[38.676609,100.705421],[38.675941,100.706451],[38.66629,100.71315],[38.667099,100.716751],[38.6675,100.720528],[38.667759,100.723961],[38.672321,100.771339],[38.655701,100.774429],[38.61655,100.780777],[38.531059,100.795723],[38.483768,100.804131],[38.480141,100.805328],[38.47905,100.805946],[38.468189,100.812027],[38.46254,100.814774],[38.459721,100.815804],[38.448559,100.818031],[38.446949,100.818893],[38.445869,100.820427],[38.443581,100.8237],[38.441841,100.82576],[38.44009,100.82679],[38.43874,100.827637],[38.43565,100.829018],[38.416019,100.837936],[38.360451,100.86335],[38.358158,100.864899],[38.33218,100.886353],[38.31292,100.896477],[38.31076,100.897339],[38.305241,100.898201],[38.302811,100.898888],[38.277481,100.908836],[38.27182,100.911423],[38.267109,100.914162],[38.263329,100.916908],[38.240681,100.934937],[38.23893,100.935966],[38.230438,100.937851],[38.22525,100.938667],[38.22401,100.938904],[38.21764,100.940109],[38.215462,100.939423],[38.214828,100.939209],[38.21431,100.938957],[38.201801,100.93528],[38.20174,100.935257],[38.200401,100.934982],[38.194172,100.932129],[38.19355,100.932167],[38.191509,100.932266],[38.189819,100.932564],[38.188801,100.933067],[38.187191,100.933891],[38.183262,100.935593],[38.18232,100.93589],[38.18116,100.936142],[38.179989,100.936096],[38.178612,100.935837],[38.176151,100.935226],[38.17593,100.935158],[38.17543,100.935127],[38.17474,100.935226],[38.174381,100.935333],[38.173191,100.935997],[38.170811,100.938019],[38.169861,100.938141],[38.169529,100.938133],[38.16922,100.938057],[38.168282,100.936287],[38.166069,100.937134],[38.166561,100.93586],[38.16634,100.935364],[38.16626,100.934853],[38.165741,100.934723],[38.16497,100.93383],[38.162579,100.934982],[38.162231,100.93528],[38.161411,100.936569],[38.161209,100.936867],[38.16053,100.937439],[38.16029,100.937447],[38.15947,100.936722],[38.158779,100.936073],[38.15852,100.93576],[38.153389,100.931503],[38.152328,100.93026],[38.151409,100.928841],[38.1483,100.923149],[38.14677,100.922836],[38.14465,100.922813],[38.13913,100.922333],[38.138729,100.921997],[38.137669,100.920853],[38.13485,100.920441],[38.133919,100.920181],[38.133221,100.920242],[38.132881,100.920341],[38.126369,100.917053],[38.125771,100.917122],[38.12159,100.91671],[38.118771,100.917053],[38.11718,100.916672],[38.11676,100.91642],[38.11602,100.916412],[38.114201,100.916252],[38.113411,100.916367],[38.113071,100.916458],[38.113041,100.916473],[38.112598,100.916527],[38.112209,100.916611],[38.110981,100.917023],[38.11047,100.917229],[38.108398,100.917892],[38.105492,100.918831],[38.10294,100.919861],[38.101051,100.921097],[38.099892,100.921783],[38.09866,100.922501],[38.096241,100.920647],[38.095921,100.920799],[38.09502,100.921738],[38.09444,100.922363],[38.094238,100.922523],[38.092918,100.922768],[38.092659,100.922768],[38.091438,100.922371],[38.091202,100.92234],[38.09095,100.922371],[38.089951,100.92292],[38.089588,100.922997],[38.087589,100.922287],[38.086342,100.921783],[38.086128,100.921959],[38.085819,100.922127],[38.085381,100.922028],[38.08466,100.921509],[38.08456,100.921089],[38.084301,100.920227],[38.084221,100.920036],[38.08353,100.918831],[38.082909,100.91761],[38.08292,100.917099],[38.083038,100.916718],[38.083771,100.915039],[38.083309,100.911873],[38.0812,100.912231],[38.079781,100.910057],[38.077671,100.908447],[38.07642,100.907082],[38.075939,100.907028],[38.075169,100.906967],[38.073582,100.906807],[38.073139,100.906593],[38.072418,100.905533],[38.07119,100.903549],[38.070061,100.902039],[38.069592,100.901604],[38.069229,100.90123],[38.069118,100.901176],[38.068958,100.901093],[38.068691,100.900917],[38.066059,100.89875],[38.06493,100.896889],[38.064602,100.896294],[38.064362,100.895851],[38.064049,100.894623],[38.063911,100.894112],[38.06369,100.893761],[38.063389,100.893471],[38.061901,100.89257],[38.061508,100.892326],[38.061089,100.892036],[38.060539,100.891502],[38.06015,100.891083],[38.060131,100.89106],[38.05999,100.890923],[38.05806,100.889229],[38.057362,100.888283],[38.057281,100.888191],[38.056889,100.887894],[38.056358,100.887466],[38.055229,100.886688],[38.05442,100.886139],[38.053909,100.886078],[38.05283,100.886497],[38.050999,100.887207],[38.04887,100.887001],[38.047798,100.886871],[38.04686,100.887138],[38.04538,100.887756],[38.044159,100.888252],[38.042259,100.888908],[38.040859,100.889023],[38.039219,100.888992],[38.03812,100.889374],[38.035961,100.89048],[38.035191,100.891068],[38.033932,100.892174],[38.032829,100.893143],[38.0313,100.894478],[38.03019,100.89547],[38.029259,100.896149],[38.02895,100.896317],[38.028,100.8964],[38.02663,100.896248],[38.025509,100.896248],[38.024231,100.896317],[38.02322,100.896011],[38.021809,100.895432],[38.02076,100.89502],[38.01973,100.894882],[38.018162,100.894783],[38.016579,100.894653],[38.01572,100.894791],[38.014729,100.895241],[38.013451,100.895851],[38.01292,100.896111],[38.012611,100.896347],[38.0116,100.897499],[38.01049,100.898743],[38.009499,100.89991],[38.00872,100.901077],[38.007912,100.902313],[38.007401,100.903084],[38.006409,100.904556],[38.005939,100.90535],[38.00589,100.90554],[38.005859,100.906082],[38.006119,100.907249],[38.00631,100.907837],[38.006321,100.908043],[38.006199,100.908684],[38.005638,100.909477],[38.004921,100.909714],[38.004341,100.909889],[38.004211,100.909973],[38.00399,100.910172],[38.00354,100.910957],[38.00296,100.912216],[38.002159,100.913986],[38.001869,100.914558],[38.00148,100.915024],[38.000629,100.915543],[38.000141,100.916023],[38.000061,100.916191],[37.999931,100.916763],[37.99995,100.917664],[37.99976,100.918251],[37.999069,100.91922],[37.998081,100.920486],[37.994629,100.922951],[37.993259,100.923653],[37.992119,100.92395],[37.991749,100.924187],[37.991718,100.924271],[37.992081,100.924622],[37.992352,100.924583],[37.993462,100.924759],[37.994831,100.925262],[37.99577,100.925636],[37.995949,100.925858],[37.995369,100.926323],[37.994511,100.92617],[37.99313,100.926003],[37.991619,100.926338],[37.98933,100.927071],[37.988651,100.927277],[37.987629,100.927383],[37.986462,100.927254],[37.985901,100.927437],[37.985729,100.927917],[37.985729,100.928139],[37.985909,100.929626],[37.985851,100.929916],[37.98558,100.929962],[37.985111,100.929047],[37.98457,100.92804],[37.9841,100.927498],[37.983879,100.927353],[37.98291,100.927193],[37.981701,100.927467],[37.98,100.927994],[37.978321,100.928558],[37.976299,100.929497],[37.973499,100.930946],[37.97234,100.931587],[37.970921,100.932564],[37.969349,100.933693],[37.968651,100.934273],[37.96822,100.934914],[37.967701,100.935738],[37.966919,100.936974],[37.965889,100.938133],[37.96278,100.941231],[37.95332,100.950447],[37.95113,100.952316],[37.948059,100.954712],[37.946251,100.956261],[37.942341,100.960251],[37.940208,100.962517],[37.938641,100.964043],[37.925011,100.976463],[37.923859,100.977821],[37.912819,100.993507],[37.91153,100.995216],[37.906441,101.00177],[37.902988,101.006012],[37.897812,101.012581],[37.895741,101.015099],[37.894581,101.016342],[37.893471,101.017319],[37.886219,101.022598],[37.884129,101.0242],[37.882912,101.02549],[37.876579,101.034492],[37.87384,101.037201],[37.87289,101.038643],[37.871059,101.042099],[37.869381,101.045097],[37.865761,101.050629],[37.86404,101.053368],[37.861839,101.05851],[37.86116,101.060448],[37.860329,101.064133],[37.860329,101.065292],[37.8606,101.065331],[37.86047,101.066803],[37.86034,101.069008],[37.86026,101.069633],[37.860062,101.070129],[37.859489,101.070717],[37.85928,101.070801],[37.85873,101.070824],[37.85714,101.070374],[37.855881,101.070053],[37.855511,101.070183],[37.85537,101.070267],[37.854889,101.070847],[37.854771,101.07119],[37.854061,101.072327],[37.85331,101.073563],[37.85252,101.074989],[37.85228,101.075417],[37.85191,101.076263],[37.851521,101.077271],[37.850632,101.080223],[37.85051,101.080566],[37.8503,101.081352],[37.849998,101.082458],[37.84977,101.083717],[37.849621,101.084793],[37.849548,101.085373],[37.849491,101.085854],[37.849098,101.08725],[37.848598,101.088982],[37.847919,101.091454],[37.847698,101.093063],[37.84763,101.09433],[37.847599,101.094627],[37.84753,101.095673],[37.847462,101.096786],[37.847321,101.098503],[37.847118,101.099922],[37.846741,101.101959],[37.846489,101.103348],[37.846371,101.104027],[37.846199,101.104767],[37.8461,101.105431],[37.845741,101.10656],[37.84515,101.107933],[37.844719,101.109108],[37.84457,101.110367],[37.844479,101.112419],[37.844398,101.114662],[37.844311,101.115028],[37.84383,101.115433],[37.843449,101.115288],[37.842651,101.114532],[37.84185,101.11367],[37.840961,101.112709],[37.840488,101.112244],[37.840469,101.11219],[37.840439,101.112259],[37.840351,101.112129],[37.84013,101.111938],[37.839489,101.111588],[37.83905,101.111526],[37.83865,101.111588],[37.8381,101.111923],[37.8377,101.112373],[37.837238,101.113403],[37.8367,101.114769],[37.836479,101.115669],[37.8363,101.117081],[37.83577,101.12207],[37.835499,101.124001],[37.835121,101.125214],[37.834309,101.127197],[37.833679,101.129219],[37.833359,101.130989],[37.83305,101.133148],[37.83321,101.134811],[37.833881,101.137657],[37.834099,101.138351],[37.834702,101.13916],[37.83567,101.139702],[37.836121,101.139923],[37.836418,101.140373],[37.83614,101.140572],[37.835178,101.140648],[37.83382,101.140762],[37.832279,101.14077],[37.830601,101.140587],[37.82917,101.140778],[37.827431,101.140717],[37.825581,101.140388],[37.82452,101.1399],[37.823139,101.139297],[37.82214,101.139259],[37.821178,101.139618],[37.819019,101.140663],[37.817181,101.141411],[37.816669,101.141617],[37.815929,101.142174],[37.814751,101.143822],[37.813019,101.146439],[37.811901,101.148109],[37.811069,101.148567],[37.809551,101.148941],[37.807381,101.149544],[37.806061,101.150299],[37.804459,101.151299],[37.804119,101.151428],[37.80278,101.151962],[37.801182,101.152908],[37.798481,101.154587],[37.79567,101.156326],[37.795521,101.156441],[37.794899,101.157471],[37.793388,101.160606],[37.792149,101.163231],[37.791801,101.164368],[37.791191,101.167183],[37.790531,101.170303],[37.789902,101.173157],[37.789532,101.173958],[37.788589,101.17514],[37.787369,101.176498],[37.786541,101.177071],[37.785759,101.177933],[37.78442,101.179588],[37.783279,101.181313],[37.782421,101.183456],[37.7813,101.186394],[37.780449,101.188187],[37.779011,101.190361],[37.777809,101.191879],[37.77594,101.193947],[37.774529,101.194939],[37.772461,101.196312],[37.770329,101.197906],[37.7682,101.200546],[37.76577,101.203506],[37.76276,101.207207],[37.760689,101.210091],[37.75843,101.213463],[37.757191,101.215767],[37.755589,101.219109],[37.75441,101.222031],[37.753521,101.223457],[37.752949,101.224693],[37.752522,101.226517],[37.751942,101.228729],[37.751259,101.230072],[37.749901,101.232407],[37.749359,101.233803],[37.74844,101.236168],[37.7481,101.236839],[37.746868,101.238503],[37.745739,101.239891],[37.745441,101.240372],[37.74519,101.241577],[37.745049,101.24324],[37.744511,101.244423],[37.743649,101.246094],[37.742661,101.247627],[37.74091,101.249893],[37.739029,101.252281],[37.73679,101.255127],[37.734909,101.257561],[37.733028,101.260033],[37.732281,101.261452],[37.730949,101.264313],[37.730011,101.265556],[37.72863,101.266953],[37.727772,101.26783],[37.727531,101.268387],[37.727402,101.270111],[37.72736,101.27079],[37.727242,101.271141],[37.727051,101.271507],[37.726719,101.272079],[37.726391,101.272667],[37.725971,101.273331],[37.725208,101.274597],[37.724411,101.275932],[37.723999,101.277107],[37.723961,101.278053],[37.72422,101.279388],[37.724289,101.279747],[37.724159,101.28093],[37.723862,101.281448],[37.722301,101.283569],[37.721378,101.284973],[37.720901,101.286507],[37.72065,101.287338],[37.720161,101.288406],[37.719929,101.288811],[37.719589,101.289467],[37.719028,101.290482],[37.718262,101.291878],[37.71706,101.294037],[37.715969,101.296043],[37.714989,101.297813],[37.714699,101.298309],[37.71434,101.299026],[37.713829,101.300072],[37.713799,101.300117],[37.713242,101.300728],[37.712799,101.301132],[37.712601,101.301208],[37.712269,101.301277],[37.71159,101.301208],[37.71125,101.30101],[37.711079,101.300903],[37.71077,101.300743],[37.710209,101.300133],[37.709751,101.29969],[37.709309,101.299187],[37.708691,101.298683],[37.70834,101.298576],[37.707771,101.298767],[37.706871,101.299149],[37.706551,101.299294],[37.70607,101.299492],[37.705238,101.29985],[37.704762,101.300049],[37.704361,101.300217],[37.703651,101.300507],[37.70253,101.300987],[37.700699,101.30172],[37.698448,101.302338],[37.695919,101.302711],[37.69265,101.303146],[37.690048,101.303581],[37.68877,101.304001],[37.686951,101.304588],[37.686069,101.304909],[37.6847,101.305496],[37.68343,101.306107],[37.680759,101.307327],[37.67836,101.308121],[37.67527,101.309196],[37.672642,101.31041],[37.669472,101.311913],[37.668152,101.312767],[37.666481,101.313927],[37.665161,101.314903],[37.664322,101.315666],[37.662891,101.317139],[37.66127,101.318573],[37.660339,101.319321],[37.659191,101.320152],[37.65731,101.321297],[37.655869,101.322144],[37.654308,101.323029],[37.652191,101.324303],[37.648499,101.326591],[37.645439,101.328568],[37.64394,101.329826],[37.643021,101.330872],[37.64254,101.331497],[37.641319,101.333237],[37.639839,101.335373],[37.638199,101.337723],[37.636379,101.340317],[37.634541,101.342957],[37.632141,101.34639],[37.629341,101.350357],[37.627628,101.352814],[37.626659,101.354301],[37.62627,101.355598],[37.625721,101.357979],[37.625141,101.359108],[37.62434,101.360046],[37.62286,101.361603],[37.621571,101.363548],[37.62019,101.365372],[37.619209,101.366013],[37.617599,101.366814],[37.616562,101.367691],[37.61496,101.369507],[37.613701,101.370613],[37.610222,101.373337],[37.607319,101.375664],[37.60474,101.37793],[37.602089,101.380333],[37.598621,101.383461],[37.594391,101.387299],[37.591091,101.390297],[37.58691,101.394119],[37.583401,101.397293],[37.580681,101.399773],[37.580269,101.400131],[37.579899,101.400482],[37.579269,101.401047],[37.5783,101.401932],[37.57708,101.403053],[37.575291,101.404663],[37.57296,101.406754],[37.57003,101.409286],[37.566971,101.411903],[37.56599,101.412727],[37.56562,101.413033],[37.564522,101.413963],[37.563381,101.414726],[37.561989,101.415352],[37.56007,101.416077],[37.557541,101.417061],[37.554241,101.418373],[37.551399,101.419312],[37.547798,101.420357],[37.545071,101.421227],[37.542511,101.42215],[37.540421,101.422928],[37.53783,101.423813],[37.53566,101.424393],[37.534081,101.424332],[37.531898,101.42424],[37.529049,101.424202],[37.525181,101.424263],[37.52179,101.424278],[37.519741,101.424316],[37.516869,101.424393],[37.512939,101.424461],[37.508251,101.424538],[37.503899,101.424629],[37.500198,101.424683],[37.49575,101.424767],[37.492561,101.424797],[37.489559,101.424988],[37.487999,101.425407],[37.48576,101.425972],[37.482288,101.426201],[37.479931,101.426361],[37.4776,101.426498],[37.475159,101.426643],[37.473331,101.426697],[37.471889,101.426514],[37.47049,101.426529],[37.467419,101.426758],[37.46513,101.426933],[37.464211,101.42672],[37.464119,101.426697],[37.463982,101.426659],[37.463848,101.426582],[37.463139,101.426132],[37.46244,101.425659],[37.461079,101.424744],[37.459431,101.423668],[37.457729,101.422523],[37.45628,101.421501],[37.455479,101.420937],[37.45435,101.419746],[37.452621,101.417473],[37.451469,101.415993],[37.44981,101.413803],[37.44854,101.412338],[37.44804,101.412064],[37.44775,101.411888],[37.445492,101.411247],[37.443668,101.410637],[37.441891,101.40976],[37.44035,101.409012],[37.440208,101.408943],[37.43853,101.40863],[37.436539,101.408112],[37.434071,101.406921],[37.433498,101.406593],[37.432201,101.406242],[37.431061,101.406303],[37.42942,101.406502],[37.427738,101.406723],[37.425339,101.407478],[37.422489,101.408386],[37.420898,101.408218],[37.419739,101.407829],[37.417549,101.40773],[37.416061,101.407822],[37.414471,101.408257],[37.412609,101.408791],[37.411018,101.409241],[37.409962,101.409531],[37.40871,101.409767],[37.4076,101.409538],[37.406799,101.409302],[37.40564,101.409393],[37.404781,101.409843],[37.403141,101.410782],[37.401932,101.411163],[37.39996,101.411751],[37.398479,101.412033],[37.397221,101.412209],[37.396179,101.412369],[37.394939,101.412666],[37.394131,101.413139],[37.39407,101.413162],[37.393711,101.413223],[37.393089,101.412956],[37.391979,101.412209],[37.390869,101.411697],[37.389389,101.411148],[37.38903,101.410583],[37.38913,101.40995],[37.389179,101.409843],[37.389591,101.409142],[37.38966,101.408524],[37.389408,101.408096],[37.38839,101.406822],[37.387348,101.405571],[37.387112,101.405411],[37.386189,101.405357],[37.38554,101.40522],[37.384762,101.404449],[37.38401,101.403732],[37.38353,101.403618],[37.3825,101.403793],[37.38203,101.403572],[37.381908,101.40332],[37.38184,101.40303],[37.38163,101.401863],[37.381161,101.400917],[37.38028,101.399353],[37.379539,101.398064],[37.37907,101.397758],[37.378651,101.397919],[37.378529,101.398209],[37.378262,101.399963],[37.378239,101.400597],[37.378601,101.401222],[37.37904,101.401627],[37.37915,101.401901],[37.379169,101.402367],[37.37854,101.403183],[37.378342,101.40345],[37.378269,101.404053],[37.378471,101.404953],[37.378979,101.406151],[37.37957,101.407173],[37.379631,101.407341],[37.37973,101.407913],[37.379639,101.409309],[37.379372,101.409698],[37.378639,101.41011],[37.378429,101.410233],[37.378311,101.410339],[37.377861,101.411201],[37.377651,101.411713],[37.377571,101.411819],[37.376991,101.412308],[37.376259,101.412827],[37.374969,101.413727],[37.374741,101.413841],[37.373779,101.413933],[37.37265,101.414131],[37.372059,101.41494],[37.371849,101.415283],[37.37146,101.415459],[37.371319,101.415199],[37.37151,101.41481],[37.37159,101.414726],[37.37183,101.41449],[37.372509,101.413429],[37.373138,101.413017],[37.37431,101.412582],[37.37439,101.412537],[37.37524,101.411491],[37.376221,101.41021],[37.376579,101.409309],[37.37677,101.408707],[37.376801,101.407959],[37.376671,101.407494],[37.376549,101.407181],[37.375622,101.406151],[37.37534,101.405891],[37.374939,101.405739],[37.37405,101.405937],[37.372532,101.406487],[37.37244,101.406502],[37.371429,101.406052],[37.370049,101.405357],[37.369881,101.40464],[37.36993,101.404381],[37.370461,101.402924],[37.370449,101.402229],[37.370121,101.401772],[37.369801,101.401688],[37.368721,101.401741],[37.36731,101.401833],[37.36607,101.402046],[37.36491,101.402313],[37.363361,101.402893],[37.362251,101.403313],[37.36216,101.403671],[37.362228,101.403793],[37.362572,101.403816],[37.362751,101.403793],[37.36301,101.403664],[37.364571,101.40313],[37.364681,101.403091],[37.36499,101.403091],[37.365139,101.40345],[37.36483,101.403687],[37.364071,101.403687],[37.36314,101.404083],[37.362671,101.404282],[37.361889,101.404373],[37.361141,101.404373],[37.361,101.404381],[37.360821,101.404442],[37.360691,101.404716],[37.36097,101.405006],[37.362041,101.40477],[37.362999,101.404846],[37.363091,101.404861],[37.364029,101.404579],[37.364319,101.404488],[37.364849,101.404587],[37.36517,101.404739],[37.365719,101.40477],[37.366051,101.404442],[37.366531,101.404007],[37.366619,101.404022],[37.36742,101.404083],[37.367668,101.404312],[37.36755,101.404663],[37.36747,101.404694],[37.36647,101.404694],[37.366249,101.404793],[37.365921,101.405167],[37.365761,101.405357],[37.36499,101.405739],[37.363918,101.405998],[37.362591,101.406319],[37.36179,101.406464],[37.361012,101.406601],[37.360149,101.406754],[37.35891,101.406799],[37.358398,101.406807],[37.357201,101.407204],[37.356079,101.407928],[37.356022,101.407967],[37.35553,101.408157],[37.354881,101.407799],[37.353771,101.406982],[37.35355,101.40683],[37.337841,101.397949],[37.335972,101.398239],[37.33374,101.398643],[37.333111,101.398743],[37.33165,101.399529],[37.3283,101.401382],[37.327991,101.401611],[37.327702,101.402107],[37.327591,101.40287],[37.327621,101.403572],[37.32711,101.4048],[37.325871,101.406174],[37.32552,101.40638],[37.325272,101.406433],[37.324612,101.406219],[37.323872,101.405457],[37.32349,101.405167],[37.32299,101.405228],[37.321861,101.406189],[37.32111,101.407578],[37.32032,101.409317],[37.320179,101.40947],[37.319901,101.409416],[37.319881,101.408897],[37.319931,101.408813],[37.320728,101.407356],[37.321331,101.406303],[37.322369,101.404823],[37.322861,101.404213],[37.323071,101.403961],[37.323219,101.403831],[37.32349,101.40377],[37.324001,101.403893],[37.324501,101.403793],[37.3246,101.403587],[37.324551,101.402191],[37.324982,101.401337],[37.326141,101.400253],[37.326759,101.399658],[37.326931,101.399437],[37.326889,101.399101],[37.326778,101.398987],[37.326469,101.399132],[37.325409,101.400177],[37.32468,101.400787],[37.32391,101.401749],[37.323589,101.402153],[37.322632,101.40284],[37.32106,101.404533],[37.32021,101.405121],[37.31958,101.40609],[37.3195,101.406197],[37.31847,101.407379],[37.316929,101.409149],[37.31678,101.409607],[37.317039,101.412064],[37.317181,101.412399],[37.31757,101.412689],[37.318748,101.412956],[37.31889,101.412971],[37.319851,101.412727],[37.32058,101.412491],[37.32103,101.412643],[37.322189,101.413002],[37.32336,101.413361],[37.324661,101.413834],[37.324821,101.413918],[37.325069,101.414093],[37.325199,101.414383],[37.325119,101.414848],[37.324951,101.415009],[37.322498,101.415657],[37.322071,101.415771],[37.320229,101.415787],[37.31879,101.416527],[37.31702,101.417488],[37.314079,101.41925],[37.312801,101.420464],[37.31229,101.420959],[37.311039,101.421883],[37.308819,101.423248],[37.308151,101.423737],[37.307831,101.424103],[37.30756,101.424423],[37.307129,101.424561],[37.3064,101.424431],[37.306149,101.424408],[37.305901,101.424454],[37.305309,101.424759],[37.304619,101.42485],[37.303761,101.424797],[37.303371,101.424927],[37.302719,101.425468],[37.302361,101.425636],[37.302189,101.425346],[37.30238,101.425018],[37.303379,101.424522],[37.304871,101.424004],[37.306099,101.422768],[37.307281,101.422249],[37.307781,101.422028],[37.307709,101.421837],[37.306499,101.422058],[37.305401,101.42244],[37.30378,101.423218],[37.30299,101.423508],[37.30265,101.423378],[37.301788,101.422119],[37.299229,101.4188],[37.29887,101.418297],[37.297771,101.417084],[37.296501,101.415581],[37.295761,101.414757],[37.294979,101.414841],[37.29454,101.41497],[37.293732,101.414757],[37.292919,101.414383],[37.292629,101.414322],[37.290932,101.414398],[37.288929,101.414543],[37.287491,101.414978],[37.286819,101.415253],[37.285591,101.415314],[37.285339,101.415314],[37.284981,101.415489],[37.28487,101.416031],[37.284981,101.4161],[37.286949,101.415756],[37.287498,101.415688],[37.28775,101.415672],[37.28846,101.415657],[37.288528,101.415657],[37.288681,101.415703],[37.288731,101.415993],[37.288582,101.416199],[37.28772,101.416443],[37.28672,101.41655],[37.28492,101.416656],[37.282841,101.416847],[37.280769,101.416542],[37.277889,101.416054],[37.275749,101.415771],[37.273762,101.416153],[37.272942,101.416183],[37.272301,101.415916],[37.271969,101.415771],[37.270729,101.415771],[37.2687,101.416069],[37.26685,101.416168],[37.263821,101.41597],[37.2612,101.415314],[37.25959,101.41494],[37.25724,101.414398],[37.25568,101.41433],[37.253761,101.414413],[37.253609,101.414429],[37.251259,101.414558],[37.250561,101.415009],[37.24929,101.416481],[37.248531,101.417526],[37.244671,101.429771],[37.243301,101.435257],[37.242859,101.437271],[37.242939,101.438911],[37.24342,101.442207],[37.2449,101.44738],[37.245338,101.450417],[37.245529,101.452568],[37.245449,101.454262],[37.24464,101.464493],[37.24445,101.466148],[37.24437,101.466454],[37.244041,101.466988],[37.243401,101.467506],[37.243069,101.467857],[37.242939,101.468613],[37.243969,101.471687],[37.244919,101.472878],[37.245079,101.473251],[37.24514,101.475067],[37.243679,101.483513],[37.243172,101.48555],[37.242458,101.486748],[37.241989,101.487427],[37.24176,101.488922],[37.241661,101.490196],[37.24086,101.491463],[37.238831,101.495354],[37.238529,101.500031],[37.237782,101.50103],[37.236099,101.501312],[37.2356,101.501694],[37.2346,101.503036],[37.23447,101.503258],[37.234409,101.503517],[37.234539,101.504219],[37.235321,101.506203],[37.235191,101.507553],[37.235222,101.507881],[37.236031,101.509827],[37.235661,101.512444],[37.235168,101.516289],[37.23476,101.517311],[37.233669,101.518204],[37.233139,101.520264],[37.2327,101.520737],[37.23246,101.520737],[37.230881,101.520073],[37.230061,101.520126],[37.22958,101.520447],[37.229382,101.520668],[37.22855,101.521217],[37.228031,101.521927],[37.227242,101.522346],[37.226849,101.522469],[37.225948,101.523193],[37.224831,101.524261],[37.223831,101.526154],[37.222679,101.528816],[37.222561,101.528976],[37.22216,101.529846],[37.221958,101.530083],[37.221588,101.530113],[37.221241,101.529846],[37.22076,101.529358],[37.220341,101.529297],[37.219872,101.5298],[37.21909,101.531013],[37.218342,101.531342],[37.218159,101.531631],[37.218189,101.532112],[37.218819,101.534027],[37.219021,101.535423],[37.219009,101.535713],[37.21862,101.536133],[37.218182,101.53595],[37.216209,101.532883],[37.215919,101.532661],[37.215542,101.53273],[37.212608,101.537086],[37.21244,101.53727],[37.20805,101.53756],[37.207062,101.537064],[37.206692,101.537086],[37.206261,101.537643],[37.206009,101.537888],[37.20583,101.537933],[37.205631,101.537872],[37.20414,101.536377],[37.20364,101.536217],[37.203091,101.537331],[37.202221,101.538544],[37.20163,101.539177],[37.199741,101.539398],[37.199051,101.539177],[37.199131,101.539062],[37.200741,101.539124],[37.201439,101.538971],[37.20163,101.538849],[37.201561,101.538239],[37.200771,101.538116],[37.19978,101.538231],[37.19849,101.538254],[37.197311,101.538109],[37.19585,101.537376],[37.19503,101.537163],[37.19453,101.537262],[37.192909,101.538673],[37.18969,101.541893],[37.1894,101.542267],[37.18771,101.543747],[37.187351,101.544594],[37.18652,101.54702],[37.185921,101.547348],[37.18494,101.54747],[37.184078,101.547211],[37.182579,101.546593],[37.179371,101.547737],[37.177158,101.54882],[37.175419,101.549004],[37.174992,101.54911],[37.173851,101.550056],[37.171951,101.551811],[37.16856,101.555199],[37.16573,101.557533],[37.165051,101.558037],[37.1646,101.558212],[37.16185,101.558594],[37.150612,101.56044],[37.149799,101.560539],[37.148972,101.561523],[37.14526,101.565498],[37.145012,101.565239],[37.144112,101.564613],[37.142639,101.563789],[37.141941,101.563713],[37.141781,101.563766],[37.141171,101.564651],[37.140381,101.568283],[37.140129,101.569633],[37.139511,101.570518],[37.139111,101.570717],[37.13829,101.570168],[37.136162,101.569733],[37.127941,101.568977],[37.120708,101.566162],[37.115791,101.566833],[37.11084,101.566566],[37.11071,101.566589],[37.110439,101.566727],[37.110569,101.566597],[37.110451,101.56649],[37.10928,101.566307],[37.106831,101.565643],[37.10585,101.565697],[37.102749,101.566742],[37.100529,101.56694],[37.10001,101.56694],[37.09763,101.566391],[37.08778,101.565727],[37.084541,101.565201],[37.081539,101.566353],[37.078499,101.568489],[37.076111,101.570312],[37.07375,101.571854],[37.068119,101.575279],[37.06662,101.573463],[37.057621,101.568863],[37.054428,101.567383],[37.04855,101.566383],[37.045929,101.566063],[37.039959,101.569397],[37.038471,101.569267],[37.036831,101.568779],[37.031479,101.56675],[37.030899,101.566673],[37.0303,101.566719],[37.025002,101.56855],[37.023991,101.569206],[37.023399,101.569893],[37.021519,101.573753],[37.020229,101.57666],[37.01791,101.581337],[37.009121,101.59391],[37.005348,101.598343],[37.004761,101.600288],[37.00333,101.606148],[37.001411,101.615402],[37.001499,101.617416],[37.001041,101.619637],[36.99847,101.625504],[36.998131,101.625938],[36.996529,101.62748],[36.988991,101.633797],[36.98806,101.634453],[36.974491,101.64325],[36.96608,101.653717],[36.96159,101.659042],[36.96096,101.659973],[36.950859,101.667549],[36.948372,101.669502],[36.946701,101.670937],[36.943699,101.673103],[36.940811,101.675346],[36.938049,101.677582],[36.934719,101.680923],[36.927681,101.686798],[36.92522,101.689323],[36.92408,101.691132],[36.922691,101.694366],[36.921761,101.6968],[36.919979,101.702789],[36.919071,101.704964],[36.918449,101.706131],[36.916691,101.708611],[36.916679,101.708733],[36.91671,101.708809],[36.916759,101.70887],[36.917049,101.709122],[36.917431,101.709488],[36.91782,101.71003],[36.918171,101.710632],[36.918308,101.711243],[36.918079,101.711983],[36.91766,101.712891],[36.917179,101.713943],[36.916649,101.714989],[36.91605,101.716057],[36.915352,101.717194],[36.914558,101.718353],[36.9137,101.719528],[36.912769,101.720703],[36.911789,101.72187],[36.910728,101.723038],[36.909641,101.724213],[36.908501,101.725403],[36.907349,101.726593],[36.9062,101.727783],[36.905048,101.728996],[36.903889,101.730202],[36.902481,101.731659],[36.901321,101.732872],[36.900169,101.734077],[36.89901,101.735283],[36.89492,101.739517],[36.893959,101.740387],[36.892769,101.741287],[36.89156,101.742027],[36.89032,101.74263],[36.889,101.743149],[36.88768,101.743683],[36.886391,101.744308],[36.885139,101.745033],[36.88385,101.745789],[36.88253,101.746559],[36.88118,101.74736],[36.879841,101.748154],[36.87849,101.748947],[36.87714,101.749786],[36.87339,101.75248],[36.868092,101.756477],[36.866772,101.757263],[36.86541,101.758003],[36.864021,101.758713],[36.85524,101.761681],[36.85376,101.762123],[36.85231,101.762558],[36.850849,101.762993],[36.849369,101.763443],[36.832531,101.766273],[36.821499,101.769531],[36.812901,101.772072],[36.81139,101.772331],[36.758228,101.771317],[36.756771,101.770851],[36.755322,101.770401],[36.753849,101.769951],[36.75116,101.769203],[36.74971,101.768867],[36.748341,101.7686],[36.746971,101.768387],[36.745579,101.768204],[36.744171,101.768021],[36.742722,101.767822],[36.684299,101.766548],[36.68285,101.766586],[36.6814,101.766693],[36.67997,101.7668],[36.6786,101.76696],[36.67728,101.767159],[36.676041,101.767357],[36.6749,101.767563],[36.67384,101.767769],[36.672791,101.767982],[36.671791,101.768181],[36.670921,101.768356],[36.670441,101.768448],[36.670219,101.768509],[36.669899,101.76857],[36.66946,101.768646],[36.6689,101.768784],[36.668201,101.768944],[36.667488,101.769127],[36.66687,101.769287],[36.66642,101.769417],[36.666119,101.769524],[36.665741,101.769691],[36.66518,101.769867],[36.66449,101.770111],[36.663719,101.770401],[36.662949,101.770714],[36.662121,101.771027],[36.661228,101.771378],[36.66024,101.771767],[36.659199,101.772171],[36.658131,101.772583],[36.657089,101.772987],[36.656109,101.773369],[36.655209,101.773781],[36.654449,101.774147],[36.653919,101.774353],[36.653351,101.774567],[36.653011,101.774696],[36.652409,101.774918],[36.651878,101.775124],[36.65136,101.775291],[36.65062,101.775543],[36.6497,101.775574],[36.648708,101.775352],[36.648239,101.774963],[36.648102,101.774643],[36.647961,101.774147],[36.647781,101.773842],[36.647572,101.773697],[36.647209,101.773727],[36.646111,101.774017],[36.644958,101.774422],[36.64172,101.776169],[36.64053,101.776848],[36.640259,101.777359],[36.64035,101.777939],[36.640629,101.778648],[36.640591,101.779846],[36.640331,101.78064],[36.63974,101.782043],[36.639099,101.783524],[36.63863,101.784576],[36.638149,101.785751],[36.637661,101.787308],[36.636921,101.790131],[36.636768,101.790733],[36.636501,101.791649],[36.63623,101.792412],[36.63588,101.793198],[36.635471,101.793922],[36.634838,101.794792],[36.634369,101.795288],[36.63266,101.796669],[36.631969,101.797287],[36.63147,101.797859],[36.630901,101.798683],[36.630348,101.799767],[36.63007,101.800583],[36.629768,101.801903],[36.629539,101.80378],[36.62936,101.804733],[36.629009,101.805862],[36.628529,101.806923],[36.62804,101.807693],[36.627628,101.808243],[36.623409,101.813072],[36.622681,101.814003],[36.622162,101.814781],[36.621712,101.815613],[36.62014,101.818932],[36.619671,101.819687],[36.61898,101.820557],[36.618038,101.82151],[36.616959,101.822289],[36.612671,101.824448],[36.611801,101.824959],[36.610989,101.825569],[36.61042,101.826103],[36.609501,101.82708],[36.605671,101.831581],[36.60498,101.832253],[36.604431,101.832687],[36.603031,101.833603],[36.596249,101.837624],[36.595249,101.838371],[36.594379,101.839287],[36.5938,101.840103],[36.59309,101.841537],[36.592079,101.844223],[36.591572,101.845154],[36.590981,101.845978],[36.58989,101.846977],[36.588341,101.847977],[36.58757,101.848618],[36.58704,101.849213],[36.586411,101.850014],[36.58567,101.851311],[36.583961,101.855827],[36.58371,101.856491],[36.583389,101.857323],[36.582649,101.85907],[36.582081,101.860291],[36.581921,101.860588],[36.581089,101.862213],[36.580181,101.863838],[36.57859,101.866623],[36.578281,101.867188],[36.576771,101.869682],[36.575649,101.871872],[36.57513,101.873138],[36.57481,101.874153],[36.573139,101.879433],[36.572811,101.880302],[36.572319,101.881653],[36.572071,101.882149],[36.571621,101.882858],[36.571098,101.883499],[36.569538,101.885063],[36.568748,101.886147],[36.56823,101.887062],[36.568001,101.887573],[36.56741,101.889587],[36.567242,101.893753],[36.56715,101.89492],[36.566921,101.896339],[36.56657,101.897942],[36.565361,101.90155],[36.565159,101.90213],[36.56501,101.902573],[36.5648,101.903381],[36.564171,101.906937],[36.563869,101.909027],[36.563831,101.90934],[36.563728,101.910263],[36.563499,101.91169],[36.562759,101.915443],[36.562241,101.917618],[36.56118,101.921127],[36.560188,101.923721],[36.559429,101.925407],[36.55801,101.928009],[36.55735,101.929329],[36.556789,101.930763],[36.556438,101.932068],[36.55624,101.933167],[36.556141,101.934288],[36.55595,101.940407],[36.555901,101.941208],[36.555679,101.942772],[36.555401,101.944077],[36.5532,101.952919],[36.552898,101.954018],[36.552471,101.955353],[36.552071,101.956352],[36.551609,101.957291],[36.550812,101.958611],[36.548988,101.960968],[36.5485,101.961594],[36.54364,101.967583],[36.542759,101.968826],[36.54158,101.970863],[36.540878,101.972298],[36.539371,101.975861],[36.538769,101.977127],[36.53796,101.9786],[36.536041,101.981743],[36.535351,101.982986],[36.53484,101.984047],[36.533951,101.986221],[36.532661,101.989998],[36.531658,101.992554],[36.529919,101.9963],[36.527691,102.000778],[36.525009,102.006371],[36.524189,102.008232],[36.52359,102.009804],[36.523079,102.011726],[36.522671,102.013718],[36.522041,102.01722],[36.521339,102.021637],[36.520679,102.025291],[36.520351,102.026657],[36.520031,102.027733],[36.5186,102.031937],[36.51833,102.033043],[36.518169,102.033867],[36.518051,102.034721],[36.517971,102.035873],[36.517879,102.039383],[36.51767,102.041382],[36.51725,102.04335],[36.51638,102.04631],[36.5159,102.048157],[36.515629,102.049507],[36.51543,102.050903],[36.515289,102.052628],[36.51524,102.054077],[36.5154,102.058456],[36.51535,102.060219],[36.515121,102.062248],[36.5144,102.066704],[36.51424,102.067497],[36.514011,102.068283],[36.51366,102.069122],[36.51329,102.069763],[36.512821,102.070381],[36.51405,102.069],[36.514992,102.067719],[36.51535,102.066994],[36.515541,102.066483],[36.515732,102.065666],[36.51582,102.064537],[36.515701,102.062073],[36.51564,102.061752],[36.515499,102.059753],[36.515388,102.061218],[36.515121,102.062866],[36.514889,102.064522],[36.51487,102.066162],[36.515049,102.06778],[36.515442,102.06929],[36.51601,102.070717],[36.51664,102.072037],[36.5172,102.073357],[36.517639,102.074722],[36.517929,102.076103],[36.518059,102.07756],[36.518009,102.079102],[36.517689,102.080673],[36.517288,102.082336],[36.517052,102.084053],[36.51693,102.085716],[36.516819,102.087341],[36.516708,102.088913],[36.516579,102.090446],[36.51646,102.091858],[36.51635,102.093132],[36.516201,102.094276],[36.515961,102.095322],[36.515678,102.096283],[36.515369,102.097137],[36.515072,102.097809],[36.514832,102.098297],[36.514339,102.099182],[36.513672,102.100212],[36.51292,102.10144],[36.5121,102.102783],[36.51125,102.104141],[36.51041,102.105492],[36.50956,102.106888],[36.508709,102.108208],[36.50795,102.109558],[36.507332,102.110977],[36.506771,102.112473],[36.506302,102.113983],[36.505932,102.115494],[36.50565,102.116966],[36.505459,102.118408],[36.505341,102.119873],[36.505291,102.121384],[36.505291,102.122963],[36.505291,102.124634],[36.505291,102.12635],[36.50528,102.128067],[36.505291,102.129753],[36.505291,102.131401],[36.50531,102.133011],[36.505291,102.134583],[36.505219,102.136162],[36.5051,102.137733],[36.504951,102.139252],[36.504768,102.140717],[36.504539,102.142174],[36.504269,102.143677],[36.503948,102.145271],[36.503571,102.146896],[36.503159,102.148529],[36.502682,102.150146],[36.502178,102.151779],[36.50169,102.153442],[36.50119,102.155128],[36.500721,102.156883],[36.50029,102.158699],[36.499939,102.160583],[36.499569,102.162857],[36.499088,102.165863],[36.49881,102.167648],[36.498482,102.16935],[36.498081,102.171013],[36.497581,102.172569],[36.49699,102.174057],[36.4963,102.175423],[36.495522,102.17672],[36.494671,102.178017],[36.493801,102.179337],[36.492939,102.180656],[36.492069,102.181938],[36.491199,102.183212],[36.490349,102.184479],[36.48954,102.185707],[36.488831,102.186958],[36.48822,102.188217],[36.48764,102.189484],[36.487148,102.190773],[36.486759,102.192101],[36.48645,102.193459],[36.486191,102.194839],[36.486019,102.196243],[36.485859,102.197617],[36.485649,102.199074],[36.485439,102.200699],[36.48521,102.202408],[36.485001,102.204178],[36.484791,102.20594],[36.484558,102.207703],[36.484329,102.209351],[36.48407,102.210953],[36.483749,102.212486],[36.483391,102.214043],[36.483021,102.215584],[36.482571,102.21711],[36.482151,102.21859],[36.481731,102.220016],[36.481258,102.221397],[36.480751,102.222717],[36.48024,102.224037],[36.47971,102.225327],[36.47921,102.226562],[36.47876,102.22773],[36.478329,102.228928],[36.478088,102.230209],[36.477921,102.231552],[36.477879,102.232903],[36.477989,102.234261],[36.478088,102.235641],[36.478168,102.237137],[36.47826,102.23877],[36.47839,102.240379],[36.478519,102.241943],[36.47868,102.243439],[36.478882,102.244881],[36.47913,102.246277],[36.479408,102.247627],[36.479759,102.248993],[36.480141,102.25042],[36.480499,102.251892],[36.480862,102.253357],[36.48122,102.254807],[36.481579,102.256302],[36.481979,102.25782],[36.482441,102.259323],[36.48296,102.260757],[36.483471,102.262192],[36.48407,102.263641],[36.484718,102.265106],[36.48539,102.266541],[36.486012,102.267982],[36.48658,102.269432],[36.487011,102.270943],[36.48732,102.272476],[36.48745,102.274063],[36.487461,102.275627],[36.487289,102.277168],[36.486992,102.278641],[36.486599,102.28009],[36.486149,102.281517],[36.48563,102.282944],[36.485119,102.284378],[36.484581,102.285851],[36.4841,102.287376],[36.483749,102.28891],[36.48354,102.290466],[36.483398,102.292061],[36.483471,102.293587],[36.48362,102.29512],[36.48381,102.296677],[36.483978,102.298286],[36.484161,102.299919],[36.484341,102.301567],[36.48452,102.303177],[36.48465,102.304802],[36.484718,102.306412],[36.484749,102.307991],[36.484741,102.309563],[36.484699,102.311142],[36.484612,102.312683],[36.484482,102.314201],[36.484291,102.315689],[36.484081,102.317146],[36.483829,102.31855],[36.483559,102.319923],[36.483261,102.321312],[36.48291,102.322769],[36.482632,102.324226],[36.482399,102.325684],[36.482201,102.327171],[36.482059,102.328697],[36.48196,102.330231],[36.48185,102.331787],[36.48175,102.333397],[36.481651,102.33503],[36.481541,102.336693],[36.481441,102.338341],[36.4813,102.339897],[36.481152,102.341423],[36.48093,102.342857],[36.480652,102.344177],[36.480251,102.345413],[36.47982,102.346573],[36.479279,102.347778],[36.478661,102.348984],[36.477901,102.350281],[36.477112,102.351631],[36.476299,102.352989],[36.475491,102.354332],[36.47472,102.355698],[36.474079,102.357162],[36.473549,102.358688],[36.473122,102.360329],[36.472778,102.361992],[36.472519,102.363678],[36.47226,102.365356],[36.472,102.367058],[36.471741,102.368736],[36.471489,102.370407],[36.471241,102.372093],[36.471001,102.373756],[36.470749,102.375412],[36.47049,102.377068],[36.47023,102.378731],[36.46999,102.380379],[36.46973,102.382027],[36.469398,102.383659],[36.469101,102.385353],[36.468819,102.387062],[36.468571,102.388809],[36.468391,102.390533],[36.468281,102.392227],[36.468201,102.393929],[36.46817,102.395607],[36.46822,102.397293],[36.468311,102.398956],[36.468418,102.400627],[36.46854,102.402298],[36.46867,102.403969],[36.4688,102.405609],[36.468929,102.40728],[36.469059,102.409012],[36.46917,102.410759],[36.46925,102.412483],[36.469299,102.414177],[36.46928,102.415909],[36.469231,102.417641],[36.46909,102.419342],[36.468929,102.421013],[36.468739,102.422737],[36.468529,102.424477],[36.468342,102.426208],[36.468151,102.427872],[36.46796,102.429443],[36.467758,102.430946],[36.467579,102.432426],[36.467388,102.433937],[36.467171,102.435501],[36.466999,102.43705],[36.466881,102.438629],[36.466801,102.440239],[36.466751,102.441872],[36.46674,102.443466],[36.46677,102.445053],[36.466801,102.446579],[36.466801,102.448067],[36.46674,102.449516],[36.466549,102.450996],[36.466309,102.452454],[36.4659,102.453903],[36.465401,102.455292],[36.464828,102.456596],[36.464211,102.457817],[36.463581,102.459007],[36.46294,102.460167],[36.462299,102.461288],[36.461739,102.462334],[36.461151,102.463387],[36.460579,102.464439],[36.45993,102.465591],[36.45916,102.467003],[36.458431,102.468513],[36.457821,102.470093],[36.457352,102.471764],[36.457008,102.473488],[36.456791,102.475258],[36.4566,102.477028],[36.45644,102.47876],[36.456329,102.480461],[36.456181,102.482147],[36.456032,102.483803],[36.455952,102.485474],[36.455891,102.48716],[36.45591,102.488869],[36.455978,102.490601],[36.4561,102.492317],[36.45628,102.494019],[36.456459,102.495728],[36.456589,102.497452],[36.45657,102.499168],[36.456371,102.500893],[36.45607,102.502541],[36.455582,102.504173],[36.45496,102.50576],[36.45438,102.507317],[36.453819,102.508827],[36.453251,102.510307],[36.45274,102.511742],[36.452179,102.513206],[36.451561,102.514618],[36.45089,102.516006],[36.45015,102.517303],[36.44923,102.51857],[36.448299,102.519783],[36.447399,102.520927],[36.446529,102.522049],[36.445629,102.523178],[36.444729,102.524338],[36.443859,102.525436],[36.443008,102.526543],[36.442249,102.52755],[36.44162,102.528481],[36.441051,102.529404],[36.440578,102.530243],[36.440128,102.531029],[36.43969,102.532089],[36.439209,102.533524],[36.438808,102.53508],[36.43853,102.536713],[36.4384,102.53833],[36.438389,102.539978],[36.438499,102.541557],[36.438751,102.543022],[36.439079,102.544373],[36.439468,102.545677],[36.439899,102.546959],[36.44035,102.548233],[36.440811,102.549522],[36.441269,102.550812],[36.441669,102.552162],[36.442009,102.553596],[36.442211,102.555061],[36.442242,102.55658],[36.442051,102.558067],[36.44173,102.559517],[36.441269,102.56089],[36.440651,102.562233],[36.43996,102.563477],[36.439201,102.564728],[36.438412,102.565933],[36.43763,102.567123],[36.43684,102.568329],[36.43605,102.569527],[36.43528,102.570717],[36.43449,102.57193],[36.433681,102.573174],[36.43288,102.574402],[36.432121,102.575684],[36.431419,102.576973],[36.430759,102.578323],[36.430141,102.579697],[36.429531,102.5811],[36.42897,102.582497],[36.428459,102.583946],[36.427971,102.585457],[36.42757,102.587013],[36.4272,102.588516],[36.42683,102.590019],[36.426521,102.591553],[36.426239,102.593063],[36.4259,102.594582],[36.42551,102.596077],[36.425091,102.597572],[36.424599,102.599121],[36.424049,102.60067],[36.423489,102.602203],[36.422932,102.603737],[36.422352,102.605301],[36.42178,102.606827],[36.42123,102.60833],[36.420719,102.609802],[36.420238,102.611267],[36.419849,102.612663],[36.419529,102.614037],[36.419258,102.615433],[36.41898,102.616821],[36.41869,102.618233],[36.418468,102.619659],[36.418301,102.621063],[36.41819,102.622437],[36.41806,102.623863],[36.417931,102.625282],[36.417809,102.626678],[36.41769,102.628036],[36.417568,102.629356],[36.41745,102.630707],[36.417339,102.632027],[36.417221,102.633324],[36.41711,102.63459],[36.417,102.635918],[36.416828,102.637367],[36.416611,102.638893],[36.416279,102.640312],[36.415859,102.641762],[36.415352,102.643158],[36.414768,102.644478],[36.414131,102.645714],[36.413441,102.646812],[36.412739,102.64785],[36.411991,102.648811],[36.411201,102.649727],[36.410412,102.650673],[36.40955,102.651558],[36.40871,102.652481],[36.407871,102.653397],[36.407082,102.65432],[36.406368,102.655373],[36.405788,102.656548],[36.405411,102.657738],[36.405239,102.658928],[36.40517,102.660103],[36.405258,102.661217],[36.405491,102.662277],[36.4058,102.663422],[36.406132,102.664673],[36.406269,102.666008],[36.40617,102.667488],[36.405979,102.668938],[36.405548,102.670311],[36.40501,102.6716],[36.404251,102.672897],[36.4034,102.674133],[36.402451,102.675148],[36.401409,102.675972],[36.400311,102.676628],[36.399181,102.677101],[36.398029,102.677467],[36.396889,102.677834],[36.395802,102.678284],[36.364868,102.688026],[36.36396,102.688309],[36.362999,102.688637],[36.362,102.68911],[36.361,102.689774],[36.3601,102.690628],[36.35936,102.691597],[36.358742,102.692703],[36.358269,102.693863],[36.357868,102.695084],[36.357529,102.696289],[36.357231,102.69751],[36.356941,102.698799],[36.35667,102.700218],[36.356491,102.701668],[36.356461,102.703102],[36.35659,102.704483],[36.356838,102.70578],[36.357239,102.707047],[36.357792,102.708229],[36.358471,102.709267],[36.35918,102.710274],[36.35981,102.711349],[36.360279,102.71257],[36.360569,102.713837],[36.36071,102.715134],[36.360661,102.716423],[36.360439,102.717644],[36.360062,102.718781],[36.35965,102.720009],[36.3591,102.721207],[36.35844,102.722366],[36.357651,102.723473],[36.356758,102.724503],[36.355801,102.725403],[36.354801,102.726173],[36.35376,102.726898],[36.35268,102.727661],[36.351768,102.728653],[36.351051,102.729797],[36.350521,102.731071],[36.350109,102.732437],[36.349739,102.73391],[36.349369,102.735382],[36.348991,102.736839],[36.348671,102.738258],[36.348381,102.739609],[36.347988,102.741013],[36.34753,102.742332],[36.34005,102.754784],[36.339161,102.755432],[36.338169,102.756142],[36.33712,102.75695],[36.33596,102.757759],[36.334949,102.758667],[36.334141,102.75975],[36.33358,102.760887],[36.33321,102.76194],[36.332981,102.762993],[36.332859,102.764],[36.332878,102.765083],[36.333118,102.766228],[36.333401,102.767479],[36.333641,102.76873],[36.333832,102.77002],[36.33387,102.771461],[36.333691,102.773102],[36.333351,102.774803],[36.333031,102.776466],[36.33279,102.778137],[36.332611,102.779831],[36.33255,102.781532],[36.332619,102.783272],[36.332779,102.784943],[36.333,102.786591],[36.333241,102.788223],[36.333469,102.789871],[36.33371,102.791519],[36.333961,102.793167],[36.334221,102.794807],[36.334469,102.796463],[36.334751,102.798119],[36.335018,102.799782],[36.33527,102.80146],[36.335522,102.803047],[36.335701,102.804604],[36.335709,102.806122],[36.335571,102.80764],[36.33527,102.809128],[36.334789,102.810516],[36.33424,102.811836],[36.333691,102.813164],[36.333199,102.814468],[36.332821,102.815819],[36.33255,102.817177],[36.332378,102.818512],[36.332352,102.819801],[36.332409,102.821037],[36.332481,102.82225],[36.332569,102.823647],[36.33268,102.825363],[36.332802,102.827103],[36.33292,102.828842],[36.333038,102.830582],[36.33316,102.832314],[36.333271,102.834053],[36.333302,102.83577],[36.333069,102.837486],[36.332649,102.839211],[36.332062,102.840851],[36.331589,102.842529],[36.331371,102.844269],[36.33147,102.846001],[36.331718,102.847679],[36.332001,102.849373],[36.33226,102.851051],[36.332458,102.852707],[36.332451,102.854446],[36.33223,102.856232],[36.331841,102.85791],[36.331322,102.859482],[36.330509,102.860924],[36.32962,102.862282],[36.328651,102.863586],[36.327679,102.864929],[36.326698,102.866257],[36.325729,102.867592],[36.32476,102.868896],[36.323879,102.87027],[36.323071,102.871727],[36.322418,102.873322],[36.321899,102.874947],[36.321522,102.87661],[36.32122,102.878304],[36.32093,102.879982],[36.32061,102.881683],[36.32021,102.883362],[36.319729,102.885094],[36.31918,102.886726],[36.318581,102.888237],[36.31789,102.889702],[36.31715,102.891113],[36.31636,102.892509],[36.31546,102.893852],[36.31448,102.895157],[36.313461,102.896408],[36.312439,102.897636],[36.311409,102.898888],[36.310379,102.900078],[36.309341,102.901283],[36.308311,102.902496],[36.30732,102.903763],[36.3064,102.905037],[36.305618,102.906418],[36.304939,102.907898],[36.304379,102.90947],[36.30394,102.91111],[36.303631,102.912811],[36.303459,102.914543],[36.303349,102.916283],[36.303249,102.918022],[36.303169,102.919777],[36.303082,102.921577],[36.30299,102.923393],[36.302891,102.925148],[36.302811,102.926842],[36.302719,102.928467],[36.30275,102.930069],[36.302879,102.931648],[36.30307,102.933121],[36.303219,102.934509],[36.303249,102.935883],[36.303261,102.937149],[36.303242,102.938301],[36.303188,102.939346],[36.30312,102.940231],[36.302509,102.94854],[36.302429,102.949707],[36.302299,102.951012],[36.302052,102.952461],[36.30167,102.954018],[36.301109,102.95565],[36.300381,102.957191],[36.29958,102.958641],[36.298752,102.96006],[36.297901,102.961487],[36.297039,102.962936],[36.296181,102.964371],[36.29533,102.96582],[36.29446,102.967308],[36.293629,102.968842],[36.292938,102.970451],[36.292339,102.972061],[36.291771,102.973679],[36.291199,102.975304],[36.290668,102.976952],[36.290089,102.978577],[36.289429,102.980171],[36.288651,102.981689],[36.287769,102.983124],[36.286812,102.984482],[36.285789,102.985733],[36.284691,102.986877],[36.283539,102.987923],[36.282318,102.988853],[36.281071,102.989723],[36.279819,102.990578],[36.278629,102.991524],[36.2775,102.992592],[36.276402,102.993752],[36.275372,102.994957],[36.274429,102.99633],[36.273571,102.99781],[36.272812,102.999336],[36.27206,103.000877],[36.271278,103.002441],[36.2705,103.004028],[36.26984,103.0056],[36.269218,103.007156],[36.268581,103.008713],[36.267792,103.010246],[36.267071,103.011818],[36.266232,103.013313],[36.265228,103.014641],[36.264111,103.015762],[36.262798,103.016663],[36.26141,103.017357],[36.26004,103.017838],[36.258659,103.018257],[36.257309,103.018677],[36.255932,103.019127],[36.25457,103.019524],[36.25322,103.019897],[36.251839,103.020363],[36.250542,103.02108],[36.249359,103.022057],[36.248291,103.023262],[36.247379,103.024658],[36.24667,103.026222],[36.245949,103.027779],[36.245079,103.029182],[36.24408,103.030457],[36.243038,103.031708],[36.241989,103.032951],[36.240891,103.034233],[36.23983,103.035477],[36.23877,103.03672],[36.237789,103.037971],[36.236752,103.039223],[36.23576,103.040527],[36.234989,103.04203],[36.234489,103.043694],[36.234299,103.045448],[36.23436,103.047256],[36.234612,103.049057],[36.234859,103.050789],[36.234909,103.052551],[36.234669,103.054314],[36.23418,103.055977],[36.233521,103.057579],[36.232681,103.059013],[36.2318,103.060432],[36.230919,103.061852],[36.230049,103.063278],[36.229179,103.064713],[36.228291,103.066116],[36.227409,103.067543],[36.226589,103.068893],[36.225819,103.070343],[36.225121,103.071907],[36.224529,103.073502],[36.223999,103.075157],[36.22348,103.076859],[36.223,103.07856],[36.222569,103.080292],[36.22208,103.081963],[36.2215,103.083603],[36.22084,103.085167],[36.220119,103.08667],[36.219379,103.088173],[36.218639,103.089668],[36.217918,103.091179],[36.21722,103.092697],[36.21656,103.094208],[36.215981,103.095863],[36.2155,103.09758],[36.215191,103.099319],[36.214958,103.101059],[36.21476,103.102783],[36.214439,103.104477],[36.213909,103.106148],[36.21312,103.107712],[36.21209,103.1091],[36.211048,103.11039],[36.210018,103.111679],[36.20903,103.112991],[36.208172,103.114464],[36.207531,103.116043],[36.207211,103.117798],[36.207008,103.119583],[36.206829,103.121361],[36.206631,103.123161],[36.206459,103.124924],[36.20628,103.126694],[36.2061,103.128464],[36.205921,103.130234],[36.205811,103.132004],[36.20578,103.133774],[36.205841,103.135551],[36.205971,103.137329],[36.20612,103.139122],[36.206249,103.140907],[36.206322,103.142693],[36.206268,103.144447],[36.206039,103.146172],[36.205601,103.147781],[36.205009,103.1493],[36.204239,103.150772],[36.20332,103.152107],[36.202358,103.153252],[36.201359,103.154373],[36.200371,103.155518],[36.199459,103.156754],[36.198689,103.158157],[36.198021,103.159721],[36.19754,103.161339],[36.197262,103.163033],[36.197151,103.164787],[36.19722,103.166573],[36.197369,103.168312],[36.19754,103.170013],[36.197659,103.171692],[36.197681,103.173317],[36.19746,103.174927],[36.197029,103.176422],[36.196381,103.177856],[36.19553,103.179077],[36.194611,103.180206],[36.193699,103.18132],[36.192829,103.182426],[36.191952,103.183563],[36.191071,103.184753],[36.190231,103.185966],[36.189449,103.187233],[36.188648,103.188507],[36.187698,103.189781],[36.186691,103.190971],[36.18565,103.192047],[36.184521,103.193123],[36.18338,103.194138],[36.18224,103.195129],[36.18108,103.196098],[36.180031,103.197189],[36.17907,103.198433],[36.17823,103.199791],[36.177589,103.201393],[36.17709,103.203041],[36.176739,103.204681],[36.176399,103.206306],[36.17598,103.207893],[36.17548,103.209412],[36.174858,103.210854],[36.174191,103.212288],[36.173538,103.213852],[36.172989,103.2155],[36.172649,103.217247],[36.172531,103.219101],[36.172668,103.221329],[36.172939,103.22316],[36.173222,103.224876],[36.1735,103.226547],[36.173752,103.228127],[36.173939,103.229721],[36.174179,103.231247],[36.174438,103.232758],[36.174648,103.234306],[36.174759,103.235893],[36.17474,103.237457],[36.17469,103.239113],[36.174622,103.240784],[36.1745,103.242447],[36.174511,103.244179],[36.174648,103.245949],[36.17495,103.247719],[36.175381,103.249428],[36.175941,103.251106],[36.176579,103.252762],[36.177219,103.254372],[36.177799,103.255951],[36.178169,103.257561],[36.178371,103.259117],[36.178391,103.260643],[36.178268,103.262154],[36.178009,103.263657],[36.177662,103.26506],[36.177181,103.266342],[36.176559,103.267609],[36.175961,103.268806],[36.175381,103.269981],[36.17482,103.271133],[36.174301,103.27227],[36.17384,103.273376],[36.17345,103.274384],[36.173161,103.275284],[36.172939,103.27607],[36.172798,103.276749],[36.17268,103.277298],[36.172619,103.277718],[36.172619,103.278023],[36.17255,103.278267],[36.172482,103.278526],[36.172138,103.279694],[36.172081,103.279877],[36.171959,103.280159],[36.171791,103.280441],[36.17173,103.280579],[36.171711,103.280663],[36.171661,103.280769],[36.171638,103.280807],[36.1716,103.280853],[36.171551,103.280937],[36.171391,103.281303],[36.17112,103.282066],[36.170689,103.283333],[36.170292,103.284767],[36.170071,103.286293],[36.169991,103.287849],[36.170078,103.289436],[36.1702,103.291023],[36.170231,103.29258],[36.170151,103.293983],[36.169941,103.295372],[36.169571,103.296951],[36.16851,103.305054],[36.168419,103.306953],[36.16827,103.308723],[36.16785,103.310417],[36.167179,103.311996],[36.166271,103.313431],[36.16523,103.314774],[36.1642,103.316132],[36.163361,103.317711],[36.163029,103.31881],[36.162781,103.320084],[36.162498,103.325623],[36.162251,103.328667],[36.161888,103.330269],[36.161179,103.332024],[36.16016,103.333656],[36.157082,103.338173],[36.155689,103.340042],[36.154961,103.340767],[36.153721,103.341583],[36.148899,103.343163],[36.148109,103.343552],[36.1474,103.344063],[36.14653,103.344963],[36.142269,103.350891],[36.141861,103.351784],[36.141548,103.352837],[36.141392,103.353622],[36.141312,103.354942],[36.141312,103.356323],[36.141521,103.3582],[36.142639,103.366814],[36.14333,103.372566],[36.14349,103.37439],[36.143551,103.378151],[36.14362,103.380043],[36.143951,103.382278],[36.144451,103.38401],[36.145111,103.385612],[36.15411,103.398842],[36.155128,103.400093],[36.15612,103.401283],[36.157051,103.402473],[36.15781,103.403847],[36.158379,103.405357],[36.158821,103.406967],[36.159088,103.408684],[36.159321,103.410454],[36.159531,103.412643],[36.159882,103.414429],[36.16058,103.416023],[36.161499,103.417427],[36.16264,103.418617],[36.163952,103.419487],[36.165371,103.420067],[36.166809,103.420593],[36.168251,103.421089],[36.169708,103.421608],[36.17115,103.422272],[36.172501,103.423119],[36.173721,103.424263],[36.174858,103.425537],[36.175659,103.427223],[36.176361,103.429291],[36.176991,103.431534],[36.177189,103.432838],[36.177212,103.434021],[36.17717,103.434967],[36.17688,103.436829],[36.17598,103.441719],[36.175621,103.44455],[36.175591,103.446701],[36.176281,103.450691],[36.176701,103.452438],[36.177071,103.454086],[36.177361,103.455711],[36.17746,103.457237],[36.177158,103.456787],[36.176998,103.456589],[36.1768,103.456467],[36.176449,103.456459],[36.176331,103.456612],[36.17625,103.456818],[36.176201,103.457039],[36.176231,103.457268],[36.176331,103.457474],[36.176491,103.457603],[36.176689,103.457733],[36.17691,103.457787],[36.177349,103.458008],[36.177731,103.458298],[36.17804,103.458687],[36.178211,103.459213],[36.178299,103.459747],[36.178322,103.460243],[36.17831,103.460457],[36.178242,103.460709],[36.178249,103.46109],[36.177689,103.462067],[36.177311,103.462547],[36.1772,103.462738],[36.177109,103.462982],[36.17701,103.463928],[36.176899,103.464378],[36.1768,103.4645],[36.175251,103.465729],[36.174911,103.467194],[36.17487,103.467773],[36.174591,103.469757],[36.174309,103.470833],[36.174229,103.471077],[36.173988,103.471497],[36.173538,103.471733],[36.174229,103.471489],[36.17416,103.471832],[36.173969,103.472],[36.173069,103.475014],[36.171669,103.478172],[36.171021,103.480209],[36.170811,103.482384],[36.170441,103.482681],[36.169361,103.482674],[36.168732,103.482658],[36.167721,103.482674],[36.167332,103.482841],[36.16708,103.483437],[36.16634,103.486961],[36.165279,103.491341],[36.164589,103.493446],[36.163799,103.494377],[36.162411,103.495079],[36.155079,103.497543],[36.15213,103.498734],[36.151791,103.49884],[36.14447,103.500648],[36.14299,103.501266],[36.142841,103.501373],[36.141708,103.502586],[36.14072,103.503593],[36.14006,103.504601],[36.138741,103.508942],[36.138149,103.511543],[36.137932,103.513313],[36.138039,103.518738],[36.138,103.522591],[36.137661,103.524048],[36.136459,103.526466],[36.136051,103.526978],[36.13266,103.529221],[36.12867,103.530296],[36.123032,103.531723],[36.122059,103.532089],[36.11982,103.533241],[36.116169,103.535553],[36.115021,103.53627],[36.11412,103.537117],[36.11311,103.538673],[36.11042,103.545486],[36.109219,103.548241],[36.1087,103.550247],[36.108509,103.552002],[36.108749,103.556358],[36.108971,103.55764],[36.109459,103.559082],[36.1115,103.562927],[36.11195,103.564087],[36.111801,103.564117],[36.11142,103.564163],[36.11076,103.564323],[36.109909,103.56456],[36.109112,103.56485],[36.10836,103.565163],[36.10775,103.56543],[36.10733,103.565666],[36.10696,103.566017],[36.10664,103.566307],[36.10622,103.566803],[36.105869,103.566978],[36.105518,103.566887],[36.105099,103.56665],[36.104721,103.566406],[36.104382,103.566269],[36.104061,103.566223],[36.10379,103.566322],[36.1035,103.566559],[36.103199,103.566811],[36.10268,103.567261],[36.101822,103.567711],[36.100868,103.568237],[36.10009,103.569122],[36.09935,103.569992],[36.09861,103.57077],[36.098011,103.571213],[36.097469,103.571411],[36.096951,103.571587],[36.096409,103.571777],[36.095909,103.57196],[36.09539,103.572144],[36.09481,103.572159],[36.0942,103.572037],[36.09362,103.571877],[36.093029,103.571693],[36.092361,103.571571],[36.091492,103.57151],[36.09053,103.571442],[36.089512,103.571136],[36.088509,103.570709],[36.08754,103.570297],[36.086658,103.569923],[36.085831,103.569489],[36.085011,103.568947],[36.08429,103.568451],[36.08358,103.568001],[36.08279,103.567543],[36.081951,103.567322],[36.08112,103.567436],[36.080292,103.567734],[36.07943,103.567833],[36.078571,103.567574],[36.077759,103.567329],[36.077,103.567253],[36.076241,103.567482],[36.075581,103.568031],[36.074841,103.568703],[36.074081,103.569122],[36.07338,103.569473],[36.07267,103.569794],[36.071899,103.57016],[36.071281,103.570473],[36.07069,103.570763],[36.070011,103.570992],[36.069382,103.570869],[36.06881,103.570473],[36.06813,103.569923],[36.067268,103.569206],[36.06641,103.56852],[36.065659,103.56781],[36.065121,103.567162],[36.06464,103.566566],[36.064171,103.566093],[36.063671,103.565788],[36.06316,103.565529],[36.062641,103.565269],[36.062092,103.564987],[36.06168,103.564552],[36.061611,103.563751],[36.061699,103.562576],[36.061779,103.561279],[36.061821,103.56012],[36.06144,103.559196],[36.060928,103.558563],[36.060329,103.558067],[36.05983,103.557602],[36.059681,103.556778],[36.05991,103.555649],[36.060169,103.55442],[36.06041,103.553177],[36.060741,103.552063],[36.061352,103.55098],[36.061878,103.549911],[36.062229,103.54892],[36.062469,103.547882],[36.062538,103.546783],[36.062408,103.54567],[36.062168,103.544594],[36.061852,103.543556],[36.061321,103.54274],[36.060532,103.542427],[36.0597,103.542511],[36.058929,103.542641],[36.05827,103.542763],[36.057571,103.542877],[36.05674,103.54303],[36.055882,103.543091],[36.054989,103.543007],[36.054211,103.543007],[36.053532,103.54306],[36.05267,103.54364],[36.05183,103.544357],[36.051189,103.544891],[36.050709,103.545082],[36.050079,103.544983],[36.04929,103.544731],[36.048359,103.544601],[36.047379,103.544884],[36.04657,103.545647],[36.04586,103.546608],[36.045101,103.547447],[36.044239,103.547958],[36.043221,103.548027],[36.04221,103.547821],[36.041279,103.547829],[36.04044,103.548058],[36.039669,103.548241],[36.039051,103.548279],[36.03828,103.548019],[36.037239,103.548073],[36.036171,103.548233],[36.035,103.548187],[36.03418,103.548042],[36.033569,103.547798],[36.033138,103.547546],[36.03281,103.547379],[36.032139,103.547073],[36.0313,103.546738],[36.03046,103.546089],[36.029499,103.545258],[36.028412,103.544601],[36.027321,103.544006],[36.02631,103.543457],[36.02544,103.543007],[36.0247,103.543068],[36.024109,103.543259],[36.023312,103.542931],[36.0224,103.542397],[36.021481,103.541931],[36.02066,103.541771],[36.01923,103.541351],[36.01841,103.540916],[36.017712,103.540497],[36.01722,103.540237],[36.01685,103.53994],[36.016548,103.539543],[36.0163,103.538963],[36.01622,103.538322],[36.016319,103.537514],[36.016602,103.536491],[36.016899,103.535431],[36.017239,103.534363],[36.01749,103.533386],[36.01749,103.532539],[36.017208,103.531807],[36.0168,103.531281],[36.016399,103.530853],[36.016022,103.53038],[36.015701,103.529823],[36.015511,103.529167],[36.015419,103.528473],[36.015541,103.527573],[36.015862,103.526611],[36.01627,103.525742],[36.01672,103.524986],[36.0172,103.524429],[36.01767,103.52401],[36.01828,103.523903],[36.019169,103.524139],[36.020119,103.524406],[36.02108,103.524277],[36.0219,103.523712],[36.02269,103.523102],[36.023571,103.522758],[36.02457,103.522697],[36.025539,103.52256],[36.026371,103.522072],[36.027069,103.521233],[36.027729,103.520287],[36.028469,103.519417],[36.02932,103.518646],[36.03019,103.517883],[36.031052,103.517113],[36.031799,103.516441],[36.032398,103.515793],[36.032879,103.514977],[36.033272,103.514061],[36.033539,103.513077],[36.033741,103.512009],[36.034111,103.510986],[36.034561,103.509987],[36.03484,103.508858],[36.034859,103.507698],[36.034721,103.506607],[36.034519,103.505722],[36.03434,103.504883],[36.03421,103.503868],[36.034302,103.502808],[36.034489,103.501747],[36.034618,103.500687],[36.034512,103.499649],[36.034328,103.498642],[36.034161,103.49765],[36.03397,103.496681],[36.033791,103.495697],[36.033691,103.494698],[36.033852,103.493683],[36.0341,103.492653],[36.034271,103.491653],[36.034851,103.490936],[36.03537,103.490097],[36.0355,103.489067],[36.035511,103.488098],[36.035259,103.487198],[36.03503,103.486282],[36.035271,103.48539],[36.035851,103.48455],[36.03611,103.483437],[36.036289,103.482193],[36.036461,103.480927],[36.03656,103.479729],[36.036449,103.478622],[36.036308,103.477608],[36.036549,103.476707],[36.037239,103.476028],[36.03809,103.475502],[36.0438,103.472023],[36.044491,103.471581],[36.044979,103.47113],[36.04533,103.470642],[36.045639,103.469948],[36.045769,103.469147],[36.045811,103.468369],[36.04591,103.467506],[36.046101,103.466667],[36.046398,103.46582],[36.046768,103.464973],[36.047211,103.464149],[36.04768,103.463463],[36.048019,103.462967],[36.048401,103.462517],[36.048851,103.461937],[36.04937,103.461304],[36.04995,103.460564],[36.050499,103.459877],[36.051048,103.45919],[36.05164,103.458443],[36.052231,103.457718],[36.052872,103.456917],[36.053539,103.455994],[36.05407,103.454971],[36.054401,103.45388],[36.054588,103.452766],[36.054691,103.451637],[36.054779,103.450531],[36.054981,103.449379],[36.055248,103.44809],[36.055519,103.446823],[36.055759,103.445663],[36.055969,103.444656],[36.055969,103.443802],[36.05571,103.442848],[36.055401,103.441811],[36.05508,103.44072],[36.05476,103.439629],[36.05444,103.438599],[36.054131,103.437607],[36.053871,103.436653],[36.053699,103.435631],[36.0536,103.434662],[36.053501,103.4338],[36.053391,103.43293],[36.053249,103.431831],[36.053051,103.43071],[36.052872,103.429764],[36.052731,103.428963],[36.052608,103.428207],[36.052471,103.427383],[36.052349,103.426514],[36.052189,103.425667],[36.051991,103.424957],[36.0518,103.424332],[36.051609,103.42366],[36.051411,103.422951],[36.051151,103.422188],[36.05072,103.421577],[36.05019,103.42115],[36.049648,103.420738],[36.04911,103.420326],[36.048531,103.419884],[36.047852,103.419342],[36.047081,103.418777],[36.046211,103.418312],[36.04528,103.417999],[36.044319,103.417847],[36.043331,103.41774],[36.042358,103.417633],[36.041401,103.417557],[36.040531,103.417473],[36.039688,103.417389],[36.038879,103.417313],[36.038071,103.417229],[36.037331,103.417152],[36.036671,103.417038],[36.03606,103.416924],[36.03553,103.416801],[36.03513,103.416687],[36.034931,103.416634],[36.034752,103.416557],[36.033508,103.416237],[36.032879,103.416054],[36.032101,103.415817],[36.031219,103.415558],[36.030369,103.41526],[36.029572,103.414803],[36.028801,103.414139],[36.028091,103.413544],[36.02739,103.413071],[36.026649,103.412933],[36.02597,103.413177],[36.02533,103.41362],[36.0247,103.41407],[36.02409,103.414139],[36.02359,103.41378],[36.02317,103.413292],[36.02272,103.41275],[36.022209,103.412132],[36.02158,103.411392],[36.020859,103.410553],[36.020149,103.409683],[36.01939,103.40892],[36.01857,103.408272],[36.0177,103.407707],[36.016781,103.407303],[36.01585,103.406937],[36.014961,103.406616],[36.01416,103.406326],[36.013451,103.405968],[36.012798,103.40535],[36.012291,103.404457],[36.01181,103.40332],[36.011269,103.402077],[36.010719,103.400902],[36.010208,103.39978],[36.00972,103.398743],[36.009071,103.397873],[36.008339,103.397087],[36.007671,103.396378],[36.00716,103.395576],[36.006851,103.394493],[36.00663,103.393227],[36.006371,103.391907],[36.005951,103.390648],[36.005299,103.389511],[36.004532,103.388588],[36.003651,103.387939],[36.002659,103.387642],[36.00169,103.387741],[36.000679,103.387947],[35.99968,103.388184],[35.99876,103.388367],[35.99791,103.388344],[35.997021,103.387993],[35.996109,103.387543],[35.995152,103.387077],[35.994228,103.386673],[35.99342,103.386421],[35.99268,103.38665],[35.992088,103.38726],[35.99144,103.387802],[35.990589,103.388161],[35.989651,103.388153],[35.98872,103.387917],[35.98782,103.38755],[35.98695,103.387047],[35.986061,103.386543],[35.985241,103.386017],[35.984661,103.385193],[35.984119,103.384323],[35.983421,103.383781],[35.982712,103.383301],[35.982182,103.382423],[35.981739,103.38134],[35.981319,103.380302],[35.980881,103.379242],[35.98045,103.378166],[35.98003,103.377159],[35.979622,103.376213],[35.979359,103.375229],[35.979252,103.374123],[35.978951,103.373123],[35.97839,103.372238],[35.977871,103.371323],[35.977631,103.370201],[35.977291,103.369133],[35.9767,103.36837],[35.9762,103.367844],[35.975719,103.367332],[35.975201,103.366882],[35.974529,103.366463],[35.973789,103.365952],[35.97324,103.365128],[35.97274,103.364227],[35.97226,103.363327],[35.971748,103.362427],[35.970909,103.361908],[35.96991,103.361443],[35.968899,103.360977],[35.967949,103.360443],[35.96703,103.359848],[35.966141,103.359261],[35.96529,103.358704],[35.964481,103.358124],[35.963871,103.357224],[35.963322,103.35611],[35.962742,103.355072],[35.96204,103.354179],[35.96133,103.353317],[35.96072,103.352547],[35.960159,103.351891],[35.959671,103.351433],[35.959,103.350822],[35.958199,103.350197],[35.957401,103.349541],[35.9566,103.3489],[35.955761,103.34832],[35.954899,103.347893],[35.95401,103.347527],[35.953079,103.347183],[35.952209,103.346848],[35.951519,103.346367],[35.951019,103.345596],[35.95052,103.344849],[35.949871,103.344421],[35.94907,103.344223],[35.948292,103.344101],[35.947639,103.344002],[35.946999,103.343887],[35.946301,103.343773],[35.945591,103.343651],[35.944809,103.343529],[35.944,103.343323],[35.943291,103.342857],[35.942692,103.342148],[35.942131,103.341408],[35.94154,103.340843],[35.940899,103.340607],[35.94035,103.340424],[35.93993,103.34037],[35.939491,103.340332],[35.938862,103.340317],[35.938301,103.340363],[35.937832,103.340408],[35.937439,103.340424],[35.93705,103.340431],[35.936581,103.340317],[35.936211,103.339737],[35.93605,103.339012],[35.93589,103.338287],[35.935741,103.337608],[35.935551,103.336746],[35.93536,103.335999],[35.935181,103.33535],[35.93491,103.334801],[35.934639,103.334183],[35.934662,103.333519],[35.93483,103.332878],[35.934952,103.332329],[35.93502,103.331711],[35.934879,103.331123],[35.934502,103.330612],[35.934231,103.330093],[35.934292,103.329514],[35.934471,103.328979],[35.934689,103.328453],[35.934959,103.327942],[35.93523,103.327438],[35.935558,103.326881],[35.935928,103.326302],[35.936329,103.325996],[35.93676,103.325882],[35.937099,103.325798],[35.93716,103.325638],[35.93689,103.325508],[35.9366,103.325447],[35.936371,103.325523],[35.936001,103.325783],[35.935661,103.326157],[35.93544,103.326553],[35.93528,103.326714],[35.935001,103.326576],[35.934631,103.32637],[35.934261,103.326149],[35.934132,103.325859],[35.93417,103.32534],[35.93425,103.324707],[35.93433,103.324173],[35.934429,103.323708],[35.934502,103.323181],[35.93457,103.322563],[35.934631,103.321854],[35.934711,103.32106],[35.934811,103.320267],[35.934879,103.319504],[35.934971,103.318771],[35.934929,103.318176],[35.934952,103.317688],[35.934898,103.317123],[35.934818,103.316391],[35.934792,103.315918],[35.934799,103.315819],[35.93449,103.315529],[35.934021,103.3153],[35.933731,103.315079],[35.9333,103.314484],[35.932991,103.314209],[35.93206,103.31369],[35.931179,103.313438],[35.93055,103.31308],[35.93045,103.312927],[35.930561,103.31279],[35.931301,103.312927],[35.931931,103.312729],[35.932541,103.312851],[35.93264,103.312767],[35.932671,103.312683],[35.93259,103.312553],[35.932251,103.312363],[35.93095,103.312019],[35.93042,103.3116],[35.93021,103.311493],[35.93,103.311501],[35.929619,103.311707],[35.92934,103.311974],[35.929199,103.31218],[35.929001,103.312714],[35.92902,103.312897],[35.929161,103.313431],[35.929131,103.313599],[35.92905,103.31369],[35.92836,103.313927],[35.928131,103.313873],[35.92802,103.313766],[35.927731,103.313408],[35.92757,103.313408],[35.927471,103.313507],[35.927441,103.313728],[35.92749,103.313828],[35.92778,103.314056],[35.92786,103.31427],[35.927811,103.3144],[35.927441,103.314796],[35.927219,103.315201],[35.92659,103.316589],[35.92635,103.317291],[35.92606,103.31871],[35.925869,103.31913],[35.925659,103.319351],[35.921909,103.322456],[35.921421,103.322708],[35.921211,103.322723],[35.920971,103.322647],[35.9207,103.322456],[35.92025,103.321831],[35.91988,103.321548],[35.919651,103.321533],[35.9193,103.3218],[35.91909,103.3218],[35.918961,103.321693],[35.918789,103.321426],[35.91853,103.320938],[35.91827,103.320763],[35.918091,103.320763],[35.917961,103.320847],[35.917641,103.321823],[35.917561,103.321907],[35.917419,103.321968],[35.917191,103.321877],[35.91679,103.321487],[35.916691,103.321449],[35.916561,103.321487],[35.916161,103.3218],[35.915901,103.321831],[35.914989,103.321136],[35.914841,103.321091],[35.914459,103.321136],[35.913651,103.321487],[35.913311,103.321579],[35.912979,103.321579],[35.912811,103.321503],[35.912701,103.321327],[35.912571,103.320686],[35.912449,103.320587],[35.91235,103.320618],[35.912251,103.320877],[35.912121,103.321709],[35.91201,103.322006],[35.911621,103.322807],[35.911381,103.32312],[35.911091,103.323288],[35.910511,103.323349],[35.90971,103.323288],[35.909481,103.32338],[35.909069,103.323914],[35.90884,103.324318],[35.908539,103.325203],[35.908451,103.325363],[35.907921,103.325851],[35.907841,103.326057],[35.907871,103.326271],[35.908291,103.327103],[35.908451,103.327797],[35.90844,103.328041],[35.90834,103.328178],[35.90797,103.328407],[35.9076,103.328377],[35.90731,103.328247],[35.907181,103.32814],[35.906361,103.327087],[35.906281,103.326759],[35.90596,103.326157],[35.905769,103.326073],[35.904621,103.32605],[35.90448,103.325974],[35.90419,103.325638],[35.904121,103.32547],[35.903931,103.323669],[35.90382,103.323341],[35.9034,103.322639],[35.903271,103.322327],[35.903221,103.322166],[35.903141,103.321648],[35.903191,103.321518],[35.90332,103.321419],[35.903751,103.321373],[35.90398,103.32122],[35.90406,103.321098],[35.904079,103.320961],[35.904041,103.320587],[35.903931,103.320419],[35.903801,103.320358],[35.90366,103.320343],[35.90303,103.320427],[35.902809,103.320297],[35.90266,103.32],[35.90202,103.318047],[35.90184,103.317719],[35.9016,103.317497],[35.899841,103.318741],[35.89954,103.320923],[35.899841,103.321854],[35.899891,103.322159],[35.899761,103.32328],[35.899811,103.323608],[35.900421,103.324417],[35.900829,103.325241],[35.90099,103.325394],[35.901291,103.325539],[35.901581,103.325768],[35.902,103.326828],[35.902531,103.327347],[35.90313,103.328468],[35.903351,103.329033],[35.903721,103.329483],[35.90395,103.330208],[35.903961,103.330566],[35.903881,103.330856],[35.903931,103.331078],[35.90419,103.331284],[35.90443,103.33165],[35.904701,103.331947],[35.905319,103.332397],[35.905491,103.332619],[35.905651,103.333023],[35.90554,103.333847],[35.905609,103.334068],[35.90588,103.334503],[35.9062,103.334747],[35.907101,103.335007],[35.907181,103.335159],[35.907181,103.335693],[35.907219,103.335777],[35.907341,103.335876],[35.90757,103.335876],[35.90773,103.335777],[35.907879,103.335617],[35.908119,103.33519],[35.908291,103.335121],[35.90839,103.335159],[35.908779,103.33548],[35.909451,103.335854],[35.90955,103.335991],[35.90955,103.336067],[35.90942,103.336571],[35.90942,103.336723],[35.909931,103.337753],[35.90995,103.338097],[35.90974,103.338676],[35.909679,103.33876],[35.90918,103.339058],[35.908791,103.339523],[35.908291,103.339897],[35.9081,103.339897],[35.907909,103.339653],[35.90773,103.339607],[35.9076,103.339737],[35.907501,103.340157],[35.907391,103.340317],[35.906929,103.340553],[35.90678,103.3405],[35.90641,103.34005],[35.906231,103.340027],[35.905979,103.340157],[35.90591,103.340218],[35.90575,103.340828],[35.9053,103.341309],[35.905121,103.341347],[35.904881,103.341309],[35.904751,103.3414],[35.904411,103.342293],[35.9039,103.343323],[35.903801,103.343407],[35.903419,103.343559],[35.902191,103.343681],[35.90147,103.343674],[35.901081,103.343536],[35.90065,103.343536],[35.89859,103.343857],[35.89846,103.343979],[35.89817,103.344414],[35.897621,103.344704],[35.897129,103.345703],[35.896881,103.34639],[35.896431,103.34671],[35.895969,103.346939],[35.89587,103.347069],[35.895691,103.347488],[35.89558,103.347527],[35.89534,103.347504],[35.89521,103.347527],[35.89476,103.348007],[35.89463,103.348091],[35.89418,103.348106],[35.893681,103.348648],[35.893181,103.349037],[35.892849,103.34922],[35.89254,103.349564],[35.89238,103.349663],[35.891979,103.3498],[35.890751,103.349899],[35.890461,103.349991],[35.890411,103.350182],[35.89043,103.350258],[35.890511,103.350327],[35.89156,103.35038],[35.892181,103.350471],[35.893009,103.350128],[35.893799,103.349693],[35.89444,103.349716],[35.894539,103.349617],[35.894619,103.349274],[35.894699,103.349159],[35.89558,103.349037],[35.896191,103.348778],[35.896641,103.34893],[35.897041,103.34993],[35.89719,103.350098],[35.897339,103.350098],[35.89772,103.349899],[35.8978,103.349777],[35.8978,103.349579],[35.89764,103.349007],[35.8978,103.348557],[35.897709,103.348099],[35.8978,103.347931],[35.898121,103.347954],[35.89872,103.348198],[35.899151,103.348503],[35.89925,103.348503],[35.899361,103.34832],[35.89933,103.347771],[35.89941,103.34761],[35.89954,103.347588],[35.90036,103.347977],[35.900539,103.348007],[35.90073,103.347939],[35.90081,103.347816],[35.900829,103.347687],[35.90081,103.347557],[35.90065,103.347237],[35.900631,103.347099],[35.900749,103.346939],[35.900909,103.346909],[35.90134,103.347023],[35.901581,103.347237],[35.901871,103.347633],[35.902,103.347656],[35.90229,103.347557],[35.902451,103.347679],[35.902481,103.347763],[35.902481,103.347893],[35.90239,103.34819],[35.902279,103.348427],[35.902161,103.348557],[35.901821,103.34874],[35.901421,103.349083],[35.90097,103.349548],[35.900539,103.349586],[35.900391,103.34967],[35.8992,103.351128],[35.898899,103.35125],[35.89851,103.351738],[35.897949,103.352081],[35.897701,103.352127],[35.89711,103.351883],[35.89674,103.351799],[35.89637,103.351517],[35.896191,103.351509],[35.895741,103.352219],[35.895531,103.352287],[35.895241,103.35228],[35.895111,103.352341],[35.895081,103.352386],[35.89502,103.352798],[35.89492,103.353027],[35.89476,103.353088],[35.89397,103.353027],[35.893871,103.353111],[35.893799,103.353317],[35.893951,103.354019],[35.89389,103.354156],[35.8937,103.354309],[35.893311,103.354301],[35.89315,103.354233],[35.89241,103.353683],[35.892151,103.353607],[35.892021,103.353699],[35.892021,103.35376],[35.89212,103.353859],[35.892509,103.353973],[35.89323,103.354584],[35.893391,103.35466],[35.89381,103.354607],[35.893921,103.35466],[35.89402,103.35479],[35.89415,103.355057],[35.894161,103.35524],[35.89365,103.356293],[35.893379,103.357338],[35.89333,103.357857],[35.89352,103.358528],[35.893539,103.358757],[35.89328,103.359581],[35.893101,103.36042],[35.892891,103.36097],[35.892601,103.361397],[35.892479,103.361679],[35.892399,103.362267],[35.89225,103.362717],[35.891689,103.363441],[35.891701,103.363586],[35.89183,103.36393],[35.89188,103.364227],[35.891739,103.364799],[35.891239,103.365868],[35.89119,103.366417],[35.89098,103.366737],[35.89064,103.367073],[35.890411,103.367378],[35.890461,103.367554],[35.8909,103.367996],[35.890999,103.368294],[35.890999,103.368591],[35.890789,103.369034],[35.89082,103.36924],[35.891251,103.369507],[35.89138,103.369766],[35.89138,103.370003],[35.8913,103.370537],[35.89101,103.371597],[35.890831,103.371979],[35.89056,103.372147],[35.89024,103.372467],[35.890041,103.372566],[35.88974,103.372597],[35.88937,103.372917],[35.88903,103.373154],[35.88842,103.374519],[35.888161,103.374847],[35.886051,103.37606],[35.886009,103.37616],[35.88596,103.376633],[35.885849,103.376869],[35.88541,103.377274],[35.884781,103.377457],[35.884541,103.377586],[35.88446,103.377731],[35.884411,103.378151],[35.8843,103.378258],[35.883511,103.378441],[35.88298,103.378433],[35.882721,103.378593],[35.88261,103.378754],[35.882599,103.37886],[35.882771,103.379341],[35.882801,103.379578],[35.882759,103.379761],[35.882641,103.37989],[35.881191,103.380547],[35.880939,103.38073],[35.880829,103.380997],[35.880619,103.382156],[35.880322,103.382767],[35.880291,103.38385],[35.880409,103.384117],[35.880939,103.38459],[35.881069,103.384758],[35.88121,103.385139],[35.88121,103.385368],[35.881161,103.385468],[35.880951,103.385757],[35.88076,103.385887],[35.879971,103.386147],[35.879841,103.386299],[35.879841,103.386543],[35.88002,103.386917],[35.879921,103.387154],[35.879681,103.387321],[35.87952,103.387543],[35.879551,103.387688],[35.879791,103.388077],[35.879791,103.388206],[35.879631,103.38842],[35.879021,103.388748],[35.87709,103.389458],[35.876881,103.389587],[35.87672,103.389809],[35.87672,103.389977],[35.876801,103.39016],[35.878311,103.3909],[35.878521,103.391068],[35.878559,103.39119],[35.878521,103.391258],[35.878349,103.391243],[35.87804,103.390953],[35.877689,103.39077],[35.87616,103.39035],[35.876011,103.390266],[35.875931,103.390129],[35.87603,103.389709],[35.87619,103.389503],[35.87701,103.388939],[35.878201,103.388283],[35.87825,103.388153],[35.878231,103.388077],[35.87812,103.388031],[35.877522,103.388428],[35.875599,103.389351],[35.875351,103.389648],[35.87513,103.390297],[35.875111,103.390511],[35.87524,103.390678],[35.87656,103.391373],[35.87661,103.391434],[35.876629,103.391602],[35.876541,103.391769],[35.876339,103.39193],[35.875771,103.392357],[35.875191,103.392609],[35.874691,103.392929],[35.874081,103.393051],[35.87344,103.393417],[35.871861,103.39402],[35.87075,103.394524],[35.87011,103.394608],[35.869961,103.394691],[35.86961,103.395073],[35.868111,103.395668],[35.867321,103.396179],[35.867111,103.39637],[35.867069,103.396553],[35.867081,103.396683],[35.867199,103.396843],[35.86832,103.39743],[35.869591,103.398453],[35.87022,103.398804],[35.87038,103.399048],[35.870361,103.399178],[35.870201,103.399361],[35.869431,103.399841],[35.869091,103.399986],[35.86861,103.400093],[35.868141,103.400467],[35.86787,103.400551],[35.867661,103.400681],[35.867149,103.401268],[35.867119,103.401443],[35.867149,103.401558],[35.86763,103.402008],[35.867649,103.402283],[35.867481,103.402573],[35.867161,103.402901],[35.866291,103.403427],[35.86607,103.403679],[35.865761,103.404739],[35.865841,103.406013],[35.865971,103.40625],[35.86607,103.406303],[35.866211,103.406273],[35.867451,103.405586],[35.867729,103.40551],[35.867889,103.405602],[35.86832,103.406197],[35.868839,103.406593],[35.868931,103.406731],[35.86898,103.406891],[35.868931,103.407028],[35.868771,103.407204],[35.867191,103.407806],[35.866859,103.407967],[35.866791,103.408081],[35.866791,103.408257],[35.866909,103.408417],[35.867561,103.408813],[35.867691,103.408951],[35.86776,103.409119],[35.86768,103.409271],[35.867569,103.40934],[35.86515,103.410027],[35.864929,103.410172],[35.864769,103.410393],[35.864689,103.410759],[35.864761,103.411324],[35.864731,103.411621],[35.864109,103.412628],[35.86393,103.413116],[35.863892,103.414146],[35.86396,103.414627],[35.86388,103.414917],[35.863529,103.415466],[35.863441,103.415733],[35.863411,103.416649],[35.863491,103.416946],[35.863731,103.417427],[35.86372,103.417908],[35.863781,103.418327],[35.864071,103.418747],[35.864521,103.420151],[35.864891,103.42057],[35.86499,103.420769],[35.86499,103.421059],[35.864799,103.421509],[35.86478,103.421677],[35.865089,103.422218],[35.865089,103.422607],[35.86515,103.422897],[35.865471,103.423698],[35.865509,103.424347],[35.866211,103.425583],[35.866371,103.425957],[35.866501,103.426392],[35.866631,103.427513],[35.866611,103.427803],[35.866501,103.428108],[35.866081,103.428947],[35.866081,103.429131],[35.866161,103.429199],[35.866261,103.429161],[35.86668,103.428268],[35.86694,103.427948],[35.86705,103.427917],[35.867531,103.428108],[35.867661,103.428101],[35.86779,103.428017],[35.868309,103.427551],[35.86842,103.427544],[35.868481,103.427681],[35.868301,103.427917],[35.867771,103.428368],[35.867661,103.428436],[35.867161,103.42852],[35.867001,103.428658],[35.866699,103.429367],[35.866699,103.429558],[35.866791,103.429817],[35.866791,103.430061],[35.866631,103.430191],[35.866371,103.430267],[35.86623,103.430397],[35.866119,103.430641],[35.86594,103.431297],[35.86578,103.431534],[35.865601,103.431633],[35.86512,103.431763],[35.86441,103.432266],[35.864201,103.432281],[35.863701,103.432137],[35.86356,103.432137],[35.86343,103.432259],[35.86338,103.43248],[35.863491,103.433296],[35.864361,103.435059],[35.864361,103.435333],[35.864269,103.435577],[35.864109,103.435791],[35.863621,103.436157],[35.863491,103.436699],[35.863361,103.436943],[35.862949,103.437317],[35.86245,103.437477],[35.862171,103.437668],[35.861931,103.437866],[35.861752,103.438148],[35.86166,103.438637],[35.86132,103.439491],[35.861229,103.440849],[35.86158,103.441933],[35.861771,103.44236],[35.862122,103.442917],[35.862141,103.443161],[35.862011,103.443298],[35.86132,103.443497],[35.861111,103.443932],[35.861012,103.444],[35.86031,103.444054],[35.8601,103.444153],[35.860031,103.444237],[35.860031,103.444519],[35.86034,103.444893],[35.860371,103.445053],[35.860321,103.445221],[35.86005,103.445541],[35.859909,103.445587],[35.859699,103.445587],[35.858891,103.445396],[35.85844,103.445396],[35.856571,103.445953],[35.8563,103.446091],[35.855801,103.44648],[35.855221,103.446709],[35.85482,103.446999],[35.854191,103.447113],[35.85363,103.447479],[35.852451,103.447937],[35.851891,103.448051],[35.85046,103.447929],[35.850182,103.44796],[35.84903,103.448624],[35.847549,103.449226],[35.8456,103.450958],[35.8447,103.45121],[35.844551,103.451347],[35.844379,103.451988],[35.84417,103.452217],[35.841621,103.453018],[35.84103,103.4533],[35.840721,103.453308],[35.839741,103.453018],[35.839409,103.45269],[35.839081,103.452217],[35.838791,103.451988],[35.837379,103.45195],[35.836552,103.45182],[35.836411,103.451714],[35.836281,103.4515],[35.83577,103.44986],[35.835541,103.449448],[35.834641,103.449051],[35.8339,103.448349],[35.833389,103.448067],[35.831711,103.446968],[35.831539,103.446907],[35.831089,103.446907],[35.83028,103.446663],[35.829361,103.446587],[35.82859,103.446327],[35.828239,103.44632],[35.826759,103.446579],[35.825489,103.446587],[35.823792,103.446289],[35.822731,103.446251],[35.822109,103.445961],[35.82196,103.445953],[35.821239,103.446121],[35.82066,103.446564],[35.820499,103.446617],[35.819111,103.446938],[35.816921,103.447937],[35.816559,103.448021],[35.81599,103.447937],[35.814091,103.44809],[35.81358,103.448036],[35.812801,103.448151],[35.8125,103.448067],[35.81221,103.447906],[35.812111,103.447777],[35.81205,103.447578],[35.81213,103.446388],[35.812031,103.445686],[35.812229,103.444946],[35.812241,103.444763],[35.812191,103.44458],[35.811161,103.443619],[35.810452,103.442787],[35.809799,103.442299],[35.809681,103.442131],[35.808922,103.440361],[35.808731,103.440071],[35.80843,103.439758],[35.808281,103.439697],[35.807869,103.439728],[35.807449,103.439537],[35.806911,103.439407],[35.805611,103.438591],[35.804291,103.438309],[35.80405,103.438179],[35.803631,103.43782],[35.802731,103.437592],[35.802341,103.437393],[35.801941,103.437286],[35.80056,103.437141],[35.7995,103.437111],[35.798691,103.437286],[35.798481,103.43721],[35.798012,103.436867],[35.797791,103.436821],[35.795181,103.43663],[35.793781,103.436768],[35.792801,103.436974],[35.79229,103.43692],[35.79073,103.436157],[35.78941,103.435959],[35.788971,103.435799],[35.787891,103.434837],[35.787312,103.434486],[35.786201,103.434097],[35.785431,103.434029],[35.783321,103.432663],[35.78191,103.431961],[35.780861,103.431618],[35.780449,103.431396],[35.779381,103.431396],[35.77903,103.431473],[35.778332,103.431137],[35.777512,103.431],[35.77626,103.430901],[35.77512,103.430588],[35.774719,103.430557],[35.77388,103.430611],[35.77367,103.430557],[35.773472,103.430397],[35.773041,103.429649],[35.772831,103.429337],[35.771561,103.428581],[35.770069,103.427193],[35.769489,103.427048],[35.768162,103.42617],[35.767551,103.426033],[35.767231,103.425774],[35.76545,103.424019],[35.764339,103.423241],[35.763401,103.42289],[35.762741,103.422348],[35.762371,103.421913],[35.76136,103.420219],[35.761292,103.419991],[35.761238,103.419327],[35.76086,103.418114],[35.760712,103.417877],[35.76012,103.417557],[35.759979,103.417381],[35.759651,103.41674],[35.759491,103.41655],[35.758671,103.415916],[35.757431,103.415581],[35.757252,103.415482],[35.757038,103.415268],[35.756512,103.414574],[35.75589,103.414101],[35.755531,103.413559],[35.755131,103.413231],[35.75449,103.41291],[35.7537,103.412727],[35.753029,103.412468],[35.751961,103.4123],[35.751732,103.412338],[35.75153,103.412437],[35.750721,103.413139],[35.750191,103.413361],[35.748661,103.414337],[35.747501,103.415573],[35.747021,103.416161],[35.746319,103.416679],[35.74596,103.417007],[35.74577,103.417267],[35.745159,103.417717],[35.744869,103.418159],[35.74469,103.418793],[35.74456,103.418877],[35.744171,103.418907],[35.743889,103.419144],[35.74361,103.419609],[35.743511,103.41996],[35.743462,103.420349],[35.74345,103.420807],[35.743721,103.421707],[35.743698,103.42186],[35.743629,103.421928],[35.743401,103.421959],[35.742809,103.421829],[35.7416,103.421478],[35.741199,103.42128],[35.74094,103.421227],[35.74065,103.42131],[35.74012,103.421638],[35.739811,103.421738],[35.738621,103.421799],[35.737419,103.422371],[35.736851,103.422546],[35.736271,103.423141],[35.735371,103.423576],[35.734909,103.424309],[35.73457,103.42469],[35.733471,103.425323],[35.732941,103.425507],[35.732761,103.425659],[35.73243,103.426041],[35.731781,103.426521],[35.731392,103.426888],[35.73093,103.427017],[35.73019,103.427361],[35.729591,103.427727],[35.728901,103.427887],[35.727501,103.428978],[35.72707,103.429199],[35.726212,103.429367],[35.72541,103.430107],[35.725182,103.43026],[35.72477,103.430443],[35.723,103.431],[35.722721,103.430969],[35.72171,103.430527],[35.72142,103.430519],[35.720909,103.43058],[35.720711,103.430641],[35.719101,103.431473],[35.718399,103.43222],[35.718151,103.432373],[35.717541,103.432457],[35.717239,103.432411],[35.716431,103.432129],[35.716171,103.432137],[35.7155,103.432327],[35.714588,103.43293],[35.713051,103.43364],[35.71278,103.433823],[35.71246,103.434158],[35.712231,103.434334],[35.71172,103.434471],[35.711391,103.434441],[35.710972,103.434128],[35.710869,103.43399],[35.710831,103.433823],[35.71093,103.431198],[35.71101,103.430946],[35.7113,103.430458],[35.711399,103.430191],[35.711391,103.429947],[35.711239,103.429314],[35.711208,103.428047],[35.711151,103.427719],[35.710819,103.427368],[35.710091,103.426849],[35.70953,103.42601],[35.708981,103.425728],[35.708778,103.425507],[35.70842,103.424606],[35.708229,103.423592],[35.70797,103.42308],[35.707722,103.422737],[35.706871,103.422058],[35.706322,103.421387],[35.70499,103.419319],[35.7048,103.418739],[35.704361,103.416847],[35.703651,103.415848],[35.70327,103.41497],[35.703098,103.414879],[35.70266,103.414818],[35.702049,103.414467],[35.701721,103.414383],[35.701271,103.414291],[35.70076,103.414337],[35.700081,103.414261],[35.69939,103.413971],[35.69849,103.413681],[35.697868,103.413673],[35.697472,103.413559],[35.696949,103.413498],[35.696659,103.413551],[35.696331,103.413689],[35.696159,103.413696],[35.695,103.413429],[35.69334,103.41317],[35.692032,103.41304],[35.69128,103.41317],[35.690941,103.413109],[35.69067,103.412949],[35.690331,103.412468],[35.690182,103.412369],[35.687698,103.411743],[35.687191,103.411568],[35.68639,103.411217],[35.685081,103.41053],[35.684212,103.410477],[35.682892,103.410057],[35.68222,103.410103],[35.681419,103.41024],[35.680771,103.410057],[35.680248,103.410011],[35.67989,103.409798],[35.679691,103.409737],[35.679241,103.409889],[35.678841,103.41011],[35.678001,103.41021],[35.67762,103.410141],[35.676731,103.40963],[35.676571,103.409576],[35.6759,103.40979],[35.675289,103.410103],[35.675011,103.410103],[35.674641,103.410011],[35.674511,103.40992],[35.674179,103.409286],[35.67355,103.408478],[35.673241,103.407913],[35.672878,103.406868],[35.67276,103.406113],[35.672611,103.405769],[35.67205,103.40509],[35.671398,103.40477],[35.671242,103.40461],[35.67078,103.403748],[35.670349,103.403191],[35.669762,103.402283],[35.66938,103.401527],[35.667961,103.39978],[35.667419,103.399017],[35.666729,103.397881],[35.666481,103.397179],[35.666401,103.3964],[35.666401,103.396027],[35.6665,103.39534],[35.66684,103.394257],[35.666851,103.39389],[35.6661,103.392097],[35.665989,103.391739],[35.665932,103.391281],[35.66592,103.390427],[35.666031,103.389999],[35.66695,103.388039],[35.666988,103.387772],[35.666931,103.386757],[35.666962,103.386276],[35.667122,103.385788],[35.667679,103.38459],[35.667751,103.384331],[35.667721,103.384216],[35.667549,103.384087],[35.66613,103.383667],[35.665871,103.38353],[35.66489,103.382767],[35.664322,103.381897],[35.664261,103.381706],[35.664249,103.381287],[35.6642,103.381027],[35.664322,103.38092],[35.665871,103.378578],[35.666142,103.378319],[35.66671,103.378059],[35.666851,103.377937],[35.666889,103.377823],[35.66687,103.377693],[35.666512,103.37719],[35.666351,103.376846],[35.666328,103.376404],[35.666401,103.375977],[35.666561,103.375519],[35.66674,103.375221],[35.666988,103.374947],[35.66732,103.374748],[35.668049,103.374527],[35.668598,103.37394],[35.66864,103.373871],[35.66864,103.373657],[35.668331,103.373161],[35.668308,103.37291],[35.668442,103.372383],[35.668991,103.370827],[35.669281,103.370537],[35.669781,103.370399],[35.669899,103.370308],[35.67017,103.369781],[35.670681,103.369217],[35.670738,103.369003],[35.67075,103.368317],[35.671169,103.366959],[35.67131,103.366699],[35.67149,103.366508],[35.67197,103.366348],[35.672138,103.366158],[35.67226,103.365868],[35.672588,103.365303],[35.672779,103.364464],[35.673592,103.362717],[35.67384,103.362488],[35.674469,103.362373],[35.67466,103.362167],[35.674641,103.361969],[35.67429,103.361183],[35.674179,103.360779],[35.674141,103.360336],[35.674179,103.35997],[35.674278,103.35952],[35.6744,103.3592],[35.675159,103.357887],[35.675381,103.357407],[35.675671,103.356628],[35.67572,103.356117],[35.675522,103.354897],[35.675228,103.354187],[35.67519,103.353928],[35.67511,103.352631],[35.67495,103.351517],[35.674931,103.350708],[35.67498,103.349876],[35.675152,103.349289],[35.676109,103.348091],[35.676201,103.347801],[35.676189,103.347366],[35.67625,103.347],[35.67664,103.346359],[35.676708,103.346169],[35.676651,103.34594],[35.676479,103.345848],[35.67622,103.345863],[35.675591,103.346001],[35.675369,103.345947],[35.674358,103.34494],[35.674191,103.344566],[35.673908,103.343567],[35.673439,103.342529],[35.672691,103.341347],[35.672001,103.339569],[35.67157,103.338913],[35.67141,103.338219],[35.671101,103.337196],[35.671089,103.336029],[35.671391,103.335098],[35.67144,103.33448],[35.671391,103.334053],[35.671181,103.333214],[35.671169,103.332649],[35.671379,103.33062],[35.671589,103.32991],[35.671638,103.329498],[35.671589,103.329224],[35.670971,103.327377],[35.67094,103.326408],[35.671162,103.324913],[35.67104,103.323448],[35.670731,103.322311],[35.670158,103.321243],[35.670052,103.320953],[35.669651,103.319107],[35.669701,103.318359],[35.66983,103.317574],[35.670078,103.317001],[35.670559,103.316399],[35.671478,103.316109],[35.672039,103.315468],[35.672112,103.315041],[35.672001,103.314247],[35.672031,103.313904],[35.672371,103.312859],[35.672649,103.312218],[35.672852,103.31192],[35.673111,103.311699],[35.673901,103.31144],[35.674511,103.31105],[35.674591,103.310944],[35.674629,103.310707],[35.674511,103.310501],[35.674358,103.310379],[35.673752,103.310043],[35.673439,103.309769],[35.673,103.30909],[35.672859,103.308746],[35.672291,103.306664],[35.672249,103.30632],[35.672241,103.305237],[35.672031,103.30368],[35.67181,103.303261],[35.671211,103.302803],[35.671021,103.302429],[35.670952,103.302147],[35.670959,103.301697],[35.671268,103.30024],[35.671268,103.299927],[35.6712,103.299637],[35.67104,103.2994],[35.670189,103.298431],[35.669708,103.297737],[35.66906,103.29705],[35.668468,103.295937],[35.66814,103.295647],[35.667011,103.29483],[35.666752,103.294487],[35.66613,103.293007],[35.665619,103.291512],[35.665421,103.290428],[35.66547,103.289299],[35.66563,103.289001],[35.6661,103.288353],[35.666439,103.287956],[35.667191,103.287514],[35.667252,103.287369],[35.66721,103.287209],[35.666969,103.287086],[35.665951,103.287117],[35.66523,103.287567],[35.665001,103.287628],[35.664711,103.28759],[35.66431,103.287376],[35.664001,103.287308],[35.663181,103.287369],[35.662651,103.287308],[35.662441,103.287209],[35.662392,103.287086],[35.66243,103.286957],[35.662498,103.286911],[35.66312,103.287117],[35.663261,103.287079],[35.663288,103.286957],[35.663158,103.286827],[35.662258,103.286507],[35.661449,103.286011],[35.661442,103.285828],[35.661579,103.285767],[35.662231,103.286209],[35.662338,103.286217],[35.662361,103.286171],[35.662338,103.286049],[35.66177,103.285568],[35.661541,103.285301],[35.661201,103.284683],[35.66111,103.28434],[35.660938,103.282738],[35.6609,103.2826],[35.660751,103.282387],[35.660568,103.282318],[35.65966,103.282188],[35.659149,103.281898],[35.65765,103.281517],[35.65723,103.281487],[35.657101,103.281387],[35.65707,103.281288],[35.657101,103.281197],[35.65723,103.281128],[35.658131,103.281342],[35.658291,103.281258],[35.65831,103.281151],[35.658291,103.281067],[35.65818,103.281013],[35.65773,103.280991],[35.657372,103.280891],[35.656239,103.280273],[35.654949,103.279778],[35.654598,103.279572],[35.65456,103.279449],[35.654621,103.27935],[35.655392,103.279572],[35.65596,103.27951],[35.65641,103.279533],[35.65654,103.27948],[35.656582,103.279373],[35.656528,103.279259],[35.656471,103.279228],[35.655281,103.279137],[35.65514,103.279053],[35.65514,103.278923],[35.655182,103.278839],[35.655331,103.278748],[35.656681,103.278648],[35.656792,103.278557],[35.656761,103.278397],[35.656651,103.278313],[35.655998,103.278236],[35.655331,103.278297],[35.655258,103.278229],[35.655251,103.278137],[35.6553,103.278038],[35.65546,103.277946],[35.65675,103.27771],[35.65683,103.277557],[35.656811,103.277481],[35.6567,103.277397],[35.655861,103.277428],[35.65443,103.277191],[35.65427,103.277077],[35.654251,103.276917],[35.65448,103.276817],[35.65659,103.276543],[35.656731,103.276367],[35.656731,103.276268],[35.656681,103.276176],[35.656528,103.276077],[35.655151,103.27552],[35.65369,103.275146],[35.653419,103.275131],[35.653278,103.275177],[35.652969,103.275414],[35.652748,103.275414],[35.65258,103.275169],[35.652451,103.274719],[35.652321,103.27446],[35.651939,103.274063],[35.651451,103.273788],[35.651291,103.273598],[35.651299,103.27343],[35.65136,103.273361],[35.651501,103.273323],[35.651642,103.273369],[35.652271,103.273804],[35.65239,103.273811],[35.652481,103.273743],[35.6525,103.273628],[35.652458,103.273483],[35.65226,103.273148],[35.6521,103.272957],[35.651661,103.272659],[35.651211,103.272621],[35.65004,103.272881],[35.649658,103.273033],[35.649212,103.273361],[35.649109,103.273376],[35.648979,103.273323],[35.64819,103.272118],[35.646919,103.271004],[35.646561,103.270851],[35.64571,103.270798],[35.645481,103.270714],[35.64291,103.267601],[35.642479,103.267113],[35.641449,103.266518],[35.640148,103.265381],[35.639851,103.26535],[35.639332,103.26561],[35.638561,103.265511],[35.638519,103.265419],[35.638618,103.265297],[35.639278,103.265327],[35.639462,103.265289],[35.640018,103.264847],[35.64048,103.264709],[35.64053,103.264664],[35.640541,103.264526],[35.640461,103.264488],[35.640331,103.264511],[35.639488,103.264816],[35.639141,103.264877],[35.63884,103.264847],[35.637539,103.264397],[35.63736,103.26413],[35.636978,103.262703],[35.636829,103.262299],[35.63596,103.260696],[35.634201,103.25956],[35.633709,103.259323],[35.633259,103.259193],[35.633369,103.258347],[35.633419,103.257973],[35.63335,103.25753],[35.632938,103.256683],[35.631889,103.254807],[35.631321,103.253601],[35.630329,103.252037],[35.629211,103.251122],[35.627739,103.249153],[35.62553,103.245537],[35.62373,103.242867],[35.622391,103.240761],[35.620541,103.236931],[35.620201,103.236359],[35.618198,103.23378],[35.617821,103.233383],[35.616402,103.232117],[35.614368,103.230057],[35.612492,103.228554],[35.61097,103.227501],[35.61018,103.22702],[35.60989,103.226784],[35.60968,103.226479],[35.609032,103.225113],[35.608459,103.223633],[35.606361,103.217888],[35.60556,103.215599],[35.605331,103.214813],[35.605228,103.214073],[35.604889,103.211906],[35.604721,103.210388],[35.60458,103.209633],[35.604149,103.206146],[35.60376,103.203613],[35.6036,103.202927],[35.603359,103.202293],[35.603119,103.201691],[35.602638,103.200798],[35.601089,103.198578],[35.600658,103.198082],[35.599781,103.197357],[35.598999,103.196541],[35.597111,103.195717],[35.596088,103.194817],[35.59544,103.194504],[35.595081,103.19426],[35.59306,103.192612],[35.592621,103.192284],[35.59185,103.191849],[35.59042,103.190697],[35.590179,103.190697],[35.58989,103.19088],[35.588188,103.19265],[35.58741,103.193542],[35.584061,103.197113],[35.582069,103.199463],[35.58186,103.199707],[35.581558,103.199982],[35.575211,103.207153],[35.57468,103.207718],[35.57449,103.207787],[35.57439,103.207703],[35.5728,103.204857],[35.57233,103.203918],[35.571621,103.201767],[35.571049,103.200562],[35.567841,103.195183],[35.566792,103.19313],[35.56625,103.191948],[35.564529,103.187828],[35.56329,103.185181],[35.562019,103.182838],[35.56052,103.180397],[35.55962,103.179077],[35.556969,103.175499],[35.55489,103.17289],[35.550018,103.166527],[35.548321,103.164391],[35.5476,103.163391],[35.546902,103.162338],[35.545528,103.16008],[35.543041,103.15567],[35.54232,103.15464],[35.541561,103.153687],[35.54073,103.152809],[35.539799,103.152023],[35.538818,103.151321],[35.535782,103.149399],[35.534851,103.148666],[35.533989,103.147789],[35.533211,103.146782],[35.532539,103.145638],[35.53196,103.14431],[35.530941,103.141441],[35.530281,103.140083],[35.529461,103.138878],[35.526112,103.134903],[35.5242,103.13282],[35.523232,103.132057],[35.521309,103.13089],[35.520531,103.130219],[35.51989,103.129433],[35.519241,103.128273],[35.51741,103.124367],[35.516689,103.1231],[35.514229,103.119591],[35.5135,103.118378],[35.512829,103.117073],[35.511581,103.114212],[35.510941,103.1129],[35.510281,103.111717],[35.509041,103.109848],[35.505951,103.106201],[35.505112,103.104973],[35.50441,103.103653],[35.50386,103.102333],[35.50346,103.101013],[35.503189,103.099716],[35.502399,103.094597],[35.502201,103.093712],[35.501808,103.092293],[35.501389,103.090981],[35.50058,103.08902],[35.499882,103.087723],[35.495811,103.081123],[35.48962,103.071373],[35.488949,103.070259],[35.488369,103.069061],[35.487919,103.067871],[35.487572,103.066711],[35.48708,103.064552],[35.486481,103.062363],[35.486,103.060966],[35.485378,103.059608],[35.484631,103.058342],[35.483799,103.05722],[35.478809,103.051376],[35.47821,103.050323],[35.477829,103.049171],[35.47768,103.047943],[35.477772,103.045326],[35.47773,103.043961],[35.47747,103.042709],[35.477051,103.041588],[35.476521,103.040527],[35.47591,103.03965],[35.47348,103.036369],[35.473091,103.035751],[35.472778,103.035004],[35.472481,103.034416],[35.47213,103.033684],[35.471741,103.03286],[35.471352,103.031998],[35.470959,103.03112],[35.47057,103.030228],[35.4702,103.029404],[35.469872,103.028671],[35.469601,103.028069],[35.469429,103.02774],[35.469158,103.027458],[35.46896,103.027069],[35.468651,103.026581],[35.46825,103.025993],[35.467819,103.025383],[35.467369,103.024727],[35.4669,103.023933],[35.466431,103.022949],[35.465912,103.021828],[35.465328,103.020729],[35.46468,103.019623],[35.464008,103.018539],[35.463291,103.017517],[35.462559,103.016533],[35.461849,103.015556],[35.46114,103.014618],[35.46048,103.013733],[35.459919,103.012947],[35.45927,103.012123],[35.458549,103.011261],[35.457821,103.010536],[35.457119,103.009933],[35.456459,103.009354],[35.45591,103.008858],[35.455589,103.008537],[35.455299,103.008209],[35.45509,103.00795],[35.454781,103.007591],[35.454411,103.007004],[35.45396,103.00631],[35.45343,103.005493],[35.452881,103.004639],[35.45229,103.003723],[35.45166,103.002747],[35.450989,103.001732],[35.450352,103.000763],[35.449749,102.999847],[35.449181,102.99894],[35.448589,102.998016],[35.448009,102.997017],[35.44743,102.995979],[35.44685,102.994904],[35.446331,102.993752],[35.44582,102.992622],[35.44537,102.991463],[35.44492,102.990227],[35.444489,102.988983],[35.44408,102.987747],[35.44368,102.986572],[35.443291,102.985443],[35.442909,102.984306],[35.442478,102.983147],[35.442039,102.982018],[35.441681,102.981148],[35.44136,102.980476],[35.440971,102.97966],[35.440491,102.978683],[35.439949,102.977654],[35.439381,102.976646],[35.43877,102.975662],[35.438099,102.97467],[35.43742,102.97364],[35.436722,102.97261],[35.436008,102.971558],[35.435322,102.970543],[35.43462,102.969528],[35.433941,102.968452],[35.4333,102.967262],[35.43269,102.966011],[35.43211,102.964684],[35.43158,102.963417],[35.431,102.962303],[35.430302,102.961357],[35.429562,102.960564],[35.428768,102.959732],[35.427952,102.958832],[35.42709,102.957909],[35.426281,102.956879],[35.425621,102.955727],[35.425098,102.954536],[35.424549,102.953484],[35.423809,102.952728],[35.422932,102.952316],[35.422001,102.952164],[35.421009,102.951927],[35.420071,102.951408],[35.419189,102.950607],[35.418491,102.94957],[35.418018,102.94838],[35.417789,102.947189],[35.417782,102.946098],[35.41782,102.945053],[35.4179,102.944054],[35.417839,102.943031],[35.417629,102.941994],[35.417309,102.94101],[35.41695,102.940071],[35.416561,102.939163],[35.416069,102.938316],[35.415401,102.937714],[35.414631,102.937431],[35.41383,102.937317],[35.413139,102.937134],[35.412491,102.936829],[35.411789,102.936691],[35.4114,102.936707],[35.411301,102.936707],[35.411072,102.93676],[35.41066,102.936859],[35.409988,102.937027],[35.409199,102.937218],[35.408352,102.937424],[35.407452,102.937622],[35.406528,102.937851],[35.405682,102.938026],[35.404869,102.937973],[35.404079,102.937561],[35.403461,102.93679],[35.403118,102.935806],[35.403011,102.934837],[35.403049,102.933891],[35.40324,102.932953],[35.403542,102.932159],[35.40387,102.931419],[35.40424,102.930603],[35.40443,102.929657],[35.404491,102.928612],[35.404388,102.927582],[35.404121,102.926682],[35.403759,102.925926],[35.403309,102.925323],[35.402802,102.92482],[35.40226,102.924454],[35.401581,102.924118],[35.400791,102.923843],[35.399948,102.923599],[35.399151,102.9235],[35.39827,102.923492],[35.39735,102.923553],[35.396461,102.923607],[35.39558,102.923599],[35.394718,102.923477],[35.39389,102.923233],[35.39307,102.922943],[35.392231,102.922623],[35.39143,102.92234],[35.39061,102.921997],[35.389771,102.921677],[35.388908,102.921349],[35.388069,102.921028],[35.387199,102.9207],[35.386341,102.920349],[35.385529,102.919762],[35.38496,102.918961],[35.384529,102.918007],[35.384071,102.917122],[35.3834,102.916473],[35.382599,102.916077],[35.38166,102.915848],[35.380772,102.915627],[35.37994,102.915367],[35.379131,102.915009],[35.378422,102.914597],[35.377838,102.914192],[35.37468,102.90918],[35.374611,102.908829],[35.374439,102.908287],[35.374298,102.907402],[35.374321,102.906273],[35.374531,102.905228],[35.37495,102.904221],[35.375511,102.903107],[35.3759,102.90184],[35.375999,102.900543],[35.375912,102.899307],[35.375759,102.898193],[35.37561,102.897133],[35.375469,102.89608],[35.375301,102.894974],[35.374969,102.893929],[35.374378,102.89315],[35.37368,102.892708],[35.372768,102.892517],[35.371868,102.892357],[35.370911,102.892181],[35.36985,102.891998],[35.368778,102.891777],[35.367809,102.891579],[35.366951,102.891083],[35.366268,102.890213],[35.365891,102.889053],[35.365669,102.888008],[35.36544,102.887177],[35.36515,102.886414],[35.36488,102.885513],[35.36478,102.884354],[35.364731,102.883034],[35.364552,102.88176],[35.364288,102.880661],[35.364029,102.879623],[35.363899,102.878464],[35.364021,102.877327],[35.364441,102.876213],[35.364979,102.875038],[35.365551,102.873749],[35.366169,102.872398],[35.366798,102.870979],[35.36742,102.869614],[35.368019,102.868248],[35.368549,102.866814],[35.368858,102.865257],[35.368961,102.86364],[35.368801,102.862106],[35.368431,102.860733],[35.368,102.859467],[35.367599,102.858261],[35.36639,102.854156],[35.365791,102.853081],[35.364971,102.852219],[35.363811,102.851501],[35.363041,102.850388],[35.362431,102.84906],[35.362061,102.847656],[35.36227,102.846184],[35.362411,102.844818],[35.36026,102.837929],[35.359489,102.837067],[35.35873,102.836166],[35.35833,102.834877],[35.358231,102.833473],[35.35804,102.83223],[35.357498,102.831139],[35.35677,102.830231],[35.35622,102.829117],[35.355942,102.827766],[35.355701,102.826424],[35.35524,102.825127],[35.35461,102.823883],[35.35376,102.822739],[35.352798,102.821808],[35.35183,102.821068],[35.35104,102.820137],[35.350651,102.81884],[35.350788,102.81739],[35.35146,102.816071],[35.352291,102.814774],[35.352989,102.813347],[35.353378,102.811852],[35.353401,102.810509],[35.353149,102.809212],[35.35268,102.807991],[35.35199,102.806923],[35.351181,102.805923],[35.35033,102.804901],[35.349461,102.803833],[35.348579,102.802696],[35.347729,102.801422],[35.346909,102.800049],[35.346119,102.798599],[35.34531,102.797157],[35.344509,102.795769],[35.34375,102.794441],[35.342979,102.793121],[35.342239,102.791832],[35.341431,102.790657],[35.34045,102.789818],[35.339298,102.789383],[35.3381,102.789253],[35.336971,102.789108],[35.33593,102.788727],[35.334961,102.787979],[35.334099,102.786957],[35.333279,102.785858],[35.332409,102.784927],[35.331421,102.784317],[35.330471,102.784027],[35.329521,102.783981],[35.32848,102.783913],[35.3274,102.783783],[35.326351,102.783684],[35.325291,102.783577],[35.32428,102.783379],[35.32341,102.782951],[35.322651,102.782417],[35.321892,102.781883],[35.32111,102.781273],[35.320259,102.780647],[35.319302,102.779938],[35.318272,102.779167],[35.317268,102.778442],[35.316319,102.777733],[35.31538,102.777039],[35.314579,102.776443],[35.313789,102.775848],[35.313019,102.775261],[35.31218,102.774643],[35.311279,102.773972],[35.310329,102.773247],[35.309299,102.772476],[35.308281,102.771721],[35.30727,102.770973],[35.306221,102.770241],[35.305149,102.76963],[35.303982,102.769386],[35.302799,102.769669],[35.301762,102.770378],[35.300961,102.771469],[35.300449,102.772797],[35.300171,102.774277],[35.29998,102.775772],[35.29966,102.777222],[35.299042,102.778503],[35.298061,102.779442],[35.29686,102.779953],[35.29562,102.780006],[35.294418,102.77993],[35.293289,102.779846],[35.292091,102.779808],[35.290871,102.780098],[35.289761,102.780853],[35.288792,102.781937],[35.287811,102.783127],[35.286819,102.784317],[35.285671,102.785278],[35.284519,102.785851],[35.283691,102.786346],[35.282909,102.786987],[35.28215,102.787903],[35.281509,102.789078],[35.28088,102.790298],[35.27998,102.791092],[35.279041,102.791397],[35.278191,102.791832],[35.277489,102.792702],[35.276871,102.793739],[35.27599,102.794518],[35.275082,102.795197],[35.274281,102.796066],[35.273659,102.797142],[35.27285,102.797981],[35.271969,102.798538],[35.27113,102.799278],[35.270439,102.800369],[35.27002,102.801697],[35.269691,102.803078],[35.269009,102.804176],[35.26833,102.80526],[35.267719,102.806412],[35.267151,102.807663],[35.26646,102.808907],[35.265461,102.809837],[35.26432,102.810318],[35.263149,102.810349],[35.262001,102.810471],[35.260948,102.810944],[35.260021,102.811798],[35.259159,102.813004],[35.258171,102.814133],[35.256962,102.81472],[35.255711,102.814743],[35.254459,102.814583],[35.253288,102.814636],[35.252251,102.815086],[35.251461,102.81588],[35.250809,102.81662],[35.25013,102.817413],[35.24934,102.818222],[35.248451,102.819069],[35.247459,102.819939],[35.246399,102.820847],[35.2453,102.821823],[35.24419,102.822777],[35.243111,102.823723],[35.24213,102.824547],[35.241241,102.825233],[35.240318,102.825447],[35.23938,102.825203],[35.238338,102.824837],[35.237228,102.824516],[35.23616,102.824661],[35.235271,102.82534],[35.23457,102.826111],[35.23394,102.826828],[35.23325,102.827423],[35.232368,102.827667],[35.23151,102.827499],[35.230751,102.826981],[35.22998,102.826317],[35.229229,102.825653],[35.2285,102.825111],[35.227921,102.824867],[35.227428,102.824753],[35.226891,102.824638],[35.226311,102.824516],[35.225788,102.824364],[35.2253,102.824142],[35.224899,102.823929],[35.224579,102.823761],[35.224289,102.823593],[35.223721,102.823593],[35.223019,102.824867],[35.22028,102.823959],[35.219189,102.82222],[35.219341,102.820396],[35.217682,102.819847],[35.216991,102.819962],[35.216461,102.820084],[35.216099,102.820137],[35.21553,102.820168],[35.214588,102.82019],[35.212101,102.820183],[35.211349,102.820267],[35.210251,102.820648],[35.209091,102.821487],[35.20895,102.821457],[35.20776,102.822563],[35.207409,102.822762],[35.206841,102.82299],[35.20562,102.823189],[35.205009,102.823189],[35.203999,102.823151],[35.20266,102.82312],[35.20145,102.822144],[35.19294,102.825737],[35.191181,102.825211],[35.18959,102.824623],[35.18874,102.823799],[35.187778,102.822731],[35.187222,102.822189],[35.186218,102.821831],[35.18605,102.821823],[35.185322,102.821877],[35.184959,102.821877],[35.184441,102.821777],[35.18425,102.821716],[35.182701,102.820602],[35.182388,102.82045],[35.181721,102.820358],[35.180901,102.820633],[35.180462,102.820976],[35.180199,102.821297],[35.17981,102.822037],[35.179729,102.822243],[35.179531,102.822861],[35.17952,102.824043],[35.177551,102.824539],[35.176521,102.824928],[35.169189,102.832947],[35.168301,102.831947],[35.167881,102.832352],[35.16703,102.833344],[35.166321,102.834084],[35.165489,102.834763],[35.164631,102.835503],[35.16338,102.836906],[35.162361,102.838348],[35.16256,102.839882],[35.156368,102.845108],[35.15435,102.845139],[35.153439,102.845741],[35.152439,102.846649],[35.15229,102.846764],[35.151039,102.847153],[35.14999,102.847733],[35.148682,102.84922],[35.144951,102.850227],[35.143131,102.848869],[35.142151,102.848541],[35.140621,102.848083],[35.1395,102.847763],[35.138168,102.847656],[35.137821,102.847679],[35.136589,102.847939],[35.13625,102.848083],[35.134949,102.848778],[35.13311,102.849907],[35.130322,102.850929],[35.12952,102.851608],[35.128719,102.85257],[35.127361,102.853859],[35.126019,102.855324],[35.114201,102.858513],[35.114029,102.860222],[35.113811,102.860641],[35.11343,102.861794],[35.11274,102.863426],[35.111851,102.86483],[35.110458,102.866867],[35.110008,102.867348],[35.108829,102.868202],[35.106941,102.869392],[35.1059,102.870377],[35.105209,102.871582],[35.104801,102.872726],[35.10276,102.878822],[35.101971,102.881264],[35.101219,102.882874],[35.100349,102.884193],[35.09911,102.886208],[35.09874,102.887062],[35.098228,102.888268],[35.097759,102.889137],[35.09724,102.889877],[35.096531,102.890739],[35.09597,102.891609],[35.095181,102.893143],[35.094181,102.894974],[35.093029,102.896812],[35.09185,102.898552],[35.091179,102.899857],[35.09074,102.90136],[35.09066,102.902786],[35.090691,102.903732],[35.090698,102.904198],[35.090401,102.905327],[35.090199,102.905724],[35.089939,102.906036],[35.089359,102.906487],[35.088699,102.906723],[35.088348,102.906731],[35.08746,102.906471],[35.086861,102.906021],[35.085949,102.905281],[35.085789,102.905167],[35.084629,102.90464],[35.084122,102.904533],[35.083241,102.904503],[35.08252,102.904678],[35.082439,102.905113],[35.080551,102.905243],[35.080002,102.905342],[35.07943,102.905388],[35.078529,102.905533],[35.077862,102.905724],[35.07674,102.906197],[35.076092,102.906303],[35.075779,102.906281],[35.075321,102.906151],[35.074951,102.905998],[35.074261,102.905907],[35.073589,102.905968],[35.073021,102.906273],[35.0728,102.906464],[35.07222,102.907021],[35.07185,102.907333],[35.070881,102.907707],[35.07037,102.90773],[35.069679,102.907471],[35.069519,102.907372],[35.06921,102.907112],[35.06815,102.905968],[35.067699,102.905647],[35.066841,102.905418],[35.066139,102.905472],[35.065319,102.905853],[35.06353,102.906998],[35.060638,102.908791],[35.059471,102.909378],[35.05872,102.909523],[35.057129,102.909554],[35.05666,102.909569],[35.055828,102.909561],[35.055069,102.909683],[35.05476,102.909767],[35.054298,102.909988],[35.053692,102.910393],[35.053219,102.910629],[35.052132,102.911293],[35.05164,102.911552],[35.051029,102.911957],[35.050388,102.9123],[35.049751,102.912727],[35.049061,102.913116],[35.0485,102.913307],[35.047729,102.91349],[35.04673,102.913612],[35.045731,102.913612],[35.045341,102.913628],[35.04422,102.91391],[35.043549,102.914284],[35.043388,102.914413],[35.042709,102.915176],[35.042332,102.915733],[35.041721,102.916733],[35.04084,102.918243],[35.040649,102.918663],[35.04018,102.919487],[35.03981,102.920067],[35.039669,102.920258],[35.038979,102.920837],[35.034828,102.92321],[35.034069,102.923576],[35.033489,102.923683],[35.032349,102.923714],[35.031311,102.924141],[35.03067,102.924637],[35.030319,102.92485],[35.029362,102.925087],[35.028751,102.925011],[35.027981,102.924629],[35.02702,102.924057],[35.02623,102.923759],[35.025589,102.923683],[35.025311,102.923691],[35.02446,102.924072],[35.023602,102.924522],[35.023251,102.924591],[35.022881,102.924622],[35.022148,102.924583],[35.021389,102.924629],[35.020828,102.924843],[35.020691,102.924896],[35.020302,102.925171],[35.019508,102.925797],[35.018921,102.926018],[35.017399,102.926132],[35.017029,102.926201],[35.01582,102.92659],[35.015659,102.926613],[35.014999,102.926613],[35.0144,102.926361],[35.01395,102.926071],[35.013599,102.925758],[35.01334,102.925507],[35.01223,102.924316],[35.011372,102.923477],[35.010792,102.922783],[35.010441,102.922287],[35.01025,102.921921],[35.01001,102.921494],[35.00967,102.9207],[35.008801,102.918907],[35.008308,102.917824],[35.007332,102.915756],[35.005859,102.912498],[35.00528,102.91127],[35.004841,102.910263],[35.004608,102.909851],[35.00452,102.909607],[35.00441,102.909309],[35.004002,102.908371],[35.003311,102.906532],[35.002911,102.905418],[35.00272,102.904968],[35.002331,102.904541],[35.00214,102.904472],[35.001499,102.904503],[35.000359,102.904617],[34.999981,102.904694],[34.998661,102.905273],[34.99477,102.905273],[34.993271,102.904968],[34.993111,102.906036],[34.993172,102.906326],[34.993172,102.906883],[34.993061,102.907677],[34.992901,102.9077],[34.992901,102.907707],[34.99292,102.907784],[34.992962,102.908218],[34.993011,102.908371],[34.99297,102.908592],[34.992722,102.908707],[34.99202,102.90873],[34.990101,102.908607],[34.989811,102.908546],[34.98624,102.908333],[34.97057,102.907372],[34.970188,102.907257],[34.96883,102.907173],[34.968571,102.907097],[34.968449,102.906738],[34.968349,102.906082],[34.96822,102.905457],[34.967999,102.904533],[34.967899,102.904167],[34.967709,102.903862],[34.967522,102.903618],[34.967319,102.90345],[34.966942,102.903412],[34.96677,102.903374],[34.966469,102.903259],[34.966099,102.903061],[34.965698,102.902763],[34.96529,102.902351],[34.965,102.90197],[34.964722,102.90155],[34.96365,102.899529],[34.96339,102.899071],[34.96312,102.898552],[34.962379,102.897202],[34.961761,102.896187],[34.961559,102.895844],[34.961151,102.895271],[34.960979,102.894951],[34.96072,102.894524],[34.960529,102.894287],[34.960339,102.893967],[34.958981,102.892014],[34.958031,102.890839],[34.957039,102.889557],[34.956711,102.889183],[34.954849,102.886749],[34.954552,102.886398],[34.95417,102.885887],[34.953442,102.884987],[34.95295,102.884338],[34.95298,102.884361],[34.952621,102.883888],[34.95232,102.883553],[34.950809,102.881683],[34.949909,102.880409],[34.949902,102.880363],[34.949459,102.879562],[34.949249,102.879082],[34.948891,102.878151],[34.94838,102.876427],[34.94825,102.875931],[34.94809,102.875397],[34.947899,102.874863],[34.947491,102.873863],[34.94685,102.872551],[34.946629,102.872147],[34.945992,102.871132],[34.945702,102.870758],[34.945068,102.870163],[34.944729,102.869919],[34.944359,102.869698],[34.94392,102.869476],[34.943031,102.869164],[34.9426,102.86898],[34.94141,102.868584],[34.940441,102.868263],[34.940182,102.868202],[34.94017,102.868172],[34.93821,102.867638],[34.92548,102.864548],[34.924671,102.864166],[34.924419,102.864082],[34.924049,102.864014],[34.923771,102.863907],[34.921612,102.863007],[34.920521,102.862503],[34.919701,102.862137],[34.919361,102.862007],[34.919041,102.861908],[34.91869,102.861847],[34.917961,102.861893],[34.917591,102.861954],[34.91721,102.862061],[34.916382,102.862396],[34.915192,102.862839],[34.91394,102.863182],[34.90559,102.863182],[34.905281,102.86306],[34.90493,102.862877],[34.904579,102.86264],[34.904289,102.862381],[34.90379,102.861794],[34.903591,102.861473],[34.903091,102.860428],[34.902969,102.860107],[34.902748,102.859421],[34.90255,102.858582],[34.902401,102.857788],[34.90229,102.856934],[34.90226,102.855743],[34.902302,102.854851],[34.902699,102.843513],[34.902748,102.843033],[34.902802,102.842773],[34.902882,102.842484],[34.902969,102.842239],[34.903091,102.841988],[34.903259,102.841743],[34.90345,102.841476],[34.903641,102.841309],[34.903839,102.841148],[34.90427,102.840889],[34.90451,102.840767],[34.904919,102.840477],[34.90519,102.840347],[34.90554,102.840111],[34.905949,102.839867],[34.9062,102.839684],[34.906399,102.8395],[34.906651,102.839073],[34.90675,102.838837],[34.906841,102.838516],[34.906841,102.838203],[34.906799,102.837883],[34.906731,102.837639],[34.906609,102.837341],[34.906422,102.837128],[34.9062,102.836983],[34.905891,102.836929],[34.905659,102.837013],[34.905479,102.837128],[34.905289,102.837334],[34.904961,102.837769],[34.9048,102.837929],[34.90456,102.838112],[34.904369,102.838158],[34.90416,102.838158],[34.90387,102.838058],[34.903702,102.837914],[34.903561,102.8377],[34.90345,102.83744],[34.9034,102.837181],[34.903358,102.8367],[34.903389,102.834],[34.90337,102.833641],[34.903309,102.833313],[34.90316,102.833023],[34.902889,102.832733],[34.902481,102.832588],[34.902111,102.83255],[34.901699,102.832443],[34.90139,102.832268],[34.901291,102.832199],[34.90126,102.832207],[34.900959,102.832062],[34.90073,102.831909],[34.900188,102.831413],[34.899799,102.830994],[34.899551,102.830391],[34.89954,102.829742],[34.89975,102.828796],[34.900291,102.826729],[34.900459,102.826141],[34.900791,102.825249],[34.901192,102.824402],[34.901939,102.823067],[34.902519,102.821953],[34.902809,102.820869],[34.902828,102.820053],[34.90266,102.818581],[34.90242,102.817253],[34.902142,102.816521],[34.90155,102.816017],[34.901119,102.815987],[34.90094,102.816032],[34.900219,102.81646],[34.89735,102.818604],[34.89658,102.819038],[34.896309,102.81913],[34.895592,102.81926],[34.89455,102.81913],[34.894299,102.819038],[34.894279,102.819054],[34.893848,102.818817],[34.891331,102.817307],[34.890549,102.816818],[34.88974,102.816223],[34.889099,102.81562],[34.88662,102.813263],[34.885929,102.812698],[34.885239,102.812553],[34.883179,102.812737],[34.882179,102.812881],[34.881531,102.813217],[34.880081,102.814484],[34.879219,102.815117],[34.87833,102.815407],[34.876251,102.815826],[34.87524,102.816177],[34.87442,102.816704],[34.8736,102.817513],[34.871979,102.819473],[34.871269,102.820374],[34.87011,102.822029],[34.868389,102.825363],[34.8675,102.827492],[34.867031,102.82843],[34.866348,102.829491],[34.865631,102.830368],[34.86274,102.833412],[34.862671,102.833473],[34.862171,102.833946],[34.861832,102.834343],[34.86105,102.835129],[34.8605,102.835587],[34.859859,102.836037],[34.859131,102.836388],[34.85902,102.836411],[34.85841,102.836441],[34.856838,102.836319],[34.85606,102.836372],[34.855518,102.83654],[34.854542,102.836899],[34.85199,102.837784],[34.851212,102.838028],[34.850399,102.838058],[34.849541,102.837807],[34.847771,102.83709],[34.846642,102.836693],[34.845551,102.836502],[34.84444,102.836479],[34.84346,102.836617],[34.842529,102.836884],[34.838779,102.838303],[34.837971,102.838623],[34.836941,102.838989],[34.836239,102.839203],[34.835381,102.839401],[34.834461,102.839531],[34.83366,102.839577],[34.832821,102.839577],[34.83197,102.8395],[34.831059,102.839348],[34.830219,102.839012],[34.82938,102.838501],[34.8284,102.837921],[34.827801,102.837502],[34.828339,102.837227],[34.8283,102.836708],[34.827179,102.836128],[34.827049,102.835678],[34.826839,102.834747],[34.826328,102.83239],[34.82626,102.831909],[34.826221,102.831367],[34.825481,102.809509],[34.82452,102.804512],[34.824749,102.800652],[34.82336,102.796608],[34.823029,102.794762],[34.822659,102.792732],[34.82222,102.790337],[34.82225,102.789932],[34.82235,102.789238],[34.822399,102.788689],[34.822479,102.788254],[34.822819,102.78569],[34.82291,102.78476],[34.822922,102.784363],[34.822948,102.783829],[34.82283,102.782516],[34.822781,102.782173],[34.822762,102.781914],[34.822659,102.781242],[34.822479,102.78022],[34.822361,102.77935],[34.822289,102.778992],[34.822231,102.77858],[34.8218,102.77594],[34.82169,102.775124],[34.82148,102.773903],[34.821281,102.772614],[34.821251,102.772308],[34.821159,102.771797],[34.82077,102.769218],[34.820641,102.768478],[34.820499,102.767776],[34.82032,102.767067],[34.82,102.766113],[34.81992,102.765938],[34.81881,102.76329],[34.817699,102.760696],[34.817261,102.759697],[34.816891,102.758812],[34.816559,102.758057],[34.816399,102.757668],[34.816101,102.757004],[34.815361,102.755127],[34.81501,102.754242],[34.814602,102.753212],[34.814301,102.752411],[34.81414,102.752022],[34.814011,102.751694],[34.813309,102.749931],[34.812111,102.746841],[34.81181,102.746033],[34.811581,102.745331],[34.811359,102.744476],[34.811249,102.743782],[34.811211,102.743439],[34.811161,102.743103],[34.811131,102.742279],[34.81115,102.741661],[34.811211,102.740913],[34.81134,102.740082],[34.81142,102.739647],[34.811649,102.738876],[34.811939,102.738121],[34.812569,102.736847],[34.812939,102.736191],[34.813702,102.734894],[34.81395,102.734512],[34.814281,102.73394],[34.814442,102.733627],[34.814701,102.733047],[34.814831,102.732674],[34.814941,102.732277],[34.815048,102.731667],[34.815029,102.731659],[34.815189,102.730492],[34.81522,102.730164],[34.815319,102.729599],[34.815411,102.728943],[34.81546,102.72863],[34.815491,102.728317],[34.815609,102.727676],[34.815632,102.727371],[34.815681,102.727142],[34.815811,102.726151],[34.81591,102.725548],[34.815979,102.724693],[34.815971,102.723831],[34.815922,102.723358],[34.81583,102.722801],[34.815731,102.722366],[34.81546,102.72139],[34.813671,102.702057],[34.813679,102.701981],[34.813641,102.701767],[34.813622,102.701439],[34.81358,102.701263],[34.81353,102.700867],[34.81329,102.699417],[34.813221,102.699097],[34.813171,102.698761],[34.812931,102.697617],[34.812698,102.696899],[34.81258,102.696678],[34.81245,102.696259],[34.811798,102.69503],[34.810711,102.6931],[34.80978,102.691353],[34.80933,102.69059],[34.808609,102.689217],[34.807819,102.687881],[34.807301,102.687149],[34.806492,102.686287],[34.806389,102.68618],[34.805779,102.685753],[34.804722,102.685097],[34.80024,102.682579],[34.798962,102.681671],[34.798031,102.68074],[34.797771,102.68045],[34.796791,102.679237],[34.795681,102.677917],[34.794701,102.676682],[34.793739,102.675369],[34.792339,102.673683],[34.79084,102.672112],[34.790329,102.671608],[34.789688,102.671013],[34.78886,102.67012],[34.7882,102.669006],[34.787392,102.667397],[34.786709,102.666054],[34.786228,102.665031],[34.785648,102.663887],[34.785099,102.662712],[34.784191,102.660843],[34.783691,102.659462],[34.783642,102.659241],[34.783249,102.657211],[34.783051,102.656487],[34.782711,102.65522],[34.782429,102.653969],[34.781731,102.651283],[34.781391,102.649628],[34.78133,102.647057],[34.7812,102.644676],[34.781181,102.643707],[34.781181,102.641258],[34.78093,102.639847],[34.780602,102.638451],[34.78027,102.637558],[34.779869,102.636703],[34.77692,102.631866],[34.77594,102.630173],[34.775299,102.629143],[34.774818,102.628311],[34.774311,102.627243],[34.773731,102.625763],[34.773201,102.624527],[34.77282,102.623756],[34.77142,102.62188],[34.77108,102.621521],[34.770821,102.621147],[34.77055,102.620667],[34.770279,102.620064],[34.769798,102.619324],[34.769329,102.618683],[34.767971,102.617058],[34.767368,102.616386],[34.766109,102.615143],[34.765209,102.614143],[34.764912,102.613869],[34.764641,102.613586],[34.763229,102.611977],[34.762489,102.611],[34.76207,102.610291],[34.761742,102.609581],[34.76152,102.6092],[34.760941,102.608047],[34.759949,102.60598],[34.75972,102.605438],[34.75909,102.604111],[34.75845,102.603073],[34.75753,102.601501],[34.756649,102.600288],[34.75621,102.599533],[34.75499,102.597313],[34.75415,102.595909],[34.753601,102.594887],[34.753201,102.593872],[34.753159,102.593674],[34.75293,102.591904],[34.752861,102.590759],[34.752949,102.589401],[34.753078,102.588303],[34.75351,102.586922],[34.75565,102.579758],[34.75584,102.578217],[34.755981,102.576653],[34.756039,102.576088],[34.75629,102.574623],[34.7565,102.57196],[34.756531,102.571327],[34.75676,102.568359],[34.756779,102.567932],[34.75708,102.564949],[34.757191,102.564148],[34.757309,102.563568],[34.75753,102.56205],[34.757702,102.560501],[34.757729,102.559914],[34.75769,102.55909],[34.757641,102.558891],[34.75716,102.557549],[34.756889,102.557037],[34.75618,102.556236],[34.755322,102.55571],[34.754429,102.555428],[34.753979,102.555321],[34.752979,102.555206],[34.750229,102.554993],[34.749149,102.554863],[34.74852,102.554703],[34.747108,102.554283],[34.746811,102.554123],[34.746132,102.55365],[34.745998,102.553543],[34.745251,102.552658],[34.74506,102.55217],[34.744949,102.55172],[34.744862,102.551529],[34.74464,102.550888],[34.744049,102.549103],[34.743271,102.547394],[34.742561,102.546082],[34.74268,102.54583],[34.74239,102.545258],[34.742222,102.544983],[34.741859,102.544289],[34.741718,102.543991],[34.74144,102.54348],[34.740608,102.541634],[34.740349,102.540916],[34.739979,102.539757],[34.739399,102.537689],[34.73888,102.535637],[34.73838,102.533928],[34.738071,102.532784],[34.73782,102.531952],[34.737358,102.530571],[34.73682,102.529381],[34.73637,102.52861],[34.736069,102.528183],[34.73502,102.526894],[34.73431,102.526207],[34.733829,102.525833],[34.73296,102.525223],[34.732029,102.524673],[34.731319,102.524223],[34.726311,102.521217],[34.723518,102.519577],[34.722172,102.518883],[34.72105,102.518623],[34.719391,102.51841],[34.717651,102.518143],[34.717461,102.518097],[34.71558,102.517487],[34.71307,102.51667],[34.709629,102.515488],[34.708309,102.515083],[34.707741,102.514877],[34.70652,102.51416],[34.705318,102.513],[34.704071,102.511543],[34.703339,102.510597],[34.70274,102.509758],[34.702259,102.508583],[34.70203,102.507317],[34.70182,102.505287],[34.701599,102.502953],[34.70126,102.500847],[34.700729,102.498833],[34.700359,102.49704],[34.700291,102.49659],[34.700001,102.494347],[34.699799,102.493042],[34.69915,102.491188],[34.698078,102.490112],[34.696999,102.489166],[34.695801,102.488373],[34.69511,102.488029],[34.694759,102.4879],[34.69408,102.487679],[34.692692,102.487457],[34.690979,102.487511],[34.689369,102.487808],[34.68774,102.488319],[34.685471,102.489143],[34.683971,102.489433],[34.68269,102.489357],[34.682259,102.489273],[34.68082,102.488647],[34.679729,102.487808],[34.678478,102.486389],[34.67598,102.483437],[34.674229,102.4813],[34.67318,102.479584],[34.672508,102.4786],[34.67181,102.478119],[34.671429,102.477966],[34.671051,102.477898],[34.668739,102.477768],[34.667679,102.477547],[34.667271,102.477371],[34.665409,102.476357],[34.664761,102.476143],[34.662941,102.475693],[34.66077,102.475197],[34.659939,102.474907],[34.659328,102.474617],[34.65836,102.47403],[34.657051,102.473282],[34.65633,102.472839],[34.655609,102.472458],[34.654861,102.472214],[34.65448,102.472153],[34.654079,102.47213],[34.653461,102.472183],[34.651669,102.47242],[34.650768,102.472382],[34.6492,102.472054],[34.648781,102.471931],[34.647369,102.471687],[34.646561,102.471687],[34.64637,102.471703],[34.64497,102.472054],[34.64394,102.472504],[34.642288,102.473297],[34.640911,102.473801],[34.640308,102.473846],[34.63929,102.473633],[34.638321,102.473129],[34.636902,102.472618],[34.635311,102.472473],[34.633961,102.472221],[34.633759,102.472153],[34.63192,102.471359],[34.629452,102.470207],[34.628571,102.469833],[34.627731,102.469353],[34.626911,102.468842],[34.626579,102.468613],[34.624931,102.467598],[34.62447,102.467377],[34.623749,102.467003],[34.620998,102.465317],[34.619572,102.464363],[34.617699,102.462662],[34.617031,102.462303],[34.6161,102.461952],[34.61515,102.461853],[34.61438,102.461983],[34.61335,102.46241],[34.612289,102.463211],[34.611771,102.463799],[34.611141,102.464928],[34.610661,102.466003],[34.610538,102.466187],[34.610062,102.46682],[34.609459,102.467216],[34.608841,102.467323],[34.608318,102.467293],[34.607849,102.467133],[34.607441,102.466827],[34.606098,102.465607],[34.605228,102.464577],[34.60186,102.460617],[34.601051,102.459717],[34.59996,102.458519],[34.597759,102.456078],[34.597462,102.455803],[34.59639,102.455307],[34.595989,102.455292],[34.595409,102.455429],[34.594521,102.455887],[34.594219,102.456169],[34.593861,102.456657],[34.59367,102.45694],[34.593369,102.457336],[34.593029,102.45787],[34.591129,102.46077],[34.588699,102.464363],[34.58794,102.46537],[34.58733,102.46595],[34.586712,102.466316],[34.58577,102.46666],[34.584919,102.466667],[34.584469,102.466583],[34.583969,102.466507],[34.582829,102.466202],[34.582531,102.466187],[34.582298,102.466118],[34.58157,102.466019],[34.578449,102.46534],[34.577202,102.464851],[34.575939,102.464088],[34.574711,102.463013],[34.573879,102.461967],[34.573132,102.460823],[34.570789,102.456993],[34.56992,102.455521],[34.568779,102.454231],[34.567451,102.453133],[34.56498,102.451134],[34.563641,102.449997],[34.56292,102.44928],[34.56282,102.449142],[34.56234,102.448418],[34.560749,102.445572],[34.55888,102.442146],[34.558361,102.441238],[34.556309,102.437523],[34.555641,102.436447],[34.55505,102.435829],[34.554169,102.435059],[34.553329,102.434258],[34.552429,102.432999],[34.55085,102.430573],[34.549931,102.429123],[34.549271,102.428207],[34.548389,102.427467],[34.547298,102.426773],[34.546532,102.425888],[34.546001,102.424759],[34.54562,102.423302],[34.545071,102.421654],[34.544369,102.420593],[34.54319,102.419388],[34.542789,102.418854],[34.542461,102.418289],[34.542191,102.417671],[34.541901,102.41658],[34.54158,102.414993],[34.541168,102.413979],[34.540581,102.413132],[34.53854,102.410606],[34.537159,102.408981],[34.536518,102.408287],[34.53492,102.407066],[34.53458,102.406693],[34.53373,102.405434],[34.53315,102.404007],[34.532421,102.40184],[34.531719,102.400589],[34.53067,102.399391],[34.52882,102.397598],[34.52821,102.396782],[34.526871,102.394547],[34.525902,102.39312],[34.525051,102.392174],[34.523788,102.390823],[34.522869,102.389793],[34.521931,102.388527],[34.52145,102.38765],[34.520679,102.386192],[34.519939,102.384987],[34.519279,102.384018],[34.518421,102.382797],[34.517941,102.38208],[34.516659,102.380219],[34.515621,102.378754],[34.514771,102.376633],[34.50613,102.368523],[34.505322,102.366173],[34.5037,102.363876],[34.501049,102.359802],[34.500092,102.358276],[34.49889,102.3563],[34.497841,102.354683],[34.496971,102.353416],[34.495789,102.352112],[34.494671,102.351784],[34.48978,102.338341],[34.490662,102.336861],[34.490559,102.335258],[34.490429,102.333649],[34.490398,102.333054],[34.490261,102.331688],[34.490219,102.330711],[34.490131,102.329948],[34.489769,102.328743],[34.4893,102.32785],[34.488739,102.327042],[34.487259,102.325104],[34.48687,102.324623],[34.486191,102.323677],[34.485748,102.322968],[34.485409,102.32235],[34.485249,102.322037],[34.48457,102.320282],[34.483841,102.318626],[34.480789,102.313278],[34.479919,102.311729],[34.478199,102.308777],[34.477699,102.308037],[34.477131,102.307373],[34.47683,102.307083],[34.476021,102.306396],[34.472462,102.303352],[34.471939,102.302994],[34.47176,102.302872],[34.470989,102.302498],[34.470181,102.302277],[34.469139,102.302208],[34.468719,102.302254],[34.46809,102.302391],[34.467178,102.303284],[34.466572,102.302879],[34.465462,102.303436],[34.464691,102.303574],[34.46426,102.303612],[34.463089,102.303551],[34.462589,102.303452],[34.461342,102.302994],[34.460819,102.30275],[34.455811,102.300583],[34.45499,102.30027],[34.45414,102.300056],[34.453041,102.299957],[34.450451,102.300034],[34.44627,102.300171],[34.445278,102.300171],[34.44389,102.299896],[34.441971,102.299477],[34.439621,102.298927],[34.431759,102.297218],[34.429379,102.296806],[34.426949,102.296707],[34.426071,102.296623],[34.425629,102.296516],[34.424591,102.296173],[34.42358,102.295723],[34.42215,102.295219],[34.421108,102.295021],[34.419628,102.294083],[34.41708,102.29528],[34.413521,102.295677],[34.410141,102.296028],[34.40892,102.29612],[34.398399,102.297173],[34.394421,102.297592],[34.393822,102.297684],[34.392269,102.298111],[34.38921,102.299088],[34.38755,102.299583],[34.38662,102.299812],[34.382931,102.300613],[34.380459,102.301064],[34.379219,102.301178],[34.378189,102.301247],[34.37674,102.301529],[34.372559,102.302727],[34.370708,102.303192],[34.369881,102.303368],[34.364689,102.304161],[34.363022,102.304207],[34.359451,102.303726],[34.358231,102.303619],[34.357208,102.303612],[34.353741,102.303864],[34.352852,102.303909],[34.35051,102.304108],[34.350021,102.304199],[34.349758,102.304291],[34.348721,102.304733],[34.347759,102.305511],[34.346939,102.306488],[34.34655,102.307022],[34.346069,102.307747],[34.345402,102.308563],[34.344791,102.309082],[34.344631,102.309189],[34.34396,102.309593],[34.343269,102.309853],[34.34251,102.310028],[34.341579,102.310066],[34.338428,102.3097],[34.33593,102.309433],[34.33326,102.309067],[34.33086,102.308769],[34.32967,102.30835],[34.329151,102.307983],[34.328819,102.307709],[34.32795,102.306801],[34.327499,102.306381],[34.326248,102.305489],[34.325771,102.305237],[34.325089,102.304947],[34.32362,102.304588],[34.32235,102.30468],[34.321461,102.304947],[34.319901,102.305779],[34.318371,102.30661],[34.31649,102.307579],[34.31612,102.307793],[34.315159,102.308479],[34.313511,102.309837],[34.310379,102.312492],[34.308121,102.314293],[34.305241,102.316673],[34.303188,102.318352],[34.301781,102.319527],[34.297661,102.322906],[34.296581,102.323822],[34.29166,102.327873],[34.291111,102.328346],[34.289768,102.329712],[34.288582,102.331207],[34.280128,102.343491],[34.27388,102.352661],[34.27211,102.355057],[34.270851,102.356216],[34.268822,102.357643],[34.266102,102.359451],[34.262959,102.361519],[34.26181,102.362518],[34.260311,102.364166],[34.257961,102.366676],[34.248569,102.377083],[34.247108,102.378723],[34.24577,102.38015],[34.244541,102.381317],[34.24242,102.383034],[34.23119,102.391983],[34.222839,102.39859],[34.221378,102.399857],[34.220169,102.401161],[34.218891,102.402946],[34.215382,102.408546],[34.213509,102.411499],[34.20911,102.417763],[34.20789,102.418282],[34.207649,102.419868],[34.205429,102.422913],[34.204109,102.424973],[34.203629,102.426666],[34.203098,102.428757],[34.20248,102.432091],[34.20042,102.442657],[34.197849,102.456253],[34.1973,102.459023],[34.19706,102.460426],[34.196369,102.464111],[34.196129,102.466629],[34.195629,102.474739],[34.195271,102.477531],[34.193829,102.483788],[34.1926,102.486267],[34.19241,102.489609],[34.191132,102.493523],[34.189491,102.497711],[34.189571,102.501793],[34.188831,102.504898],[34.188229,102.508217],[34.18763,102.509987],[34.186218,102.515877],[34.185211,102.520317],[34.183899,102.525864],[34.183189,102.528763],[34.182529,102.531616],[34.181938,102.534042],[34.181278,102.536423],[34.180641,102.538559],[34.179699,102.541634],[34.17907,102.5439],[34.178169,102.546806],[34.177151,102.550217],[34.176739,102.55175],[34.176121,102.553719],[34.175461,102.555748],[34.17477,102.557159],[34.17395,102.558182],[34.17289,102.558884],[34.171749,102.559273],[34.170589,102.559387],[34.168159,102.559578],[34.16251,102.560081],[34.160141,102.560318],[34.15765,102.560509],[34.15731,102.560608],[34.157009,102.560783],[34.15667,102.561234],[34.155861,102.562752],[34.154591,102.564873],[34.154411,102.565613],[34.154419,102.565758],[34.154598,102.566277],[34.154881,102.566757],[34.155289,102.567383],[34.155651,102.567993],[34.155701,102.568123],[34.15572,102.568939],[34.155331,102.569717],[34.1549,102.570488],[34.154251,102.571564],[34.154091,102.571739],[34.15382,102.571907],[34.15242,102.572319],[34.151798,102.572937],[34.151661,102.573471],[34.151508,102.574753],[34.151279,102.577316],[34.150928,102.580673],[34.150951,102.581352],[34.151138,102.583923],[34.15094,102.584732],[34.150742,102.584976],[34.15062,102.585083],[34.15036,102.585197],[34.148972,102.585426],[34.146721,102.585762],[34.146019,102.585907],[34.145489,102.586121],[34.14447,102.586723],[34.14291,102.587181],[34.1423,102.58741],[34.141529,102.58786],[34.14101,102.588257],[34.140419,102.588898],[34.139992,102.589684],[34.137878,102.594872],[34.137569,102.595581],[34.137058,102.596458],[34.136478,102.597252],[34.136108,102.597794],[34.135769,102.598373],[34.135502,102.59919],[34.135269,102.599823],[34.134621,102.600739],[34.13414,102.601173],[34.133541,102.601761],[34.132969,102.602966],[34.13279,102.603416],[34.132259,102.604134],[34.131371,102.605133],[34.130749,102.605881],[34.130569,102.606178],[34.13039,102.606453],[34.129902,102.607567],[34.129478,102.608711],[34.129021,102.609818],[34.128429,102.610817],[34.128059,102.611389],[34.125,102.616364],[34.123699,102.618591],[34.12326,102.619942],[34.123058,102.621437],[34.123169,102.623863],[34.12286,102.62487],[34.122269,102.625343],[34.121922,102.625443],[34.120152,102.62561],[34.11916,102.629173],[34.117748,102.629852],[34.11734,102.630692],[34.11689,102.631721],[34.116718,102.632317],[34.11668,102.632736],[34.116741,102.633392],[34.117569,102.634941],[34.117119,102.636574],[34.117851,102.637733],[34.117489,102.639999],[34.11742,102.640556],[34.11742,102.640762],[34.117611,102.641777],[34.117809,102.642403],[34.118019,102.64315],[34.118118,102.64357],[34.118328,102.644272],[34.118549,102.645073],[34.118622,102.645287],[34.11869,102.6455],[34.118961,102.646332],[34.119091,102.646553],[34.119579,102.646988],[34.12048,102.647331],[34.120602,102.647346],[34.120838,102.647476],[34.121189,102.647629],[34.121571,102.647881],[34.12178,102.648064],[34.122101,102.648453],[34.122299,102.648804],[34.122421,102.649071],[34.12252,102.649559],[34.12254,102.650414],[34.12241,102.651123],[34.12159,102.654167],[34.12141,102.654877],[34.120789,102.657181],[34.120602,102.657951],[34.119202,102.663193],[34.11874,102.664993],[34.117939,102.667877],[34.117481,102.669327],[34.117271,102.669952],[34.116741,102.671371],[34.116451,102.672081],[34.11586,102.673431],[34.115139,102.674973],[34.114189,102.67688],[34.113899,102.67749],[34.113861,102.677513],[34.113602,102.678078],[34.11298,102.679298],[34.111851,102.681679],[34.11161,102.682251],[34.111301,102.683113],[34.110828,102.684723],[34.110661,102.68541],[34.11026,102.686928],[34.10931,102.690353],[34.108589,102.693024],[34.108318,102.694092],[34.107891,102.695663],[34.107639,102.696693],[34.10741,102.697479],[34.107201,102.698318],[34.106979,102.699112],[34.1068,102.699806],[34.106602,102.700508],[34.10611,102.702332],[34.105911,102.703239],[34.10569,102.704292],[34.105518,102.705276],[34.10527,102.70755],[34.105209,102.708504],[34.10516,102.709648],[34.105122,102.711617],[34.105061,102.712791],[34.104931,102.713821],[34.104752,102.714607],[34.104321,102.715973],[34.104279,102.716187],[34.104019,102.716766],[34.10371,102.71772],[34.103432,102.71846],[34.103142,102.71933],[34.102959,102.720306],[34.10294,102.720757],[34.103001,102.72171],[34.10358,102.725479],[34.10368,102.726471],[34.10368,102.727333],[34.103619,102.727814],[34.103371,102.728653],[34.102989,102.729439],[34.102558,102.730049],[34.102509,102.730164],[34.10207,102.730568],[34.10099,102.731247],[34.100201,102.731697],[34.098301,102.732727],[34.09761,102.733131],[34.09655,102.733688],[34.095421,102.734306],[34.094818,102.734612],[34.094059,102.734802],[34.093418,102.734848],[34.092781,102.734718],[34.092171,102.734459],[34.091621,102.734123],[34.090931,102.733582],[34.090691,102.733414],[34.087151,102.730698],[34.086498,102.730301],[34.086021,102.730087],[34.085419,102.729973],[34.084221,102.729912],[34.08215,102.729851],[34.081181,102.729134],[34.07951,102.730637],[34.07851,102.729851],[34.077999,102.729927],[34.078018,102.729927],[34.077862,102.72998],[34.077381,102.730087],[34.07605,102.730476],[34.0742,102.730957],[34.073021,102.731308],[34.072559,102.731361],[34.072121,102.731377],[34.071659,102.731323],[34.071259,102.731216],[34.069962,102.730743],[34.0695,102.730553],[34.067268,102.729713],[34.06567,102.729057],[34.064571,102.728554],[34.062561,102.727524],[34.062019,102.727226],[34.05949,102.725906],[34.059021,102.725723],[34.058472,102.725548],[34.05484,102.724602],[34.054459,102.724518],[34.05402,102.724388],[34.053341,102.724113],[34.052719,102.723793],[34.04837,102.721077],[34.048031,102.720886],[34.04689,102.720177],[34.04665,102.720039],[34.04604,102.719757],[34.045361,102.719566],[34.044289,102.719398],[34.0443,102.719414],[34.044189,102.719414],[34.043919,102.71936],[34.043369,102.719299],[34.042461,102.719162],[34.042141,102.719139],[34.04137,102.719017],[34.04052,102.718941],[34.040279,102.71888],[34.039242,102.718773],[34.038658,102.718681],[34.038349,102.718658],[34.037701,102.718559],[34.036789,102.718437],[34.036201,102.718437],[34.03595,102.718483],[34.035679,102.718536],[34.035469,102.71862],[34.035061,102.718903],[34.034851,102.719101],[34.034481,102.719582],[34.034019,102.720261],[34.032318,102.722923],[34.032169,102.723129],[34.031799,102.723518],[34.031601,102.723686],[34.03141,102.723824],[34.03117,102.723953],[34.03093,102.724037],[34.030689,102.724113],[34.03043,102.724152],[34.03019,102.724136],[34.029148,102.72406],[34.028519,102.723984],[34.028259,102.723991],[34.027969,102.723953],[34.02771,102.723953],[34.027409,102.723999],[34.027111,102.724083],[34.026871,102.724167],[34.026611,102.724319],[34.026119,102.724693],[34.025501,102.725212],[34.025318,102.725319],[34.02512,102.725502],[34.024391,102.726021],[34.023659,102.726501],[34.023232,102.726753],[34.023048,102.726883],[34.022831,102.726997],[34.021309,102.72789],[34.021019,102.728081],[34.020611,102.728416],[34.020409,102.72863],[34.019951,102.729271],[34.019691,102.729782],[34.018902,102.731781],[34.018452,102.732986],[34.018139,102.733757],[34.017879,102.734299],[34.01767,102.734619],[34.017479,102.734863],[34.01725,102.735107],[34.017052,102.735359],[34.016781,102.735641],[34.013119,102.738113],[34.008789,102.741043],[34.00354,102.74456],[34.002659,102.745171],[34.002548,102.745232],[34.001911,102.745667],[34.001431,102.745911],[34.000221,102.746902],[33.99966,102.747452],[33.999161,102.748161],[33.998959,102.74855],[33.998829,102.748894],[33.998611,102.749763],[33.99855,102.750549],[33.998581,102.751427],[33.998661,102.752113],[33.99894,102.753883],[33.998981,102.754433],[33.99905,102.754868],[33.999142,102.755241],[33.999321,102.756371],[33.999962,102.760437],[34.00042,102.763367],[34.00053,102.764191],[34.00061,102.765053],[34.00058,102.765778],[34.00045,102.766693],[34.000111,102.767281],[33.99979,102.767883],[33.997421,102.771591],[33.997379,102.77169],[33.997211,102.771896],[33.9944,102.77623],[33.991291,102.781052],[33.990311,102.782539],[33.988289,102.785713],[33.98724,102.787323],[33.985649,102.789726],[33.984509,102.791489],[33.983978,102.792351],[33.982471,102.794647],[33.980518,102.797699],[33.980141,102.798248],[33.979351,102.799507],[33.978889,102.800194],[33.97575,102.805038],[33.97533,102.805717],[33.974899,102.806343],[33.97456,102.806892],[33.97398,102.807747],[33.97361,102.808327],[33.973179,102.808983],[33.97274,102.809677],[33.97234,102.81028],[33.971889,102.810997],[33.967892,102.817139],[33.966999,102.818527],[33.966179,102.819763],[33.965462,102.820877],[33.96508,102.821442],[33.96019,102.828987],[33.95985,102.829529],[33.956089,102.83532],[33.955639,102.836037],[33.955219,102.836662],[33.954239,102.838188],[33.953659,102.83905],[33.953629,102.839073],[33.953621,102.839127],[33.953159,102.839882],[33.950729,102.843613],[33.950432,102.844116],[33.949982,102.844757],[33.943562,102.854668],[33.941631,102.857613],[33.937241,102.864418],[33.936729,102.865189],[33.936131,102.865997],[33.935501,102.866768],[33.93491,102.867416],[33.934181,102.868118],[33.930019,102.871872],[33.929482,102.872414],[33.928982,102.873016],[33.928581,102.873756],[33.928459,102.874039],[33.928261,102.874702],[33.927151,102.879211],[33.926868,102.880211],[33.92659,102.880882],[33.926262,102.881554],[33.92585,102.882187],[33.925751,102.882309],[33.92522,102.882874],[33.924709,102.883324],[33.92411,102.883743],[33.921749,102.8853],[33.912102,102.891747],[33.909801,102.893257],[33.908459,102.894173],[33.90493,102.896492],[33.90419,102.897003],[33.902908,102.897842],[33.900631,102.899384],[33.894958,102.903137],[33.894371,102.903549],[33.88932,102.906891],[33.88871,102.907333],[33.888161,102.907669],[33.885799,102.909233],[33.885151,102.909683],[33.88385,102.910522],[33.880421,102.912827],[33.872849,102.917847],[33.871632,102.918694],[33.871029,102.91906],[33.861191,102.925621],[33.84753,102.934692],[33.843861,102.937149],[33.8433,102.937508],[33.839359,102.94014],[33.838619,102.940613],[33.837799,102.94117],[33.83699,102.941803],[33.83633,102.942436],[33.835701,102.943169],[33.83033,102.950912],[33.830059,102.951248],[33.82962,102.951691],[33.829041,102.952103],[33.828609,102.952293],[33.828289,102.952393],[33.827839,102.952477],[33.825901,102.952759],[33.825291,102.952873],[33.824951,102.952972],[33.82473,102.953056],[33.82378,102.95359],[33.82267,102.954277],[33.822578,102.954353],[33.821991,102.954712],[33.821289,102.955017],[33.82061,102.9552],[33.817371,102.955978],[33.815041,102.95649],[33.814362,102.956612],[33.813492,102.95665],[33.812759,102.956581],[33.811111,102.95649],[33.809631,102.956383],[33.808189,102.956322],[33.80751,102.956383],[33.806839,102.956612],[33.806271,102.956963],[33.80566,102.957474],[33.803619,102.959358],[33.802921,102.959923],[33.802151,102.96032],[33.801472,102.960487],[33.800758,102.96051],[33.800201,102.960388],[33.799492,102.960083],[33.798309,102.959412],[33.797821,102.959167],[33.797161,102.958946],[33.796391,102.958923],[33.79549,102.959068],[33.795151,102.959137],[33.794991,102.959137],[33.79488,102.95919],[33.789989,102.960152],[33.788921,102.960342],[33.788219,102.960487],[33.787189,102.960617],[33.786499,102.960617],[33.78574,102.960587],[33.784649,102.96048],[33.783852,102.960327],[33.781792,102.96003],[33.781132,102.959969],[33.78038,102.959976],[33.779659,102.960052],[33.778271,102.960243],[33.777191,102.960342],[33.775761,102.960533],[33.77491,102.960587],[33.77422,102.960609],[33.773399,102.960564],[33.772469,102.960442],[33.771858,102.960327],[33.7701,102.959953],[33.767799,102.959488],[33.763859,102.958656],[33.76247,102.958344],[33.760979,102.957939],[33.759571,102.957527],[33.758968,102.957336],[33.75602,102.956253],[33.75528,102.955994],[33.74733,102.953102],[33.746521,102.952003],[33.739429,102.953453],[33.73904,102.95488],[33.738609,102.955276],[33.738121,102.955704],[33.737041,102.956688],[33.73307,102.960243],[33.732578,102.960716],[33.731289,102.961899],[33.730652,102.962433],[33.72995,102.962967],[33.729382,102.963333],[33.72916,102.963417],[33.728291,102.963753],[33.72757,102.963913],[33.726791,102.963966],[33.720871,102.964233],[33.71986,102.964287],[33.719379,102.964302],[33.717449,102.964409],[33.711418,102.964668],[33.706329,102.964928],[33.704552,102.964989],[33.703678,102.964943],[33.7029,102.96479],[33.700619,102.964142],[33.699989,102.963997],[33.699162,102.963982],[33.69836,102.964157],[33.696911,102.964821],[33.6945,102.966003],[33.68998,102.968147],[33.689308,102.968353],[33.68885,102.96843],[33.68819,102.968384],[33.687592,102.968231],[33.687099,102.967987],[33.686779,102.967796],[33.686111,102.967247],[33.685181,102.966362],[33.684639,102.965912],[33.684299,102.965668],[33.683739,102.965393],[33.683189,102.965149],[33.682461,102.964928],[33.681049,102.964546],[33.68066,102.96447],[33.67968,102.964203],[33.679169,102.964073],[33.678822,102.963959],[33.677391,102.9636],[33.677269,102.963593],[33.676781,102.963371],[33.676491,102.963211],[33.67598,102.962837],[33.675831,102.962708],[33.674549,102.961243],[33.674171,102.960907],[33.673759,102.960617],[33.673061,102.96032],[33.67297,102.960274],[33.672691,102.960243],[33.672081,102.96022],[33.672058,102.960243],[33.671799,102.960251],[33.67091,102.960327],[33.669979,102.960426],[33.668468,102.960564],[33.667591,102.960587],[33.666801,102.96048],[33.66629,102.960281],[33.66592,102.960052],[33.66552,102.959747],[33.66534,102.959587],[33.665039,102.959244],[33.66473,102.958801],[33.663448,102.956543],[33.662201,102.954262],[33.66201,102.953957],[33.66161,102.953217],[33.661018,102.952362],[33.66029,102.951698],[33.659512,102.951286],[33.659019,102.951157],[33.65802,102.950996],[33.653961,102.950623],[33.65266,102.95047],[33.651711,102.950119],[33.65136,102.949898],[33.650639,102.949242],[33.649712,102.94828],[33.648491,102.946968],[33.64846,102.946907],[33.647911,102.946327],[33.647621,102.946083],[33.6474,102.945847],[33.647099,102.945572],[33.646801,102.945328],[33.64645,102.945084],[33.646141,102.944893],[33.645821,102.944748],[33.64521,102.944527],[33.644489,102.944389],[33.643711,102.944397],[33.64344,102.944443],[33.64278,102.944603],[33.64246,102.94471],[33.641861,102.945023],[33.641541,102.945221],[33.641239,102.945457],[33.640751,102.945892],[33.640251,102.946373],[33.63728,102.9496],[33.63625,102.950737],[33.635609,102.951401],[33.635101,102.951851],[33.634411,102.95224],[33.634312,102.952278],[33.633221,102.95253],[33.631989,102.952599],[33.631111,102.952782],[33.630299,102.953247],[33.62973,102.953773],[33.628448,102.955116],[33.627991,102.955566],[33.627449,102.955917],[33.626678,102.956131],[33.625938,102.956017],[33.625351,102.955704],[33.624329,102.954811],[33.624031,102.954567],[33.623772,102.954407],[33.623371,102.954208],[33.623089,102.954109],[33.622799,102.954048],[33.622501,102.95401],[33.622181,102.954018],[33.620621,102.954269],[33.620171,102.954308],[33.619781,102.954308],[33.61916,102.954224],[33.618759,102.954086],[33.618351,102.953903],[33.618019,102.95369],[33.617241,102.95314],[33.616989,102.952904],[33.616562,102.95256],[33.615978,102.952049],[33.615711,102.951843],[33.615139,102.951447],[33.614639,102.951218],[33.614071,102.951111],[33.613449,102.951157],[33.61269,102.951347],[33.612331,102.951462],[33.611542,102.95166],[33.61105,102.951683],[33.610149,102.951462],[33.609959,102.951347],[33.609249,102.950798],[33.609169,102.950706],[33.60878,102.950104],[33.607841,102.947853],[33.607712,102.94751],[33.607029,102.945877],[33.60688,102.945473],[33.606258,102.944077],[33.605999,102.943443],[33.606239,102.942429],[33.605961,102.942207],[33.605289,102.941772],[33.603168,102.941093],[33.602612,102.939697],[33.598629,102.938179],[33.598061,102.937988],[33.597691,102.937843],[33.597599,102.937843],[33.596951,102.937767],[33.59639,102.937759],[33.595661,102.93869],[33.594891,102.938461],[33.59399,102.938477],[33.59269,102.940697],[33.592319,102.940483],[33.592289,102.940483],[33.59235,102.940598],[33.592289,102.940742],[33.59235,102.941292],[33.59026,102.944901],[33.588982,102.944992],[33.588531,102.945557],[33.588219,102.94593],[33.58786,102.946457],[33.586781,102.947868],[33.586369,102.948547],[33.58622,102.948624],[33.58601,102.948837],[33.585121,102.949966],[33.584629,102.950562],[33.584221,102.950989],[33.583839,102.951408],[33.582951,102.952339],[33.582539,102.952797],[33.580509,102.954964],[33.579029,102.956596],[33.57869,102.95694],[33.577942,102.957771],[33.577641,102.958038],[33.57756,102.958092],[33.577511,102.958138],[33.577469,102.958168],[33.57653,102.961349],[33.576649,102.961388],[33.576839,102.9618],[33.577148,102.962677],[33.577599,102.964157],[33.577709,102.964577],[33.578209,102.965652],[33.577011,102.967728],[33.562309,102.992767],[33.56229,102.995613],[33.56152,102.997063],[33.560551,102.998123],[33.558681,102.998947],[33.55827,103.000237],[33.558331,103.003082],[33.55722,103.005333],[33.556961,103.007217],[33.556789,103.008347],[33.55669,103.00946],[33.55669,103.016533],[33.556629,103.018227],[33.556561,103.018593],[33.556301,103.019386],[33.556061,103.019974],[33.55497,103.022774],[33.554691,103.023613],[33.554531,103.024307],[33.554489,103.024986],[33.554611,103.025681],[33.554852,103.026299],[33.555038,103.026611],[33.55547,103.027077],[33.556049,103.027412],[33.556301,103.027473],[33.558159,103.027588],[33.558571,103.027443],[33.560741,103.027687],[33.562149,103.02787],[33.564812,103.028107],[33.56588,103.028259],[33.566101,103.028313],[33.566521,103.02845],[33.567268,103.028893],[33.568119,103.029701],[33.568401,103.03009],[33.568619,103.030518],[33.569099,103.031937],[33.56929,103.032692],[33.570278,103.03598],[33.570869,103.037613],[33.571529,103.038567],[33.571819,103.038918],[33.572639,103.039703],[33.57436,103.041023],[33.576141,103.042473],[33.577438,103.043503],[33.578541,103.044456],[33.57946,103.045403],[33.58009,103.046387],[33.580711,103.047668],[33.581051,103.048508],[33.581772,103.050163],[33.582081,103.050926],[33.582359,103.051498],[33.583759,103.054657],[33.584389,103.05619],[33.5853,103.058311],[33.585911,103.059708],[33.58717,103.062637],[33.587841,103.064102],[33.588612,103.066017],[33.589489,103.067993],[33.590069,103.069412],[33.59116,103.072006],[33.592331,103.0737],[33.592239,103.076012],[33.591888,103.077469],[33.588421,103.091187],[33.58823,103.093384],[33.587769,103.099693],[33.586311,103.101318],[33.58577,103.102692],[33.58519,103.103661],[33.584728,103.104362],[33.584541,103.104553],[33.583931,103.10508],[33.583511,103.105438],[33.582981,103.105759],[33.581848,103.106354],[33.576511,103.108421],[33.56625,103.112213],[33.562092,103.113823],[33.560051,103.114532],[33.557999,103.115288],[33.556381,103.115921],[33.554642,103.116798],[33.55278,103.118057],[33.540932,103.12635],[33.540051,103.126831],[33.53867,103.127197],[33.536831,103.127403],[33.534981,103.127831],[33.533508,103.128571],[33.532131,103.129562],[33.530449,103.130882],[33.528648,103.132103],[33.52784,103.132584],[33.526031,103.13372],[33.525089,103.134483],[33.523491,103.136093],[33.52187,103.137619],[33.520359,103.138779],[33.518581,103.139954],[33.51659,103.141243],[33.51403,103.142937],[33.512081,103.144287],[33.510559,103.145508],[33.5093,103.146713],[33.508282,103.147774],[33.506821,103.149513],[33.505219,103.151497],[33.503681,103.153297],[33.502419,103.154572],[33.501141,103.155182],[33.498909,103.156174],[33.49741,103.157066],[33.496059,103.158203],[33.494041,103.160233],[33.490829,103.163582],[33.4893,103.164886],[33.488022,103.165588],[33.48666,103.165993],[33.482281,103.167053],[33.48,103.167587],[33.47776,103.167923],[33.47578,103.167976],[33.47366,103.167992],[33.473042,103.168053],[33.472118,103.168411],[33.471451,103.168877],[33.46891,103.171303],[33.46743,103.172752],[33.466019,103.173973],[33.465092,103.174339],[33.464039,103.174347],[33.463402,103.17424],[33.460442,103.17347],[33.459129,103.173553],[33.458099,103.17395],[33.456661,103.174797],[33.452709,103.177162],[33.451981,103.177551],[33.450802,103.177933],[33.448799,103.178253],[33.4459,103.178673],[33.444172,103.178818],[33.442329,103.178841],[33.440689,103.178886],[33.43597,103.178757],[33.43486,103.178963],[33.434509,103.179077],[33.43354,103.179619],[33.432861,103.180191],[33.432621,103.180367],[33.428909,103.183418],[33.427761,103.184303],[33.426731,103.185028],[33.426079,103.185371],[33.424889,103.185768],[33.423561,103.186249],[33.42234,103.186783],[33.42144,103.187538],[33.420849,103.188568],[33.41993,103.190323],[33.419071,103.191368],[33.41795,103.1922],[33.416611,103.192886],[33.41518,103.193527],[33.414162,103.193932],[33.412579,103.19426],[33.411289,103.194458],[33.409969,103.194748],[33.409081,103.195297],[33.408409,103.195999],[33.407421,103.197197],[33.40657,103.198158],[33.40559,103.198967],[33.40443,103.199654],[33.403301,103.200119],[33.402142,103.200333],[33.400848,103.200493],[33.3992,103.20047],[33.39814,103.200737],[33.397228,103.201271],[33.395699,103.202797],[33.39473,103.20369],[33.393841,103.204552],[33.393452,103.204903],[33.39249,103.205544],[33.391548,103.20594],[33.39053,103.205963],[33.38789,103.205322],[33.3843,103.204483],[33.38155,103.203796],[33.380268,103.203644],[33.380119,103.203667],[33.37936,103.20401],[33.378689,103.204781],[33.377628,103.206673],[33.377392,103.20694],[33.376301,103.207603],[33.37542,103.207771],[33.375221,103.207787],[33.373589,103.207779],[33.371601,103.207703],[33.369869,103.20768],[33.368271,103.207527],[33.364609,103.206711],[33.363331,103.206749],[33.362511,103.206848],[33.35915,103.207161],[33.35651,103.207298],[33.354771,103.207253],[33.352612,103.206963],[33.350712,103.206741],[33.350052,103.206711],[33.348801,103.20694],[33.34761,103.207336],[33.346218,103.207764],[33.344971,103.207817],[33.34351,103.207718],[33.340851,103.207443],[33.339149,103.207283],[33.337589,103.207191],[33.33651,103.207367],[33.335629,103.207718],[33.335289,103.207893],[33.33448,103.208481],[33.33342,103.209343],[33.332958,103.209671],[33.331921,103.210167],[33.33073,103.210426],[33.328442,103.210587],[33.326839,103.21067],[33.32542,103.210709],[33.324169,103.210793],[33.322571,103.210983],[33.32114,103.211067],[33.31963,103.21125],[33.318501,103.211456],[33.318321,103.211517],[33.317341,103.212067],[33.317051,103.212341],[33.31641,103.213173],[33.315929,103.214523],[33.315769,103.215584],[33.315392,103.217644],[33.315022,103.218781],[33.31493,103.218964],[33.314308,103.219673],[33.31403,103.219887],[33.31282,103.220322],[33.310768,103.220886],[33.309471,103.221313],[33.308739,103.221474],[33.307789,103.221581],[33.307049,103.221519],[33.304871,103.221161],[33.30373,103.221107],[33.30304,103.221283],[33.301949,103.221893],[33.30154,103.222267],[33.3009,103.223007],[33.300018,103.223831],[33.29895,103.224327],[33.297581,103.224564],[33.296982,103.22464],[33.295471,103.22496],[33.294319,103.225349],[33.292728,103.226143],[33.291061,103.226891],[33.288261,103.227432],[33.286781,103.227943],[33.282139,103.229927],[33.280621,103.230652],[33.276501,103.233047],[33.274921,103.234009],[33.273731,103.234467],[33.27227,103.234741],[33.271271,103.23468],[33.270931,103.234619],[33.27002,103.234413],[33.26836,103.233803],[33.26722,103.233566],[33.266048,103.233704],[33.264832,103.233948],[33.261791,103.23468],[33.26038,103.234917],[33.25914,103.235062],[33.257462,103.235161],[33.253731,103.235443],[33.25238,103.235397],[33.25106,103.235001],[33.249592,103.234207],[33.245819,103.232117],[33.244678,103.231339],[33.24382,103.230408],[33.240059,103.225594],[33.238972,103.224113],[33.23819,103.223106],[33.23785,103.22274],[33.23695,103.222267],[33.236149,103.22216],[33.235329,103.222282],[33.233398,103.222618],[33.231781,103.22258],[33.231091,103.222488],[33.22718,103.221893],[33.225471,103.221657],[33.224178,103.221687],[33.223011,103.22187],[33.221619,103.222328],[33.219818,103.223061],[33.218491,103.223648],[33.21571,103.2248],[33.214199,103.225372],[33.212749,103.225952],[33.20895,103.227547],[33.202869,103.230019],[33.201542,103.230637],[33.199081,103.23204],[33.197811,103.23259],[33.19664,103.232933],[33.19558,103.233063],[33.194279,103.233063],[33.192841,103.23288],[33.191399,103.232643],[33.18642,103.231979],[33.185291,103.231842],[33.183811,103.231827],[33.18346,103.231873],[33.182259,103.232147],[33.180988,103.232643],[33.179909,103.233147],[33.178261,103.233887],[33.176609,103.234703],[33.1754,103.23526],[33.17424,103.235748],[33.173161,103.236099],[33.171631,103.236526],[33.168621,103.23732],[33.167042,103.237823],[33.16547,103.238548],[33.164291,103.239281],[33.160252,103.242126],[33.15736,103.244202],[33.155819,103.245247],[33.15461,103.245842],[33.15316,103.246277],[33.15181,103.246437],[33.14666,103.246887],[33.145031,103.24704],[33.1436,103.247307],[33.142368,103.247726],[33.14098,103.248497],[33.139992,103.249237],[33.134682,103.253471],[33.13332,103.254578],[33.132111,103.255623],[33.13126,103.256447],[33.130001,103.257912],[33.128738,103.259537],[33.127579,103.261253],[33.126831,103.262512],[33.12627,103.263611],[33.124859,103.266617],[33.124149,103.268204],[33.123569,103.269531],[33.12236,103.272102],[33.12175,103.273468],[33.121052,103.274872],[33.1194,103.278381],[33.118641,103.280159],[33.118469,103.281509],[33.118641,103.284523],[33.118599,103.285828],[33.118481,103.286583],[33.11805,103.287819],[33.116661,103.290291],[33.11607,103.291298],[33.114521,103.294037],[33.113831,103.295357],[33.110771,103.300713],[33.108799,103.30423],[33.10693,103.307663],[33.10585,103.309563],[33.10474,103.311562],[33.10376,103.313301],[33.10342,103.313927],[33.10157,103.317261],[33.100632,103.318848],[33.099758,103.320091],[33.096821,103.323883],[33.096001,103.324966],[33.095161,103.326042],[33.094471,103.327003],[33.093639,103.328377],[33.092258,103.331177],[33.091648,103.332573],[33.091042,103.333832],[33.090149,103.335831],[33.089481,103.337082],[33.088829,103.338371],[33.08831,103.339577],[33.087849,103.340714],[33.087318,103.342339],[33.087101,103.343529],[33.086899,103.345703],[33.086929,103.347954],[33.08675,103.349571],[33.0863,103.350693],[33.08556,103.351624],[33.084641,103.352303],[33.078941,103.355186],[33.078522,103.35537],[33.077671,103.355667],[33.076359,103.355904],[33.075459,103.355949],[33.0746,103.355873],[33.07333,103.355553],[33.07206,103.355103],[33.071529,103.354889],[33.069302,103.35408],[33.06802,103.353828],[33.066929,103.353844],[33.06506,103.35424],[33.063622,103.354446],[33.062641,103.354362],[33.061691,103.354103],[33.060921,103.353767],[33.060162,103.353394],[33.05899,103.352783],[33.056351,103.351448],[33.055248,103.350853],[33.05402,103.350143],[33.052711,103.349342],[33.051449,103.348427],[33.050282,103.347649],[33.049179,103.347076],[33.048111,103.346832],[33.046661,103.346809],[33.04493,103.347054],[33.043259,103.347359],[33.04216,103.347313],[33.040951,103.347214],[33.039921,103.347031],[33.038059,103.346832],[33.037102,103.347107],[33.029449,103.349022],[33.028889,103.349289],[33.02813,103.349907],[33.027081,103.351288],[33.026409,103.352318],[33.025848,103.353027],[33.024971,103.353699],[33.023991,103.354027],[33.021801,103.354317],[33.020592,103.354553],[33.019341,103.354713],[33.017941,103.354828],[33.016911,103.35479],[33.016479,103.354752],[33.01535,103.354446],[33.01424,103.354088],[33.013458,103.353592],[33.01091,103.352257],[33.0103,103.351982],[33.008732,103.351624],[33.005501,103.351112],[33.004581,103.3507],[33.003799,103.350021],[33.003651,103.349854],[33.003201,103.349083],[33.002541,103.347862],[33.001862,103.346657],[33.001579,103.346313],[33.00087,103.345573],[32.999931,103.345062],[32.998878,103.344803],[32.992008,103.343224],[32.990391,103.343048],[32.989071,103.34304],[32.987709,103.343117],[32.986309,103.343323],[32.984741,103.343651],[32.979359,103.344963],[32.977219,103.345512],[32.974861,103.346077],[32.970989,103.347076],[32.96925,103.347572],[32.967682,103.348213],[32.966331,103.348824],[32.965172,103.349152],[32.964169,103.349197],[32.963829,103.349136],[32.962742,103.348732],[32.960621,103.347633],[32.959702,103.347198],[32.95908,103.347054],[32.95863,103.347038],[32.958031,103.347107],[32.957119,103.347351],[32.955151,103.347977],[32.952831,103.348663],[32.952141,103.3489],[32.951641,103.349167],[32.95116,103.349442],[32.949409,103.350571],[32.94825,103.351273],[32.94762,103.351593],[32.947079,103.351791],[32.945309,103.35257],[32.944351,103.3526],[32.943501,103.352821],[32.943272,103.352859],[32.941738,103.353241],[32.940842,103.353378],[32.940022,103.353416],[32.93951,103.353409],[32.938541,103.353279],[32.937328,103.352989],[32.936821,103.352829],[32.935581,103.352386],[32.93502,103.352127],[32.93438,103.35173],[32.92968,103.348557],[32.928959,103.348389],[32.92881,103.348389],[32.927872,103.348579],[32.927238,103.348923],[32.926979,103.349167],[32.926231,103.350121],[32.92588,103.350883],[32.92561,103.351929],[32.925621,103.353188],[32.926079,103.354408],[32.92646,103.355003],[32.926689,103.355247],[32.926819,103.35537],[32.927231,103.355652],[32.92894,103.356537],[32.92939,103.356903],[32.92963,103.357208],[32.929829,103.357567],[32.929981,103.358223],[32.930019,103.358673],[32.93,103.359138],[32.929909,103.3601],[32.930092,103.361542],[32.93021,103.362022],[32.93042,103.36274],[32.930618,103.364227],[32.930641,103.364723],[32.930511,103.366203],[32.93037,103.366928],[32.929901,103.370033],[32.929829,103.370567],[32.92918,103.373558],[32.928799,103.375076],[32.928452,103.376228],[32.928242,103.377434],[32.928139,103.378677],[32.928169,103.3797],[32.928249,103.38044],[32.928341,103.380913],[32.928692,103.382339],[32.928909,103.382988],[32.929192,103.383743],[32.929409,103.384277],[32.929859,103.385559],[32.930119,103.386688],[32.93008,103.38781],[32.929829,103.388687],[32.92976,103.388863],[32.929501,103.389328],[32.929329,103.389587],[32.928612,103.390182],[32.927959,103.390533],[32.92667,103.391029],[32.9259,103.391296],[32.924332,103.391922],[32.924019,103.392059],[32.921459,103.393173],[32.92033,103.393883],[32.918991,103.394997],[32.91835,103.397507],[32.918289,103.399567],[32.918541,103.402367],[32.918579,103.403191],[32.918869,103.404228],[32.91993,103.406593],[32.920429,103.408546],[32.9212,103.410851],[32.921989,103.412651],[32.922771,103.414688],[32.92392,103.417473],[32.9244,103.418663],[32.92532,103.420891],[32.92561,103.421631],[32.925999,103.422462],[32.926659,103.423683],[32.927441,103.424919],[32.928329,103.426208],[32.928848,103.427254],[32.928989,103.427818],[32.92905,103.429153],[32.928909,103.430054],[32.928532,103.431862],[32.928421,103.432999],[32.928551,103.434288],[32.928719,103.435532],[32.928741,103.436203],[32.92852,103.437347],[32.92844,103.437569],[32.927872,103.438599],[32.926811,103.440201],[32.92614,103.441238],[32.925838,103.441612],[32.92487,103.442177],[32.924221,103.442284],[32.923759,103.442238],[32.92308,103.442139],[32.92284,103.442032],[32.922298,103.441994],[32.921169,103.441811],[32.919289,103.441727],[32.917931,103.441872],[32.917221,103.442162],[32.916569,103.442596],[32.914398,103.444443],[32.913891,103.444946],[32.912571,103.446381],[32.911499,103.447723],[32.91016,103.449493],[32.90984,103.449928],[32.909279,103.450684],[32.90884,103.451134],[32.907711,103.452148],[32.90715,103.452873],[32.906818,103.453522],[32.90646,103.454453],[32.906151,103.455406],[32.905731,103.456581],[32.905121,103.457428],[32.904419,103.458252],[32.90411,103.458588],[32.903252,103.459747],[32.903019,103.460037],[32.90263,103.460426],[32.90176,103.461113],[32.901588,103.461182],[32.901039,103.461357],[32.900089,103.461479],[32.89872,103.461533],[32.897171,103.46167],[32.896172,103.461678],[32.894901,103.461601],[32.89386,103.461304],[32.893242,103.461021],[32.892818,103.460808],[32.88744,103.45845],[32.885921,103.458076],[32.884232,103.45826],[32.88364,103.458801],[32.88335,103.459244],[32.883228,103.460114],[32.883331,103.461067],[32.883701,103.462151],[32.884941,103.464317],[32.885361,103.465477],[32.88559,103.466217],[32.885941,103.46756],[32.886768,103.471481],[32.88702,103.472878],[32.88702,103.473999],[32.886959,103.474541],[32.8867,103.475273],[32.886589,103.475487],[32.886299,103.475929],[32.885639,103.476753],[32.885151,103.477409],[32.884171,103.4786],[32.883739,103.479172],[32.883289,103.480072],[32.883289,103.481178],[32.88422,103.483498],[32.884609,103.484032],[32.885479,103.484833],[32.885681,103.485199],[32.885921,103.486977],[32.886101,103.48748],[32.88789,103.488998],[32.88847,103.489853],[32.889359,103.490211],[32.88966,103.490784],[32.89048,103.491524],[32.890678,103.491867],[32.890888,103.492531],[32.89201,103.494492],[32.89254,103.495956],[32.8932,103.496986],[32.893539,103.497864],[32.894569,103.499237],[32.894711,103.499672],[32.894741,103.500282],[32.895451,103.501518],[32.89576,103.503227],[32.895981,103.503563],[32.896961,103.504143],[32.898571,103.505417],[32.898788,103.505783],[32.89922,103.506897],[32.89954,103.508629],[32.899872,103.509567],[32.901138,103.512047],[32.9021,103.513329],[32.90271,103.514191],[32.90337,103.515282],[32.903599,103.5159],[32.90369,103.51725],[32.903641,103.5177],[32.903542,103.51815],[32.9034,103.51857],[32.903118,103.51918],[32.90287,103.519539],[32.901981,103.52021],[32.89875,103.521294],[32.897659,103.521713],[32.896591,103.52224],[32.895561,103.522926],[32.89481,103.523613],[32.89386,103.524544],[32.892632,103.525681],[32.89151,103.526657],[32.889999,103.528061],[32.88969,103.528328],[32.887032,103.530907],[32.88538,103.532829],[32.88414,103.534088],[32.883041,103.535133],[32.88232,103.535957],[32.88184,103.536827],[32.881329,103.538147],[32.880569,103.539284],[32.880119,103.539719],[32.87899,103.540367],[32.878181,103.540756],[32.876961,103.541527],[32.87677,103.541687],[32.875542,103.542923],[32.87439,103.544113],[32.87344,103.544777],[32.87281,103.54496],[32.872379,103.544991],[32.871529,103.544769],[32.869991,103.543968],[32.868919,103.543694],[32.86871,103.543694],[32.86792,103.543907],[32.865631,103.545013],[32.864841,103.545326],[32.863529,103.546043],[32.863209,103.546341],[32.862499,103.547562],[32.862141,103.548943],[32.861809,103.550858],[32.86142,103.552467],[32.86134,103.552696],[32.860748,103.55394],[32.860229,103.554649],[32.859379,103.555748],[32.858181,103.55687],[32.857422,103.557388],[32.855759,103.558571],[32.854111,103.559631],[32.852581,103.560661],[32.85178,103.56115],[32.850929,103.561546],[32.84938,103.560806],[32.847279,103.562027],[32.846119,103.561127],[32.844318,103.560806],[32.842979,103.560966],[32.83886,103.561691],[32.836922,103.561974],[32.835239,103.562263],[32.835041,103.562317],[32.833969,103.562889],[32.832489,103.56398],[32.832199,103.56424],[32.830921,103.565247],[32.829681,103.565933],[32.828079,103.566483],[32.826851,103.566849],[32.826199,103.566994],[32.825119,103.566849],[32.82309,103.565964],[32.82196,103.56604],[32.821091,103.566437],[32.819809,103.567093],[32.81958,103.567169],[32.818661,103.567421],[32.816849,103.567734],[32.81509,103.567963],[32.813641,103.568352],[32.81329,103.568604],[32.81266,103.569221],[32.81216,103.570007],[32.811611,103.570801],[32.810741,103.571503],[32.80975,103.571831],[32.80854,103.571991],[32.806389,103.572197],[32.80484,103.572342],[32.801029,103.572723],[32.800159,103.572884],[32.79948,103.573219],[32.79895,103.573669],[32.79842,103.574249],[32.79784,103.575233],[32.79734,103.576553],[32.79668,103.578011],[32.796631,103.578827],[32.796841,103.581757],[32.796799,103.582779],[32.796261,103.583809],[32.795582,103.584511],[32.793018,103.585953],[32.792259,103.586868],[32.79192,103.587959],[32.79147,103.592941],[32.79113,103.595108],[32.79044,103.596313],[32.789612,103.596863],[32.78825,103.597397],[32.788052,103.597458],[32.787029,103.597878],[32.786579,103.598267],[32.786301,103.598579],[32.78574,103.599663],[32.78553,103.60096],[32.78524,103.603996],[32.785069,103.605637],[32.785721,103.607887],[32.785721,103.608856],[32.785389,103.609711],[32.784641,103.610893],[32.78352,103.612663],[32.782211,103.614609],[32.78183,103.615097],[32.780869,103.616226],[32.78072,103.616257],[32.780609,103.61631],[32.780491,103.616371],[32.780258,103.616623],[32.779961,103.616898],[32.778049,103.618217],[32.776642,103.619171],[32.775639,103.619743],[32.774971,103.619812],[32.774311,103.619583],[32.773739,103.619347],[32.773289,103.619118],[32.772671,103.618927],[32.771999,103.618568],[32.771679,103.618523],[32.771259,103.618523],[32.770809,103.618294],[32.770481,103.618217],[32.770248,103.61824],[32.7701,103.618294],[32.769852,103.618462],[32.769402,103.618912],[32.769089,103.619797],[32.768589,103.620064],[32.76759,103.620682],[32.767712,103.618896],[32.767509,103.618248],[32.767559,103.617279],[32.767399,103.616951],[32.767208,103.616699],[32.766899,103.61644],[32.766251,103.616249],[32.76609,103.616226],[32.765862,103.616249],[32.765579,103.616241],[32.765041,103.616058],[32.76498,103.616013],[32.764648,103.615883],[32.76403,103.615891],[32.763828,103.615959],[32.763561,103.616081],[32.762581,103.616364],[32.76236,103.616409],[32.76173,103.616272],[32.76059,103.615753],[32.756771,103.614197],[32.755939,103.613922],[32.754959,103.613441],[32.754341,103.613152],[32.754169,103.613091],[32.753738,103.61306],[32.753349,103.613052],[32.75243,103.612778],[32.751999,103.612778],[32.751919,103.612762],[32.751499,103.612793],[32.750641,103.612663],[32.750401,103.61261],[32.749691,103.612511],[32.748161,103.612556],[32.747429,103.612289],[32.746552,103.611816],[32.745739,103.611656],[32.74556,103.611679],[32.745361,103.611656],[32.744301,103.611977],[32.74408,103.612099],[32.7439,103.612099],[32.743488,103.611992],[32.743408,103.611992],[32.743271,103.612053],[32.742981,103.61232],[32.742882,103.612396],[32.74255,103.61274],[32.742531,103.61274],[32.742401,103.612938],[32.74218,103.613113],[32.741951,103.613312],[32.74173,103.613472],[32.741379,103.613831],[32.741161,103.613983],[32.74057,103.614433],[32.740231,103.614548],[32.740028,103.614571],[32.739491,103.614548],[32.738289,103.614304],[32.737469,103.614227],[32.736851,103.614113],[32.736641,103.614113],[32.736401,103.614021],[32.736271,103.614014],[32.73555,103.613983],[32.734982,103.613892],[32.73439,103.614037],[32.73407,103.614166],[32.73391,103.614182],[32.73341,103.614281],[32.733051,103.614441],[32.73288,103.614662],[32.731121,103.615913],[32.733009,103.614578],[32.731171,103.616257],[32.728809,103.614731],[32.72821,103.614487],[32.72781,103.61451],[32.7276,103.614601],[32.727131,103.615219],[32.7267,103.615868],[32.726521,103.616058],[32.726341,103.616112],[32.725739,103.616089],[32.724991,103.615448],[32.723011,103.613426],[32.722759,103.613197],[32.722198,103.612961],[32.72105,103.612663],[32.720032,103.612297],[32.71991,103.612244],[32.719711,103.612053],[32.719181,103.611343],[32.718578,103.610367],[32.718201,103.60994],[32.717861,103.609596],[32.7174,103.609222],[32.716751,103.608887],[32.71611,103.608681],[32.714588,103.608047],[32.71349,103.607727],[32.712181,103.607422],[32.711411,103.607193],[32.71056,103.607246],[32.710251,103.607239],[32.709042,103.606903],[32.70776,103.606293],[32.707481,103.606216],[32.707062,103.606163],[32.706421,103.606087],[32.70546,103.605927],[32.704552,103.605583],[32.703732,103.605598],[32.70332,103.605667],[32.703072,103.605698],[32.702839,103.605667],[32.70211,103.605438],[32.701931,103.605408],[32.701771,103.605408],[32.701271,103.605263],[32.700932,103.605141],[32.700531,103.604874],[32.699711,103.604362],[32.699169,103.604118],[32.698891,103.604088],[32.698589,103.604118],[32.698139,103.604012],[32.6973,103.603699],[32.69627,103.6036],[32.695469,103.603432],[32.695122,103.60334],[32.694538,103.603218],[32.693939,103.603157],[32.69331,103.602837],[32.69286,103.602531],[32.692181,103.602127],[32.69138,103.602203],[32.690689,103.60231],[32.68866,103.601852],[32.687641,103.601738],[32.68716,103.601822],[32.686211,103.602089],[32.686081,103.602112],[32.684361,103.601738],[32.682961,103.601402],[32.682331,103.601341],[32.681709,103.601334],[32.680939,103.601372],[32.68008,103.601387],[32.679352,103.601357],[32.67865,103.60128],[32.67775,103.60128],[32.67635,103.601967],[32.67564,103.60199],[32.6745,103.601768],[32.673389,103.60173],[32.671902,103.601349],[32.671082,103.601578],[32.670502,103.601852],[32.669762,103.602242],[32.66906,103.602257],[32.667542,103.602127],[32.666489,103.602188],[32.665051,103.602013],[32.663712,103.601898],[32.661572,103.601799],[32.660351,103.601608],[32.659389,103.601212],[32.658588,103.60099],[32.657459,103.600868],[32.657021,103.600853],[32.655869,103.600868],[32.654869,103.600761],[32.652618,103.600151],[32.65189,103.599792],[32.651279,103.599457],[32.650551,103.598969],[32.650131,103.598763],[32.64856,103.59819],[32.64624,103.597343],[32.64613,103.597282],[32.646099,103.597252],[32.644691,103.596863],[32.64436,103.596947],[32.644329,103.59697],[32.64418,103.597214],[32.643421,103.598312],[32.643139,103.598549],[32.64296,103.598618],[32.64146,103.598503],[32.640888,103.598488],[32.638309,103.598106],[32.637669,103.597969],[32.637081,103.597794],[32.63623,103.597557],[32.635571,103.597229],[32.634159,103.59642],[32.633621,103.595932],[32.633099,103.595192],[32.63298,103.595062],[32.630989,103.593307],[32.630871,103.593224],[32.63018,103.593033],[32.62859,103.592728],[32.627861,103.592484],[32.627331,103.592087],[32.626701,103.591553],[32.626431,103.591339],[32.625969,103.591042],[32.625401,103.590927],[32.624741,103.590843],[32.623569,103.590637],[32.62336,103.590607],[32.620441,103.590843],[32.61964,103.590919],[32.618912,103.591141],[32.618301,103.591522],[32.617229,103.592491],[32.61618,103.593407],[32.613911,103.59549],[32.612141,103.597343],[32.60939,103.600151],[32.60881,103.600609],[32.60812,103.600983],[32.607559,103.601189],[32.60487,103.602074],[32.60397,103.601501],[32.599178,103.605614],[32.598019,103.605003],[32.597408,103.605362],[32.597099,103.605637],[32.596779,103.605873],[32.5961,103.606407],[32.59581,103.607697],[32.58968,103.610817],[32.588779,103.609818],[32.587219,103.609459],[32.58707,103.609444],[32.586552,103.60965],[32.58593,103.61013],[32.585361,103.610619],[32.585091,103.61097],[32.584961,103.611092],[32.58469,103.611214],[32.584171,103.611511],[32.58358,103.612038],[32.583382,103.613289],[32.573071,103.617027],[32.572479,103.61599],[32.572121,103.61599],[32.57011,103.616623],[32.56966,103.616882],[32.569519,103.617027],[32.569351,103.617126],[32.56926,103.617233],[32.568729,103.617599],[32.56815,103.617767],[32.567829,103.61776],[32.567451,103.617661],[32.566639,103.617523],[32.566261,103.61763],[32.565498,103.618553],[32.565231,103.618668],[32.561069,103.620064],[32.560051,103.620728],[32.560001,103.62178],[32.54961,103.625549],[32.546169,103.626801],[32.544022,103.627579],[32.5396,103.629181],[32.539082,103.628212],[32.530869,103.630623],[32.528111,103.630257],[32.527721,103.630333],[32.526001,103.631042],[32.52544,103.631203],[32.52467,103.631088],[32.523991,103.630859],[32.523708,103.630859],[32.522869,103.631157],[32.52224,103.631233],[32.521599,103.631126],[32.520771,103.631111],[32.520168,103.631279],[32.519741,103.6315],[32.519482,103.631683],[32.519119,103.632027],[32.518742,103.632233],[32.51857,103.632362],[32.518261,103.632889],[32.518059,103.633118],[32.517811,103.633324],[32.517342,103.633774],[32.516441,103.634323],[32.5159,103.634613],[32.515598,103.634857],[32.515469,103.635094],[32.515301,103.636017],[32.515099,103.636948],[32.514881,103.637337],[32.514751,103.63868],[32.510632,103.641068],[32.509769,103.639954],[32.509331,103.639832],[32.508751,103.63958],[32.508579,103.639526],[32.508289,103.639519],[32.507221,103.639709],[32.506599,103.639847],[32.505138,103.64035],[32.504871,103.640373],[32.504539,103.640282],[32.504421,103.640213],[32.504131,103.639923],[32.504051,103.639793],[32.502449,103.639282],[32.502102,103.639664],[32.501961,103.639877],[32.501869,103.640083],[32.50156,103.641472],[32.501389,103.642082],[32.500481,103.644814],[32.4991,103.645393],[32.498219,103.645126],[32.49791,103.645111],[32.49778,103.645119],[32.49712,103.645409],[32.496429,103.645859],[32.493111,103.648804],[32.492649,103.648972],[32.49192,103.649017],[32.49152,103.648979],[32.491261,103.648872],[32.491058,103.648666],[32.49078,103.648216],[32.490429,103.647552],[32.490261,103.647293],[32.48975,103.646797],[32.489422,103.646507],[32.488869,103.646133],[32.488708,103.646088],[32.488609,103.646103],[32.488419,103.646156],[32.488251,103.646294],[32.487968,103.646683],[32.487228,103.647362],[32.4869,103.647827],[32.486591,103.648651],[32.486309,103.649246],[32.485149,103.651466],[32.484699,103.652138],[32.484268,103.652397],[32.483719,103.652641],[32.482811,103.652809],[32.481812,103.653061],[32.481209,103.653191],[32.480999,103.653259],[32.48045,103.653709],[32.480061,103.654411],[32.479839,103.655159],[32.479599,103.656219],[32.479561,103.656441],[32.479481,103.657791],[32.47961,103.659042],[32.475731,103.661293],[32.474949,103.660133],[32.474339,103.660072],[32.47393,103.660149],[32.472481,103.660339],[32.47221,103.660408],[32.469349,103.661484],[32.468899,103.662041],[32.46833,103.662727],[32.467201,103.664032],[32.466019,103.66507],[32.464512,103.666359],[32.464039,103.666801],[32.463879,103.66703],[32.463669,103.667793],[32.463581,103.668404],[32.463928,103.669243],[32.455311,103.675484],[32.44862,103.680344],[32.443989,103.683693],[32.438961,103.687317],[32.43782,103.686546],[32.43652,103.686813],[32.436062,103.686958],[32.435749,103.687141],[32.43425,103.688454],[32.433849,103.688766],[32.43364,103.688881],[32.43288,103.689041],[32.432201,103.689087],[32.431709,103.689262],[32.43148,103.689537],[32.431221,103.689781],[32.430901,103.690392],[32.430779,103.690521],[32.430569,103.690689],[32.430302,103.691002],[32.43005,103.691017],[32.429619,103.691109],[32.429199,103.691223],[32.428699,103.691429],[32.4282,103.691597],[32.427891,103.691879],[32.427719,103.692093],[32.427269,103.692978],[32.42688,103.693932],[32.426559,103.694733],[32.426208,103.695396],[32.425591,103.695999],[32.42511,103.6968],[32.424549,103.697533],[32.423981,103.698036],[32.42355,103.69838],[32.42337,103.698738],[32.423248,103.699593],[32.42337,103.700943],[32.42247,103.701736],[32.42268,103.703369],[32.422531,103.703758],[32.421791,103.704437],[32.42112,103.705002],[32.420502,103.705597],[32.419819,103.70636],[32.41909,103.707314],[32.41893,103.707489],[32.4179,103.709068],[32.41293,103.713463],[32.411888,103.713661],[32.410511,103.71376],[32.409721,103.713173],[32.4021,103.720001],[32.401299,103.720428],[32.387909,103.726318],[32.387878,103.727661],[32.387779,103.727737],[32.387428,103.728081],[32.387211,103.728348],[32.386478,103.728844],[32.38607,103.728958],[32.385349,103.728912],[32.384682,103.728897],[32.383949,103.728867],[32.38303,103.727943],[32.37851,103.728539],[32.378052,103.729881],[32.377319,103.730423],[32.377121,103.730499],[32.37574,103.730873],[32.374809,103.731003],[32.374081,103.731056],[32.373859,103.73111],[32.373112,103.73143],[32.37228,103.731667],[32.371811,103.73175],[32.371632,103.731697],[32.37093,103.731216],[32.369781,103.730347],[32.369221,103.729057],[32.365871,103.728638],[32.36549,103.726868],[32.365139,103.726471],[32.364941,103.726196],[32.364769,103.726021],[32.3647,103.725861],[32.36459,103.725563],[32.364441,103.724899],[32.364208,103.724403],[32.363659,103.723984],[32.36335,103.723862],[32.36224,103.723877],[32.361752,103.723869],[32.361462,103.723907],[32.3605,103.724121],[32.360321,103.724121],[32.35928,103.723869],[32.358891,103.724007],[32.358719,103.724167],[32.358139,103.725037],[32.35788,103.725449],[32.357471,103.726189],[32.35717,103.72718],[32.357121,103.727638],[32.357059,103.727814],[32.356861,103.727661],[32.35606,103.728683],[32.356659,103.730026],[32.356579,103.730827],[32.356449,103.731697],[32.356121,103.733276],[32.355782,103.735153],[32.355492,103.735832],[32.35524,103.736168],[32.35519,103.736282],[32.35503,103.736519],[32.35458,103.736748],[32.353859,103.736992],[32.3536,103.73703],[32.35339,103.73703],[32.352219,103.736847],[32.350929,103.736702],[32.350719,103.736748],[32.350319,103.736893],[32.350101,103.736282],[32.34993,103.737289],[32.34943,103.737503],[32.348598,103.737381],[32.348,103.737122],[32.347729,103.736923],[32.347641,103.735962],[32.34623,103.735779],[32.345821,103.734337],[32.34568,103.7342],[32.345551,103.734009],[32.345379,103.733856],[32.340771,103.727203],[32.34053,103.726822],[32.340481,103.726677],[32.340439,103.726479],[32.34045,103.726242],[32.3405,103.726082],[32.34066,103.72567],[32.340672,103.725456],[32.340439,103.724876],[32.340099,103.724167],[32.340019,103.723389],[32.340031,103.72316],[32.340111,103.7229],[32.340462,103.722481],[32.340611,103.722221],[32.340599,103.721718],[32.340519,103.721527],[32.340092,103.720932],[32.339809,103.720772],[32.33762,103.72052],[32.33683,103.72049],[32.336369,103.720421],[32.335609,103.720207],[32.33519,103.720032],[32.334728,103.719711],[32.334259,103.71933],[32.333832,103.719162],[32.333599,103.719109],[32.332722,103.718712],[32.33234,103.718613],[32.331558,103.71875],[32.330231,103.719467],[32.329472,103.719803],[32.329041,103.719841],[32.328621,103.719849],[32.32827,103.71981],[32.327869,103.719887],[32.327389,103.719841],[32.327122,103.719658],[32.327019,103.719437],[32.32682,103.718987],[32.32658,103.718788],[32.32629,103.718719],[32.326061,103.718613],[32.325771,103.718536],[32.325531,103.71859],[32.325089,103.718727],[32.324959,103.718803],[32.32428,103.719032],[32.32365,103.719139],[32.323429,103.719193],[32.3232,103.719276],[32.323051,103.71936],[32.322319,103.719917],[32.321701,103.720268],[32.320808,103.72068],[32.320461,103.720589],[32.32016,103.720291],[32.319981,103.7202],[32.31926,103.720177],[32.319061,103.7202],[32.318741,103.720169],[32.318642,103.720329],[32.318451,103.720284],[32.31786,103.720062],[32.317741,103.720062],[32.317532,103.720154],[32.317039,103.720467],[32.316441,103.721413],[32.316071,103.721367],[32.315369,103.72123],[32.314651,103.720978],[32.313961,103.720818],[32.313251,103.720802],[32.312721,103.720818],[32.312141,103.720993],[32.31142,103.721336],[32.31131,103.721367],[32.310471,103.721367],[32.310162,103.721313],[32.30938,103.720802],[32.30904,103.72068],[32.308788,103.720657],[32.30843,103.720863],[32.308201,103.7211],[32.307041,103.721878],[32.30603,103.722488],[32.30579,103.722588],[32.305161,103.723068],[32.304489,103.723373],[32.30444,103.723373],[32.303829,103.723457],[32.303188,103.72361],[32.302551,103.723793],[32.301521,103.723824],[32.300659,103.723892],[32.300339,103.723938],[32.29982,103.724121],[32.299648,103.724281],[32.299541,103.724426],[32.29929,103.725037],[32.299129,103.725609],[32.299,103.726334],[32.29895,103.726807],[32.29908,103.72802],[32.28278,103.735847],[32.282139,103.734863],[32.281811,103.734901],[32.281319,103.734909],[32.280991,103.734932],[32.280048,103.735046],[32.279228,103.734962],[32.27861,103.735107],[32.278561,103.73513],[32.2784,103.735298],[32.277771,103.736427],[32.277031,103.737267],[32.276718,103.737709],[32.27663,103.7388],[32.27467,103.739754],[32.274441,103.741219],[32.273811,103.741577],[32.27319,103.741737],[32.272499,103.741997],[32.271721,103.742462],[32.27121,103.742844],[32.270771,103.743271],[32.27013,103.743736],[32.269711,103.743942],[32.26902,103.744179],[32.26878,103.744217],[32.268242,103.7444],[32.267399,103.744713],[32.266949,103.745033],[32.266449,103.745407],[32.266289,103.745499],[32.26561,103.745697],[32.264511,103.745117],[32.26244,103.74675],[32.26263,103.748032],[32.262428,103.748466],[32.26202,103.748802],[32.261749,103.748993],[32.26149,103.749092],[32.261181,103.749313],[32.260849,103.749634],[32.260441,103.749863],[32.259892,103.749931],[32.259129,103.749352],[32.255508,103.75219],[32.255661,103.75383],[32.25523,103.755402],[32.2547,103.756187],[32.254581,103.756477],[32.25425,103.756783],[32.25404,103.757088],[32.253658,103.757812],[32.253181,103.758797],[32.252628,103.759499],[32.252041,103.759956],[32.251362,103.76017],[32.250881,103.760178],[32.250431,103.760246],[32.250271,103.760193],[32.250019,103.760139],[32.24942,103.760101],[32.24892,103.760193],[32.24855,103.760353],[32.248371,103.760628],[32.24818,103.760788],[32.247921,103.76078],[32.247719,103.760857],[32.247601,103.760986],[32.24733,103.761414],[32.24699,103.761803],[32.24659,103.762108],[32.246311,103.762253],[32.24559,103.762543],[32.24535,103.762657],[32.24522,103.762688],[32.244541,103.762772],[32.24379,103.762787],[32.243359,103.762917],[32.243111,103.763077],[32.242298,103.764],[32.24152,103.764717],[32.240849,103.765167],[32.2402,103.76545],[32.239552,103.765663],[32.238811,103.765701],[32.23835,103.765701],[32.23772,103.765602],[32.237068,103.765427],[32.236561,103.76516],[32.236031,103.764816],[32.23555,103.764458],[32.234901,103.763496],[32.233509,103.764069],[32.23288,103.764282],[32.224331,103.765762],[32.220219,103.766548],[32.219711,103.765091],[32.219559,103.764893],[32.219341,103.764732],[32.219231,103.764687],[32.21899,103.764641],[32.218861,103.764603],[32.217991,103.764503],[32.216721,103.764427],[32.21656,103.764503],[32.21627,103.76458],[32.215931,103.764526],[32.215691,103.764557],[32.215611,103.764603],[32.215092,103.7649],[32.21487,103.765068],[32.214329,103.765556],[32.213848,103.765984],[32.21368,103.766083],[32.213299,103.766129],[32.21262,103.765923],[32.212448,103.765938],[32.212139,103.765953],[32.21146,103.766144],[32.211151,103.766167],[32.210129,103.766037],[32.20974,103.765907],[32.208851,103.765282],[32.20853,103.765259],[32.20784,103.765244],[32.207291,103.765198],[32.206909,103.765213],[32.205502,103.765457],[32.20406,103.765137],[32.20266,103.764061],[32.202389,103.763924],[32.202091,103.763809],[32.201061,103.763603],[32.200821,103.763321],[32.200741,103.762932],[32.200588,103.762619],[32.200359,103.762421],[32.200008,103.762177],[32.199879,103.762032],[32.199371,103.762123],[32.19912,103.762032],[32.197449,103.761223],[32.19677,103.760948],[32.19651,103.760857],[32.19553,103.760399],[32.195431,103.760384],[32.194851,103.760391],[32.19352,103.760483],[32.193169,103.76049],[32.192711,103.760437],[32.19249,103.760361],[32.192451,103.760384],[32.19223,103.760292],[32.191719,103.760223],[32.19112,103.760071],[32.190578,103.759804],[32.190128,103.759468],[32.189541,103.758987],[32.189251,103.758774],[32.189072,103.758713],[32.1884,103.758659],[32.18734,103.75856],[32.186588,103.758537],[32.18642,103.758507],[32.185841,103.758492],[32.185539,103.758423],[32.18528,103.758179],[32.185169,103.757729],[32.184952,103.757149],[32.184818,103.756958],[32.184601,103.756721],[32.183971,103.756264],[32.182529,103.755493],[32.18235,103.755463],[32.180672,103.755501],[32.18037,103.755623],[32.180271,103.755722],[32.179218,103.756973],[32.17902,103.757111],[32.178589,103.757187],[32.178162,103.757187],[32.17794,103.757133],[32.1782,103.757179],[32.177479,103.756889],[32.176491,103.756157],[32.175869,103.755608],[32.17561,103.755188],[32.175282,103.754471],[32.17485,103.753616],[32.174622,103.752991],[32.174191,103.751953],[32.174129,103.751694],[32.173981,103.75135],[32.173321,103.750267],[32.172981,103.749519],[32.172749,103.748756],[32.17263,103.748497],[32.17244,103.748177],[32.171909,103.747513],[32.171791,103.747299],[32.171471,103.746872],[32.171249,103.746223],[32.171101,103.745667],[32.171001,103.745117],[32.171021,103.744598],[32.171059,103.744263],[32.17112,103.743896],[32.171131,103.743523],[32.171082,103.743179],[32.170929,103.742683],[32.1707,103.742149],[32.17046,103.741623],[32.170261,103.741432],[32.170029,103.74147],[32.169788,103.741653],[32.169571,103.741737],[32.16925,103.741951],[32.168861,103.742126],[32.168369,103.742264],[32.167759,103.742081],[32.167648,103.741997],[32.16708,103.741257],[32.166809,103.741043],[32.16544,103.740593],[32.164761,103.740387],[32.164242,103.740181],[32.163879,103.739899],[32.163651,103.739647],[32.163429,103.739227],[32.16325,103.738724],[32.163109,103.738358],[32.162701,103.737907],[32.162079,103.737297],[32.16188,103.737061],[32.161549,103.736763],[32.161449,103.736633],[32.161121,103.73629],[32.16048,103.735924],[32.159801,103.735672],[32.158619,103.735321],[32.158321,103.735168],[32.157829,103.734978],[32.157619,103.734871],[32.157261,103.734863],[32.15641,103.734749],[32.156132,103.734734],[32.155869,103.734741],[32.15556,103.734787],[32.15498,103.734978],[32.154881,103.734993],[32.15456,103.734863],[32.154018,103.734497],[32.153561,103.734306],[32.153309,103.734123],[32.153069,103.733887],[32.15284,103.73362],[32.152649,103.733353],[32.152611,103.7332],[32.152512,103.733101],[32.152302,103.732964],[32.152199,103.732933],[32.151611,103.732811],[32.150921,103.732643],[32.150028,103.73246],[32.149891,103.732407],[32.14967,103.732384],[32.149471,103.732323],[32.149132,103.732269],[32.148769,103.732162],[32.148399,103.732109],[32.148102,103.732147],[32.147652,103.732246],[32.147018,103.732269],[32.146889,103.732231],[32.146309,103.731903],[32.146118,103.731773],[32.145882,103.731682],[32.145241,103.731667],[32.14481,103.731697],[32.144581,103.731773],[32.143681,103.732109],[32.14352,103.732193],[32.14336,103.732239],[32.143082,103.732399],[32.142429,103.732674],[32.142059,103.732903],[32.14172,103.7332],[32.141521,103.733467],[32.14122,103.733803],[32.140888,103.733917],[32.14045,103.733757],[32.140251,103.733597],[32.139679,103.733017],[32.13945,103.732826],[32.138981,103.732613],[32.138741,103.732536],[32.138519,103.732513],[32.138199,103.732567],[32.137489,103.732903],[32.13707,103.733231],[32.136742,103.733437],[32.136459,103.733528],[32.136021,103.73365],[32.135731,103.733757],[32.13538,103.733849],[32.135151,103.733849],[32.134472,103.733772],[32.134109,103.733658],[32.1339,103.733612],[32.133678,103.733719],[32.13327,103.734016],[32.132912,103.734138],[32.132721,103.734177],[32.132309,103.734451],[32.13208,103.734528],[32.131302,103.734627],[32.130322,103.734642],[32.129959,103.734703],[32.129459,103.734818],[32.128342,103.734962],[32.12801,103.734932],[32.12796,103.734947],[32.127811,103.734932],[32.127411,103.734818],[32.127129,103.734779],[32.126709,103.734642],[32.126419,103.734444],[32.12624,103.734329],[32.12587,103.733849],[32.125641,103.733711],[32.125179,103.733582],[32.124821,103.733543],[32.123871,103.733559],[32.12331,103.733521],[32.122761,103.733383],[32.12159,103.732971],[32.12088,103.732597],[32.120209,103.732147],[32.119419,103.731651],[32.118851,103.731148],[32.118061,103.73037],[32.11755,103.729736],[32.117001,103.728928],[32.11657,103.728508],[32.116482,103.728447],[32.11618,103.728317],[32.115959,103.728271],[32.115841,103.728233],[32.11515,103.728073],[32.114681,103.727882],[32.114521,103.727791],[32.11412,103.727226],[32.11396,103.727127],[32.1138,103.726967],[32.113609,103.726753],[32.11338,103.726562],[32.112801,103.726143],[32.11261,103.726112],[32.112209,103.726151],[32.112041,103.726128],[32.111629,103.725693],[32.111462,103.725578],[32.111382,103.725487],[32.11079,103.725159],[32.110691,103.725189],[32.110519,103.725319],[32.110249,103.725563],[32.11005,103.725731],[32.109749,103.725662],[32.109631,103.725563],[32.109341,103.725449],[32.108501,103.725731],[32.108212,103.725983],[32.107979,103.726227],[32.107899,103.726288],[32.107689,103.726372],[32.107262,103.726448],[32.107059,103.726433],[32.106621,103.726227],[32.1064,103.725937],[32.106468,103.725822],[32.10664,103.725662],[32.106419,103.725403],[32.106838,103.724632],[32.106541,103.724342],[32.106781,103.723579],[32.10656,103.723412],[32.106461,103.723213],[32.105831,103.723534],[32.10561,103.723511],[32.105389,103.723541],[32.103531,103.725349],[32.103321,103.725487],[32.103142,103.725563],[32.102829,103.725723],[32.102638,103.725754],[32.102261,103.725891],[32.102081,103.725922],[32.1017,103.725937],[32.100639,103.725937],[32.100368,103.725883],[32.100151,103.725639],[32.099911,103.725288],[32.099491,103.724838],[32.0994,103.724709],[32.09919,103.724068],[32.09903,103.723351],[32.09874,103.722366],[32.09869,103.722183],[32.098431,103.721733],[32.098091,103.721329],[32.098011,103.721268],[32.097778,103.72123],[32.09734,103.721336],[32.096729,103.721321],[32.096039,103.721069],[32.095852,103.72084],[32.095718,103.720329],[32.095692,103.720032],[32.095558,103.719658],[32.095242,103.71949],[32.094551,103.719528],[32.093971,103.719597],[32.093029,103.719841],[32.092461,103.720016],[32.092072,103.719994],[32.09169,103.720093],[32.09132,103.720222],[32.090988,103.720383],[32.090691,103.720467],[32.09034,103.720451],[32.090019,103.72039],[32.08976,103.720177],[32.089458,103.719994],[32.089298,103.719978],[32.08894,103.719887],[32.088661,103.71965],[32.088459,103.719582],[32.08799,103.719368],[32.0877,103.71917],[32.087158,103.718628],[32.086891,103.718407],[32.08662,103.718384],[32.08622,103.718437],[32.085991,103.718513],[32.085491,103.718719],[32.085121,103.718826],[32.08485,103.718964],[32.08456,103.719177],[32.084278,103.719513],[32.083988,103.719597],[32.083691,103.719414],[32.08334,103.719078],[32.083149,103.71891],[32.082939,103.718788],[32.082661,103.718811],[32.082359,103.718948],[32.081539,103.719131],[32.081551,103.719147],[32.08149,103.719147],[32.081402,103.719177],[32.081322,103.719177],[32.081108,103.719292],[32.0807,103.719437],[32.080441,103.719467],[32.079571,103.719292],[32.079418,103.7192],[32.079071,103.718903],[32.078289,103.718468],[32.077709,103.71804],[32.07732,103.717697],[32.077068,103.717644],[32.076691,103.717667],[32.07597,103.71785],[32.075291,103.717949],[32.074791,103.717903],[32.07415,103.717781],[32.073978,103.71769],[32.073811,103.717697],[32.073521,103.71759],[32.073269,103.71756],[32.073101,103.717461],[32.072868,103.717392],[32.072659,103.7173],[32.072201,103.717331],[32.071869,103.717308],[32.071651,103.717239],[32.071442,103.717163],[32.071369,103.717056],[32.071178,103.716927],[32.070919,103.716942],[32.070351,103.717209],[32.069969,103.717339],[32.069939,103.717133],[32.069771,103.716927],[32.071201,103.716042],[32.07135,103.715736],[32.07127,103.715477],[32.070969,103.715363],[32.070621,103.715279],[32.070332,103.715103],[32.070061,103.714867],[32.06992,103.714828],[32.06934,103.714539],[32.06897,103.714447],[32.068741,103.714417],[32.068489,103.714371],[32.068489,103.714256],[32.068359,103.714127],[32.068241,103.71376],[32.068069,103.71347],[32.067909,103.713387],[32.067501,103.713242],[32.06707,103.713173],[32.066971,103.713188],[32.06673,103.713463],[32.066639,103.713783],[32.06649,103.71405],[32.065781,103.714432],[32.065659,103.714233],[32.065651,103.713913],[32.06575,103.71283],[32.065701,103.712608],[32.065639,103.712532],[32.065121,103.71212],[32.065071,103.711838],[32.065239,103.711227],[32.065262,103.710899],[32.06509,103.710602],[32.064751,103.710327],[32.064442,103.710121],[32.064159,103.710213],[32.063801,103.71051],[32.063591,103.710823],[32.06345,103.711143],[32.063278,103.711411],[32.063019,103.711502],[32.06271,103.711517],[32.062469,103.71138],[32.062168,103.711082],[32.06192,103.710777],[32.06189,103.710609],[32.061798,103.710243],[32.061611,103.709633],[32.06134,103.709129],[32.0611,103.708908],[32.06097,103.70874],[32.06094,103.708641],[32.060879,103.708618],[32.060692,103.708397],[32.060551,103.708183],[32.06041,103.707863],[32.06041,103.707817],[32.060459,103.707581],[32.060478,103.707321],[32.06041,103.707062],[32.060181,103.706543],[32.06015,103.70636],[32.060181,103.705681],[32.05999,103.705177],[32.059761,103.704674],[32.05954,103.704399],[32.059391,103.704086],[32.05901,103.703987],[32.058632,103.703957],[32.05806,103.703819],[32.057991,103.703613],[32.05806,103.703194],[32.057499,103.703552],[32.057331,103.703819],[32.05698,103.704231],[32.05648,103.704903],[32.05624,103.705261],[32.056068,103.705452],[32.055962,103.705627],[32.055691,103.705872],[32.0555,103.705994],[32.05529,103.70607],[32.055061,103.7062],[32.054859,103.706284],[32.0546,103.706306],[32.054409,103.705971],[32.0541,103.705528],[32.05405,103.705307],[32.053959,103.705109],[32.053959,103.704964],[32.054081,103.704842],[32.054539,103.704552],[32.054741,103.704468],[32.054859,103.704231],[32.05481,103.703911],[32.054722,103.703659],[32.0546,103.703461],[32.054501,103.703247],[32.054451,103.703056],[32.054619,103.702797],[32.05455,103.702911],[32.056252,103.701553],[32.056499,103.701393],[32.056709,103.70118],[32.056801,103.701027],[32.057209,103.700912],[32.057961,103.700989],[32.058311,103.700768],[32.058529,103.700684],[32.058811,103.700706],[32.059181,103.700844],[32.0592,103.700867],[32.059509,103.701019],[32.059669,103.701073],[32.060009,103.700996],[32.060581,103.700813],[32.06073,103.700661],[32.06078,103.700417],[32.06076,103.700233],[32.06057,103.699951],[32.060429,103.699837],[32.060169,103.699677],[32.058109,103.698669],[32.057529,103.698318],[32.057381,103.698257],[32.057308,103.69825],[32.057011,103.698143],[32.056919,103.69809],[32.05685,103.698013],[32.056671,103.697723],[32.056561,103.697388],[32.056461,103.696854],[32.0564,103.696701],[32.055801,103.695648],[32.055531,103.695229],[32.055012,103.694649],[32.054909,103.69442],[32.05484,103.693748],[32.054829,103.693298],[32.054821,103.693039],[32.05484,103.69265],[32.054699,103.692177],[32.05471,103.692101],[32.054562,103.691803],[32.053829,103.690521],[32.053612,103.690224],[32.053162,103.689713],[32.052589,103.688713],[32.052509,103.688606],[32.05228,103.688454],[32.051979,103.688316],[32.051769,103.688171],[32.05154,103.687897],[32.05138,103.687752],[32.051041,103.687187],[32.05088,103.687027],[32.050549,103.687027],[32.04998,103.687103],[32.049671,103.686989],[32.04921,103.686707],[32.04884,103.68615],[32.048988,103.685677],[32.048859,103.684868],[32.048698,103.684334],[32.04834,103.6828],[32.048092,103.681953],[32.048038,103.681664],[32.048149,103.68132],[32.04829,103.681358],[32.048149,103.681213],[32.047981,103.680946],[32.047791,103.680733],[32.04731,103.680023],[32.046822,103.679764],[32.046478,103.679703],[32.046249,103.679611],[32.046211,103.679604],[32.0462,103.679619],[32.045959,103.679878],[32.045879,103.680122],[32.045681,103.680962],[32.045631,103.681129],[32.045521,103.681473],[32.045311,103.682533],[32.045219,103.682877],[32.04509,103.683601],[32.044991,103.683937],[32.044788,103.684158],[32.044609,103.684196],[32.043598,103.68428],[32.042339,103.684319],[32.04211,103.684349],[32.04179,103.684509],[32.041679,103.684669],[32.0415,103.684883],[32.04113,103.684967],[32.041069,103.684937],[32.040691,103.684624],[32.04034,103.68454],[32.03973,103.684624],[32.039589,103.684593],[32.039341,103.684464],[32.038689,103.683983],[32.038311,103.68383],[32.0382,103.683769],[32.038101,103.683678],[32.037682,103.683083],[32.037521,103.682961],[32.037281,103.682922],[32.037289,103.682953],[32.037029,103.683006],[32.03677,103.68309],[32.036461,103.683273],[32.036072,103.683601],[32.036011,103.683693],[32.035789,103.684303],[32.035461,103.684898],[32.035381,103.686089],[32.033588,103.686653],[32.03339,103.687881],[32.033291,103.688087],[32.033081,103.688461],[32.032982,103.68856],[32.032951,103.688622],[32.03281,103.688744],[32.032391,103.689171],[32.032379,103.689217],[32.03233,103.689247],[32.031929,103.689728],[32.031879,103.689758],[32.0317,103.689934],[32.031361,103.69017],[32.031109,103.690269],[32.030891,103.690323],[32.030621,103.690323],[32.030411,103.690247],[32.029942,103.690117],[32.029812,103.690063],[32.029789,103.690041],[32.029701,103.69001],[32.02953,103.689987],[32.02906,103.689789],[32.02874,103.689713],[32.028679,103.689682],[32.02832,103.689552],[32.027969,103.689598],[32.02779,103.689713],[32.02774,103.689789],[32.027599,103.689911],[32.02747,103.690048],[32.02689,103.690582],[32.026562,103.690826],[32.025902,103.691238],[32.025791,103.691353],[32.02533,103.691628],[32.025211,103.691757],[32.025082,103.691963],[32.02504,103.692108],[32.025021,103.692329],[32.025021,103.692688],[32.02504,103.69278],[32.025021,103.693359],[32.024921,103.693649],[32.024811,103.69381],[32.024632,103.693947],[32.02438,103.694],[32.024231,103.693916],[32.023949,103.693527],[32.02346,103.693108],[32.023392,103.693024],[32.023048,103.692467],[32.0228,103.692017],[32.022049,103.690773],[32.02161,103.68985],[32.02132,103.68856],[32.021198,103.68856],[32.018799,103.687172],[32.018398,103.687973],[32.017841,103.688713],[32.017681,103.688873],[32.01749,103.688988],[32.017269,103.689072],[32.016529,103.689171],[32.01627,103.689232],[32.016109,103.68924],[32.015911,103.689194],[32.015789,103.689087],[32.015659,103.688873],[32.015282,103.688042],[32.01524,103.687988],[32.015141,103.687767],[32.01498,103.6875],[32.014832,103.687309],[32.014671,103.687241],[32.014599,103.687248],[32.014469,103.687302],[32.014351,103.687393],[32.01403,103.687553],[32.013962,103.68763],[32.013512,103.687889],[32.013248,103.687958],[32.013031,103.687897],[32.012581,103.687714],[32.012291,103.687553],[32.01202,103.687332],[32.01173,103.686836],[32.01165,103.686684],[32.011608,103.686623],[32.01152,103.686417],[32.0112,103.685883],[32.01107,103.685593],[32.010941,103.68515],[32.010891,103.684738],[32.010761,103.683968],[32.010681,103.683746],[32.01062,103.683708],[32.010551,103.683678],[32.01012,103.683777],[32.00996,103.683853],[32.009838,103.683937],[32.00935,103.684143],[32.0093,103.684174],[32.009121,103.684242],[32.00806,103.684708],[32.00771,103.684776],[32.006889,103.684822],[32.005989,103.684822],[32.005859,103.684799],[32.00555,103.684593],[32.005421,103.684341],[32.005329,103.684013],[32.00515,103.683601],[32.005001,103.683434],[32.004749,103.683296],[32.004169,103.683273],[32.003941,103.68338],[32.00388,103.68364],[32.00391,103.684212],[32.004059,103.68502],[32.004089,103.685089],[32.004139,103.685707],[32.004219,103.686089],[32.00441,103.686531],[32.004959,103.687462],[32.005562,103.688522],[32.005859,103.689491],[32.005871,103.69001],[32.00568,103.690758],[32.00552,103.691643],[32.004871,103.693199],[32.004799,103.693359],[32.0047,103.693489],[32.00449,103.693489],[32.004379,103.69326],[32.00444,103.692886],[32.004509,103.692108],[32.00449,103.691849],[32.00444,103.691673],[32.004009,103.690979],[32.00378,103.690742],[32.003441,103.690742],[32.003101,103.690804],[32.00272,103.690826],[32.002499,103.690697],[32.002419,103.690392],[32.0023,103.689796],[32.002209,103.689667],[32.00145,103.688766],[32.00124,103.688393],[32.00082,103.687828],[32.000992,103.687607],[32.000961,103.687553],[32.00106,103.687531],[32.001209,103.687347],[32.00016,103.685837],[31.99964,103.685143],[31.99942,103.684769],[31.999229,103.684349],[31.99905,103.683792],[31.998989,103.683434],[31.998949,103.683281],[31.998859,103.683098],[31.998819,103.68306],[31.998409,103.682907],[31.998079,103.682671],[31.997959,103.682503],[31.997829,103.682228],[31.997499,103.682091],[31.997,103.682266],[31.996469,103.682426],[31.99605,103.682426],[31.99486,103.682411],[31.994129,103.681923],[31.99395,103.681549],[31.99382,103.680733],[31.99361,103.680489],[31.993389,103.680641],[31.992479,103.681931],[31.992331,103.682098],[31.99192,103.682259],[31.991211,103.682198],[31.990641,103.682121],[31.989719,103.681847],[31.98885,103.681557],[31.98814,103.681267],[31.98777,103.681091],[31.98768,103.680992],[31.987761,103.680817],[31.987921,103.680878],[31.988609,103.681297],[31.990959,103.681488],[31.991449,103.681488],[31.991989,103.68116],[31.9921,103.680992],[31.99231,103.680511],[31.99242,103.680313],[31.99271,103.680031],[31.992861,103.679916],[31.99299,103.679764],[31.993219,103.67907],[31.9935,103.678726],[31.993641,103.67865],[31.993731,103.678436],[31.99354,103.678329],[31.993441,103.678413],[31.99317,103.678703],[31.99308,103.678848],[31.992929,103.67939],[31.992689,103.67968],[31.992359,103.679787],[31.99194,103.680229],[31.99155,103.680397],[31.99077,103.680252],[31.990499,103.680153],[31.99,103.679901],[31.989771,103.679802],[31.98945,103.679733],[31.98896,103.679604],[31.988859,103.679558],[31.98881,103.679497],[31.988251,103.679222],[31.987749,103.679077],[31.98703,103.679077],[31.98654,103.679153],[31.98535,103.679413],[31.98514,103.67942],[31.984949,103.67939],[31.98477,103.679337],[31.98423,103.678902],[31.98399,103.678673],[31.98382,103.678413],[31.98365,103.677872],[31.983561,103.67691],[31.983561,103.676697],[31.983521,103.676399],[31.983509,103.676422],[31.983419,103.6763],[31.98321,103.676147],[31.983049,103.676079],[31.982861,103.676041],[31.9825,103.676003],[31.982321,103.676003],[31.98192,103.675957],[31.98172,103.675972],[31.981541,103.676003],[31.981211,103.676132],[31.98065,103.67646],[31.98004,103.676773],[31.979469,103.677017],[31.978901,103.677094],[31.97864,103.677101],[31.978121,103.677193],[31.97716,103.677322],[31.97678,103.677353],[31.97662,103.677361],[31.976391,103.677406],[31.975889,103.677467],[31.97518,103.677452],[31.97434,103.677452],[31.972851,103.677422],[31.972481,103.677498],[31.972269,103.677597],[31.972019,103.677711],[31.97098,103.678223],[31.970699,103.678268],[31.97035,103.67823],[31.970209,103.678169],[31.9692,103.677452],[31.969009,103.677406],[31.968861,103.677422],[31.968651,103.677467],[31.968149,103.677643],[31.96809,103.677628],[31.96797,103.677681],[31.96767,103.677963],[31.96734,103.678337],[31.96706,103.678772],[31.96677,103.679108],[31.96656,103.679268],[31.96627,103.679611],[31.96604,103.680023],[31.965691,103.680557],[31.9653,103.680649],[31.964319,103.680389],[31.963421,103.680183],[31.96328,103.679947],[31.96348,103.679878],[31.963539,103.679893],[31.96409,103.680153],[31.96434,103.680191],[31.96452,103.680191],[31.964701,103.680153],[31.96505,103.679962],[31.96534,103.679703],[31.96578,103.679398],[31.966209,103.678726],[31.966619,103.67791],[31.966999,103.677277],[31.96771,103.676239],[31.967979,103.675949],[31.96834,103.675743],[31.96888,103.675522],[31.96911,103.675323],[31.969009,103.675201],[31.96888,103.675278],[31.968691,103.675461],[31.968349,103.675697],[31.96773,103.67601],[31.96744,103.676178],[31.967239,103.676422],[31.96682,103.67717],[31.96637,103.677567],[31.965931,103.677887],[31.965731,103.677994],[31.96524,103.678032],[31.964569,103.677971],[31.96418,103.678108],[31.96356,103.678459],[31.963341,103.678352],[31.963449,103.678131],[31.964211,103.677711],[31.96497,103.677437],[31.96604,103.677391],[31.966471,103.677063],[31.96681,103.676117],[31.967119,103.675697],[31.96789,103.675049],[31.968349,103.674713],[31.968861,103.674477],[31.968941,103.674232],[31.968691,103.674118],[31.968611,103.674133],[31.968361,103.674217],[31.96801,103.674431],[31.96714,103.675072],[31.96664,103.67527],[31.966471,103.675247],[31.966181,103.675323],[31.96574,103.675484],[31.965521,103.675537],[31.96493,103.675636],[31.963949,103.675972],[31.96307,103.676208],[31.96254,103.67617],[31.96192,103.675827],[31.960951,103.675194],[31.960871,103.675133],[31.960739,103.674927],[31.96084,103.67482],[31.961069,103.674911],[31.96154,103.675346],[31.962179,103.675468],[31.962669,103.675468],[31.962879,103.67543],[31.96319,103.675293],[31.96376,103.674843],[31.96398,103.674622],[31.964001,103.674301],[31.963751,103.674339],[31.963039,103.674927],[31.962721,103.675018],[31.962061,103.674911],[31.96166,103.674683],[31.96077,103.673447],[31.96077,103.673424],[31.95982,103.672707],[31.95936,103.672493],[31.95837,103.672241],[31.95751,103.672234],[31.9566,103.672363],[31.95599,103.67218],[31.95553,103.671944],[31.95491,103.671677],[31.953979,103.671417],[31.953461,103.671089],[31.95289,103.67086],[31.95249,103.670731],[31.95084,103.670067],[31.950411,103.670029],[31.950081,103.670082],[31.94912,103.670319],[31.94894,103.670326],[31.948771,103.670303],[31.948521,103.670303],[31.94829,103.670341],[31.948021,103.670441],[31.94791,103.670509],[31.947599,103.670509],[31.94602,103.67038],[31.945841,103.670433],[31.94503,103.670418],[31.94383,103.670372],[31.943661,103.670387],[31.943171,103.670403],[31.942419,103.670448],[31.941509,103.67067],[31.941351,103.670692],[31.941111,103.670776],[31.940821,103.670929],[31.94002,103.671257],[31.93902,103.671547],[31.93849,103.671623],[31.93815,103.671692],[31.937639,103.671738],[31.937469,103.671783],[31.93697,103.671852],[31.93646,103.672043],[31.93585,103.672333],[31.934759,103.672752],[31.93413,103.672867],[31.933599,103.673019],[31.93354,103.673058],[31.932859,103.673279],[31.93256,103.67334],[31.931919,103.673264],[31.931589,103.673149],[31.931379,103.673042],[31.93117,103.672859],[31.930771,103.67276],[31.930531,103.67276],[31.93025,103.672691],[31.929951,103.672691],[31.92959,103.672623],[31.929331,103.672401],[31.929041,103.672379],[31.92865,103.672188],[31.92831,103.672058],[31.92807,103.672012],[31.927919,103.671783],[31.92782,103.671547],[31.92782,103.671547],[31.927719,103.671501],[31.92771,103.671417],[31.92749,103.671432],[31.926901,103.671623],[31.92679,103.671707],[31.926661,103.671753],[31.926371,103.671883],[31.92581,103.672043],[31.925119,103.672096],[31.9249,103.67215],[31.92481,103.672127],[31.92453,103.671997],[31.92415,103.671989],[31.923849,103.672096],[31.92359,103.67215],[31.922529,103.672409],[31.922079,103.672539],[31.921459,103.672783],[31.92091,103.673141],[31.920349,103.673569],[31.919979,103.67379],[31.919319,103.674133],[31.918659,103.674423],[31.91729,103.675049],[31.91678,103.675262],[31.91613,103.675682],[31.91539,103.676239],[31.915359,103.676582],[31.914511,103.677742],[31.914009,103.678291],[31.913601,103.678833],[31.91308,103.678993],[31.912729,103.679131],[31.9121,103.679466],[31.911579,103.679718],[31.91099,103.679832],[31.910271,103.679893],[31.90967,103.679993],[31.9091,103.68026],[31.907619,103.681168],[31.907049,103.681503],[31.906269,103.681839],[31.90589,103.681938],[31.904499,103.682213],[31.904249,103.682297],[31.90403,103.682281],[31.904119,103.682426],[31.903959,103.68248],[31.903431,103.682518],[31.90321,103.682602],[31.901991,103.683411],[31.90144,103.683746],[31.90024,103.684357],[31.899611,103.684769],[31.898359,103.685959],[31.897631,103.686348],[31.89703,103.686691],[31.896799,103.68679],[31.896139,103.686897],[31.89554,103.68692],[31.89493,103.686859],[31.894199,103.68663],[31.89382,103.686569],[31.893709,103.686577],[31.89315,103.686852],[31.89258,103.687492],[31.892191,103.68811],[31.891279,103.689301],[31.890841,103.689812],[31.89011,103.690804],[31.889391,103.691223],[31.889191,103.691292],[31.888929,103.691277],[31.888611,103.691231],[31.88792,103.690979],[31.887289,103.690666],[31.88656,103.690437],[31.886129,103.690376],[31.88599,103.690407],[31.885361,103.690712],[31.885,103.690567],[31.884661,103.690491],[31.884489,103.690613],[31.88435,103.690804],[31.884199,103.691093],[31.88397,103.691597],[31.883671,103.692062],[31.88357,103.692192],[31.88382,103.692307],[31.88278,103.69278],[31.882139,103.69313],[31.88139,103.693382],[31.87995,103.693489],[31.879089,103.693687],[31.87871,103.693871],[31.87858,103.693947],[31.878481,103.693916],[31.878059,103.694077],[31.87727,103.694649],[31.8771,103.694809],[31.876459,103.695236],[31.876011,103.69548],[31.87565,103.695534],[31.875521,103.695457],[31.874981,103.695259],[31.874701,103.695236],[31.874319,103.695343],[31.873831,103.695557],[31.87311,103.695923],[31.872299,103.696114],[31.871611,103.696136],[31.87063,103.696083],[31.87023,103.696098],[31.86994,103.696152],[31.869049,103.696487],[31.86899,103.696548],[31.86886,103.696854],[31.868799,103.697189],[31.86879,103.697708],[31.86862,103.698029],[31.868509,103.698059],[31.86772,103.698013],[31.867599,103.69796],[31.86746,103.69796],[31.867069,103.697998],[31.866871,103.697891],[31.86672,103.69767],[31.866501,103.697449],[31.866051,103.697197],[31.865761,103.696892],[31.865219,103.696541],[31.864599,103.696083],[31.864519,103.695999],[31.86438,103.695717],[31.863899,103.69545],[31.86322,103.695358],[31.862711,103.695427],[31.86134,103.695557],[31.861099,103.695442],[31.86097,103.695412],[31.860649,103.695374],[31.860359,103.695358],[31.860029,103.695427],[31.859529,103.695686],[31.85914,103.695938],[31.858879,103.695969],[31.85874,103.69603],[31.85832,103.696037],[31.858009,103.696136],[31.85664,103.696747],[31.856409,103.696793],[31.856199,103.696777],[31.8557,103.696693],[31.855379,103.696671],[31.85475,103.696823],[31.853951,103.69706],[31.853689,103.69709],[31.853081,103.697052],[31.852369,103.696953],[31.85146,103.696747],[31.850861,103.696648],[31.849831,103.696602],[31.849291,103.696671],[31.848949,103.696671],[31.8487,103.696831],[31.848021,103.696877],[31.847349,103.696777],[31.84696,103.696739],[31.8466,103.696617],[31.8458,103.695999],[31.845579,103.695717],[31.845369,103.695389],[31.845169,103.694893],[31.844761,103.694054],[31.844509,103.693748],[31.84387,103.693314],[31.8437,103.693169],[31.843361,103.693047],[31.84314,103.693153],[31.843069,103.693283],[31.843031,103.693367],[31.842939,103.693893],[31.842859,103.694023],[31.84277,103.694077],[31.841921,103.694344],[31.841619,103.694389],[31.841511,103.694489],[31.841459,103.694504],[31.84137,103.694862],[31.841339,103.695251],[31.84124,103.695763],[31.841061,103.696518],[31.84091,103.696716],[31.8407,103.696854],[31.840509,103.697037],[31.84016,103.697861],[31.839609,103.698853],[31.839121,103.699532],[31.83886,103.70108],[31.838499,103.701141],[31.838421,103.701653],[31.838369,103.702339],[31.838329,103.702591],[31.838249,103.702843],[31.83782,103.703659],[31.836781,103.704193],[31.836821,103.705048],[31.83672,103.705704],[31.83482,103.710823],[31.835489,103.71196],[31.83531,103.712517],[31.835011,103.713013],[31.83404,103.712936],[31.832781,103.716331],[31.83177,103.715919],[31.831129,103.716087],[31.830839,103.716331],[31.83029,103.716728],[31.83008,103.716957],[31.829781,103.717499],[31.829479,103.71814],[31.829161,103.718758],[31.82902,103.718933],[31.828711,103.719254],[31.82844,103.719498],[31.82836,103.719704],[31.828369,103.71981],[31.82831,103.719887],[31.828291,103.719978],[31.82782,103.720734],[31.826111,103.721161],[31.823009,103.724838],[31.822451,103.725182],[31.821369,103.725723],[31.820841,103.726112],[31.82028,103.72644],[31.820021,103.726547],[31.81946,103.726852],[31.819099,103.727173],[31.81893,103.727631],[31.818899,103.727852],[31.818899,103.727951],[31.81883,103.728271],[31.8188,103.728691],[31.81778,103.728409],[31.81743,103.7286],[31.81723,103.728737],[31.81683,103.728958],[31.81637,103.729111],[31.81601,103.729378],[31.815741,103.729462],[31.815371,103.729492],[31.81517,103.729584],[31.814989,103.729752],[31.814989,103.729897],[31.815599,103.730919],[31.81551,103.731392],[31.81539,103.731552],[31.81481,103.731583],[31.813641,103.731087],[31.813419,103.73127],[31.813231,103.731483],[31.81304,103.731712],[31.81291,103.73201],[31.812599,103.732117],[31.81226,103.732399],[31.81201,103.732559],[31.81159,103.732712],[31.81119,103.732674],[31.811069,103.732788],[31.81065,103.732727],[31.81044,103.732819],[31.81044,103.732948],[31.8099,103.732964],[31.809681,103.732986],[31.809259,103.733231],[31.809,103.73333],[31.808741,103.733383],[31.808281,103.733231],[31.8078,103.733177],[31.80777,103.733208],[31.80809,103.734016],[31.80801,103.734131],[31.80776,103.734138],[31.80702,103.733963],[31.806049,103.73391],[31.80595,103.734001],[31.80534,103.734131],[31.805201,103.734467],[31.805201,103.735077],[31.805111,103.735077],[31.805019,103.735962],[31.804911,103.736061],[31.80488,103.736153],[31.804291,103.735771],[31.803391,103.735138],[31.802799,103.734863],[31.802441,103.734749],[31.80213,103.73468],[31.801661,103.734596],[31.801189,103.734482],[31.80093,103.734444],[31.80147,103.733681],[31.80092,103.733597],[31.800369,103.733429],[31.79858,103.732971],[31.7983,103.732933],[31.797649,103.732811],[31.79673,103.732826],[31.796431,103.732918],[31.79594,103.733017],[31.79587,103.73307],[31.795811,103.73317],[31.79587,103.733437],[31.796009,103.733582],[31.795839,103.733742],[31.79594,103.73407],[31.79627,103.734894],[31.795931,103.735298],[31.79587,103.735443],[31.79578,103.735764],[31.795811,103.735786],[31.795839,103.735947],[31.795971,103.73629],[31.796049,103.736839],[31.796089,103.737083],[31.796089,103.737518],[31.79598,103.738052],[31.795971,103.738373],[31.795919,103.738823],[31.795839,103.739319],[31.79579,103.739769],[31.79587,103.740547],[31.796141,103.742592],[31.79608,103.742622],[31.79587,103.742081],[31.79582,103.742561],[31.79558,103.742851],[31.79524,103.743011],[31.79487,103.743393],[31.791531,103.753731],[31.790319,103.753754],[31.78965,103.754066],[31.789061,103.754578],[31.7887,103.755051],[31.78842,103.7556],[31.78825,103.755981],[31.787979,103.756798],[31.787901,103.756958],[31.787571,103.757446],[31.787069,103.758057],[31.78665,103.758438],[31.78623,103.758682],[31.786051,103.758743],[31.784121,103.759537],[31.783621,103.759697],[31.78343,103.759697],[31.783079,103.759857],[31.78252,103.760017],[31.78229,103.760429],[31.781969,103.760643],[31.781691,103.760643],[31.781321,103.760651],[31.78089,103.760803],[31.780479,103.760918],[31.78023,103.761017],[31.780081,103.761139],[31.77957,103.761681],[31.77924,103.762138],[31.7792,103.762253],[31.779119,103.762688],[31.77916,103.763138],[31.77915,103.763344],[31.77903,103.763603],[31.778959,103.763962],[31.77894,103.764267],[31.77887,103.764503],[31.77846,103.765358],[31.778111,103.765938],[31.777809,103.766518],[31.777611,103.766853],[31.777361,103.767357],[31.777241,103.767723],[31.77718,103.768112],[31.777109,103.76886],[31.7771,103.769501],[31.777121,103.769859],[31.77721,103.770309],[31.777361,103.771294],[31.77734,103.771584],[31.777189,103.77227],[31.7771,103.773232],[31.77759,103.774353],[31.776859,103.776382],[31.77779,103.777153],[31.777719,103.777412],[31.777571,103.777603],[31.77737,103.777733],[31.776951,103.777908],[31.77623,103.778259],[31.776159,103.778313],[31.77593,103.778969],[31.774679,103.778999],[31.774561,103.779083],[31.774309,103.779404],[31.77387,103.780411],[31.77351,103.781342],[31.773149,103.782097],[31.773479,103.78299],[31.76511,103.789299],[31.76424,103.788803],[31.764059,103.788918],[31.76396,103.789017],[31.76359,103.78933],[31.763201,103.789612],[31.76284,103.790092],[31.76256,103.790787],[31.76247,103.791367],[31.762871,103.792313],[31.7623,103.793083],[31.763201,103.794403],[31.76347,103.794762],[31.764099,103.795464],[31.764521,103.796158],[31.765039,103.797447],[31.765289,103.798141],[31.765409,103.798553],[31.765511,103.799088],[31.76552,103.799751],[31.765471,103.800423],[31.76553,103.801903],[31.765551,103.802116],[31.76556,103.802422],[31.76553,103.80323],[31.765539,103.805206],[31.76553,103.805862],[31.765511,103.805923],[31.765459,103.807419],[31.765499,103.807999],[31.76549,103.808167],[31.765591,103.808479],[31.765671,103.808777],[31.765909,103.809509],[31.766029,103.809807],[31.7661,103.810127],[31.76622,103.810516],[31.766491,103.81205],[31.76668,103.812691],[31.767071,103.813316],[31.76815,103.814392],[31.768391,103.814743],[31.76856,103.815079],[31.76861,103.815353],[31.76865,103.815804],[31.768539,103.816299],[31.76837,103.816772],[31.76803,103.817413],[31.767691,103.817787],[31.76757,103.817833],[31.76709,103.818169],[31.766491,103.818489],[31.765921,103.818359],[31.765209,103.818123],[31.76478,103.818001],[31.76436,103.817917],[31.764151,103.81794],[31.76396,103.818024],[31.7638,103.818176],[31.762899,103.818771],[31.762751,103.818893],[31.762119,103.819878],[31.761869,103.820221],[31.761511,103.820778],[31.761311,103.821159],[31.760889,103.821877],[31.760509,103.822403],[31.760389,103.822533],[31.76022,103.822693],[31.76004,103.822823],[31.75967,103.822952],[31.759541,103.822952],[31.75906,103.822998],[31.758619,103.823097],[31.75794,103.823311],[31.757521,103.823471],[31.75667,103.823486],[31.751591,103.831108],[31.75139,103.831291],[31.75066,103.831802],[31.75094,103.833023],[31.750351,103.833847],[31.750219,103.833977],[31.750019,103.834091],[31.749229,103.834328],[31.74898,103.834503],[31.748501,103.835091],[31.748199,103.835854],[31.748199,103.835838],[31.747869,103.836678],[31.747589,103.837143],[31.747339,103.83744],[31.74721,103.837669],[31.74711,103.837692],[31.74708,103.837738],[31.746849,103.837769],[31.7467,103.837723],[31.746651,103.837738],[31.74621,103.837601],[31.745951,103.837608],[31.74544,103.837784],[31.74523,103.83783],[31.744459,103.83783],[31.74403,103.837967],[31.74374,103.838074],[31.743549,103.838203],[31.74305,103.838676],[31.74268,103.839233],[31.74264,103.839241],[31.74234,103.839577],[31.74229,103.839592],[31.74169,103.840752],[31.741409,103.841141],[31.741159,103.841011],[31.74094,103.841164],[31.740669,103.841454],[31.738171,103.843643],[31.737659,103.844048],[31.737391,103.844177],[31.737169,103.844238],[31.7369,103.844383],[31.73649,103.84449],[31.73601,103.844513],[31.734369,103.844421],[31.734011,103.844353],[31.73353,103.843582],[31.73074,103.845497],[31.722481,103.851181],[31.721781,103.850327],[31.72146,103.850388],[31.721239,103.850449],[31.7208,103.850632],[31.720289,103.850891],[31.719749,103.851257],[31.71924,103.851646],[31.718679,103.852013],[31.71838,103.852097],[31.71792,103.852119],[31.717039,103.852493],[31.7167,103.8526],[31.716,103.853142],[31.71582,103.853348],[31.7155,103.852966],[31.71513,103.853149],[31.714649,103.853256],[31.714319,103.853317],[31.713989,103.853409],[31.713329,103.853523],[31.712799,103.853447],[31.71246,103.853416],[31.71192,103.853363],[31.711491,103.853279],[31.711149,103.853256],[31.710831,103.853287],[31.710279,103.853523],[31.710039,103.853561],[31.709749,103.853569],[31.709419,103.8535],[31.70919,103.853378],[31.709021,103.853363],[31.70867,103.853432],[31.70829,103.853592],[31.707581,103.85379],[31.707319,103.853844],[31.706829,103.853851],[31.70647,103.853882],[31.706051,103.853889],[31.705891,103.853859],[31.704599,103.853119],[31.704229,103.852859],[31.703501,103.851593],[31.70344,103.851463],[31.70225,103.850548],[31.701151,103.84977],[31.7006,103.849579],[31.700199,103.850067],[31.699499,103.850227],[31.69916,103.850357],[31.697941,103.850883],[31.697689,103.850838],[31.697639,103.850853],[31.698191,103.850487],[31.697781,103.850502],[31.697229,103.850662],[31.696899,103.850662],[31.69673,103.850693],[31.696581,103.850632],[31.696159,103.850243],[31.695869,103.849747],[31.69516,103.848351],[31.69486,103.847588],[31.69433,103.846321],[31.69418,103.845993],[31.69404,103.845657],[31.693939,103.845467],[31.69384,103.845367],[31.69348,103.845093],[31.69335,103.844971],[31.69327,103.844948],[31.69294,103.844727],[31.69268,103.844513],[31.69241,103.844414],[31.692181,103.844368],[31.69173,103.844383],[31.691389,103.844437],[31.69006,103.844933],[31.68998,103.844948],[31.689449,103.844887],[31.68928,103.844833],[31.68854,103.844673],[31.686399,103.844727],[31.685869,103.844772],[31.68545,103.844772],[31.68499,103.84481],[31.6845,103.844833],[31.684099,103.844887],[31.68379,103.84491],[31.68375,103.844948],[31.683599,103.844994],[31.68347,103.844978],[31.683081,103.844879],[31.682541,103.844589],[31.682091,103.844261],[31.681471,103.843887],[31.68079,103.84359],[31.67959,103.84343],[31.6793,103.843353],[31.67861,103.842819],[31.677931,103.842216],[31.677271,103.841614],[31.676781,103.841202],[31.67572,103.84024],[31.67477,103.83934],[31.67441,103.83905],[31.67417,103.838814],[31.673901,103.838577],[31.673281,103.83799],[31.67313,103.837891],[31.672689,103.837433],[31.67164,103.836563],[31.6712,103.836143],[31.669941,103.834976],[31.669479,103.834534],[31.66906,103.834213],[31.66855,103.833969],[31.6682,103.833893],[31.66783,103.833763],[31.667379,103.833633],[31.66733,103.833656],[31.666821,103.833366],[31.66638,103.833031],[31.66555,103.832458],[31.664881,103.831863],[31.663839,103.830544],[31.663401,103.829941],[31.662809,103.829079],[31.662411,103.8284],[31.662041,103.827629],[31.66198,103.827469],[31.661921,103.827377],[31.661631,103.826813],[31.66135,103.826134],[31.66128,103.825989],[31.66123,103.825844],[31.661119,103.82563],[31.66086,103.824982],[31.66082,103.824669],[31.660879,103.824387],[31.661119,103.824112],[31.6614,103.8237],[31.66165,103.823158],[31.66206,103.822563],[31.66206,103.822166],[31.66115,103.82093],[31.6605,103.819977],[31.66037,103.819511],[31.6604,103.819298],[31.66054,103.819008],[31.661131,103.818253],[31.662029,103.817177],[31.66238,103.816566],[31.66254,103.816109],[31.66251,103.816078],[31.662821,103.815193],[31.662979,103.814796],[31.663099,103.814362],[31.66312,103.813957],[31.663,103.813606],[31.662861,103.813271],[31.662609,103.812897],[31.662161,103.812553],[31.661501,103.812119],[31.661381,103.812057],[31.66119,103.811897],[31.66066,103.811737],[31.657261,103.811653],[31.656969,103.811607],[31.656799,103.811607],[31.65591,103.811508],[31.65435,103.811256],[31.65407,103.81115],[31.65349,103.810959],[31.65291,103.810699],[31.65218,103.810318],[31.65169,103.810028],[31.651421,103.809837],[31.65086,103.809486],[31.650181,103.809013],[31.64917,103.80835],[31.64901,103.808273],[31.648069,103.80764],[31.64772,103.807457],[31.64661,103.806664],[31.646,103.806282],[31.645321,103.805817],[31.64521,103.805771],[31.644779,103.805473],[31.64201,103.803658],[31.64163,103.803429],[31.641411,103.803261],[31.640711,103.802788],[31.640459,103.80265],[31.640051,103.802353],[31.63879,103.801537],[31.638399,103.801224],[31.63818,103.800911],[31.637899,103.800056],[31.637699,103.799606],[31.63752,103.79937],[31.637421,103.799309],[31.637091,103.799179],[31.636299,103.798683],[31.63612,103.798439],[31.636049,103.79818],[31.63599,103.797836],[31.63596,103.797417],[31.63578,103.796913],[31.63439,103.795692],[31.633631,103.79509],[31.633011,103.794724],[31.63138,103.793823],[31.630911,103.793266],[31.63064,103.792877],[31.630251,103.792221],[31.628441,103.789413],[31.627769,103.788399],[31.62665,103.786667],[31.626141,103.786324],[31.625351,103.786057],[31.624701,103.785873],[31.62455,103.785858],[31.623051,103.786079],[31.62244,103.785873],[31.622271,103.78569],[31.621571,103.784348],[31.620819,103.782867],[31.62027,103.781723],[31.620211,103.781509],[31.62023,103.780823],[31.620359,103.779968],[31.620359,103.779022],[31.62023,103.776962],[31.62007,103.77623],[31.619789,103.775642],[31.61961,103.775467],[31.619471,103.775192],[31.619471,103.775131],[31.61939,103.775017],[31.61923,103.774712],[31.618891,103.77417],[31.618549,103.773529],[31.6182,103.772949],[31.617941,103.772743],[31.6178,103.772667],[31.617611,103.772621],[31.615549,103.772438],[31.615431,103.772453],[31.61515,103.772438],[31.61446,103.772339],[31.6124,103.772141],[31.611521,103.771957],[31.611401,103.771889],[31.61091,103.771347],[31.610479,103.770729],[31.609631,103.769333],[31.609159,103.768631],[31.608749,103.767776],[31.60873,103.767029],[31.60874,103.766586],[31.60874,103.766281],[31.608841,103.765717],[31.60885,103.765213],[31.608801,103.764809],[31.60874,103.764587],[31.6085,103.763832],[31.608351,103.763412],[31.608299,103.763184],[31.60766,103.7612],[31.607519,103.760681],[31.60745,103.760246],[31.60742,103.759247],[31.60746,103.758263],[31.607491,103.758011],[31.607479,103.757538],[31.60751,103.755051],[31.60742,103.754303],[31.60717,103.753563],[31.6071,103.753403],[31.606939,103.753181],[31.606911,103.753014],[31.606859,103.752869],[31.60623,103.751663],[31.606039,103.751427],[31.605419,103.750862],[31.60511,103.750618],[31.604509,103.750183],[31.603661,103.749817],[31.60322,103.749542],[31.602449,103.749207],[31.60186,103.749046],[31.60113,103.748894],[31.600531,103.748779],[31.600149,103.748749],[31.599739,103.74881],[31.599489,103.748947],[31.599791,103.750053],[31.59976,103.750511],[31.59939,103.750511],[31.598949,103.750381],[31.598301,103.749687],[31.597931,103.749947],[31.59779,103.750061],[31.59738,103.750267],[31.597139,103.750298],[31.596889,103.750267],[31.59667,103.750229],[31.595501,103.750107],[31.595249,103.750107],[31.594379,103.750031],[31.593941,103.749969],[31.593651,103.749893],[31.59326,103.749657],[31.59285,103.749336],[31.591949,103.748558],[31.59079,103.74762],[31.589581,103.74659],[31.58902,103.746071],[31.58843,103.745483],[31.587721,103.744789],[31.586809,103.743843],[31.585581,103.742828],[31.585119,103.742523],[31.58432,103.741852],[31.584089,103.741547],[31.583691,103.740662],[31.5835,103.740356],[31.58338,103.74012],[31.583389,103.739594],[31.58337,103.739517],[31.583269,103.73941],[31.58316,103.739052],[31.58317,103.738792],[31.583099,103.738708],[31.582979,103.738319],[31.582911,103.738052],[31.58285,103.737244],[31.583099,103.735764],[31.58333,103.734688],[31.583441,103.733932],[31.583599,103.73304],[31.58354,103.732521],[31.583509,103.732407],[31.583321,103.732109],[31.583139,103.731934],[31.582781,103.731773],[31.58251,103.731468],[31.582439,103.731194],[31.582399,103.730988],[31.58235,103.730873],[31.582319,103.730713],[31.58205,103.730408],[31.581869,103.730232],[31.58148,103.729797],[31.581249,103.729568],[31.57992,103.728477],[31.579309,103.728127],[31.578699,103.727837],[31.57826,103.727676],[31.577909,103.727654],[31.57765,103.727661],[31.577391,103.727859],[31.57725,103.728027],[31.577181,103.728218],[31.577049,103.728989],[31.57687,103.729736],[31.57692,103.729759],[31.576811,103.730118],[31.576521,103.73053],[31.57486,103.731537],[31.574511,103.731621],[31.57411,103.731613],[31.572451,103.731178],[31.572081,103.731049],[31.57181,103.730904],[31.571581,103.730659],[31.57115,103.730003],[31.57091,103.729698],[31.570841,103.729446],[31.570551,103.728958],[31.570419,103.728668],[31.570259,103.727829],[31.570221,103.727303],[31.570259,103.726196],[31.570601,103.725067],[31.571039,103.723846],[31.571091,103.723778],[31.571409,103.723427],[31.571951,103.723061],[31.572781,103.72226],[31.572981,103.721764],[31.573111,103.720444],[31.57321,103.719803],[31.57345,103.717644],[31.57349,103.717079],[31.57333,103.716583],[31.572769,103.715477],[31.57268,103.715317],[31.57251,103.714951],[31.572399,103.714767],[31.572121,103.714607],[31.570459,103.714119],[31.57028,103.714073],[31.56971,103.714188],[31.569071,103.714523],[31.56881,103.71463],[31.56859,103.714638],[31.56839,103.714592],[31.56753,103.714233],[31.567221,103.71405],[31.566891,103.713669],[31.56612,103.712608],[31.56591,103.712273],[31.56567,103.711967],[31.565531,103.7117],[31.565269,103.710907],[31.565241,103.710709],[31.56505,103.708588],[31.564871,103.707779],[31.56448,103.70652],[31.56403,103.7052],[31.563551,103.704109],[31.56237,103.701767],[31.56175,103.70079],[31.561319,103.700592],[31.56106,103.700706],[31.560499,103.701073],[31.560169,103.700996],[31.559509,103.700127],[31.55743,103.697662],[31.557249,103.697479],[31.55703,103.697067],[31.556971,103.696693],[31.556971,103.696404],[31.55706,103.695908],[31.5571,103.695534],[31.55711,103.695259],[31.557211,103.694489],[31.557289,103.693314],[31.55723,103.692993],[31.55699,103.692467],[31.556499,103.691849],[31.555901,103.691437],[31.555229,103.691093],[31.554729,103.690727],[31.553869,103.690033],[31.55308,103.689453],[31.55245,103.689293],[31.55179,103.689331],[31.5515,103.689194],[31.551279,103.688927],[31.551201,103.68882],[31.551069,103.68856],[31.550911,103.688332],[31.55088,103.688263],[31.550791,103.688141],[31.55068,103.687943],[31.550501,103.687691],[31.55039,103.687492],[31.550249,103.687332],[31.550039,103.686989],[31.549721,103.686569],[31.549561,103.686401],[31.54932,103.686073],[31.549061,103.685806],[31.548849,103.685654],[31.548201,103.685471],[31.546721,103.685173],[31.54623,103.685043],[31.545071,103.684883],[31.544661,103.684914],[31.54361,103.685059],[31.542259,103.685219],[31.541861,103.685226],[31.54143,103.68512],[31.54108,103.684959],[31.540331,103.684486],[31.539591,103.684113],[31.539339,103.683937],[31.538879,103.683456],[31.53878,103.683273],[31.538549,103.682693],[31.53841,103.682228],[31.538349,103.682083],[31.53797,103.681633],[31.537781,103.681549],[31.53731,103.681503],[31.536909,103.681633],[31.536739,103.681793],[31.53632,103.682243],[31.535919,103.682571],[31.53581,103.682632],[31.53521,103.682831],[31.5347,103.682961],[31.534069,103.683067],[31.533119,103.683151],[31.532459,103.683151],[31.532169,103.682983],[31.531931,103.682549],[31.53187,103.682388],[31.531691,103.682007],[31.531469,103.681419],[31.531269,103.681068],[31.53096,103.680771],[31.53055,103.680618],[31.53031,103.680397],[31.53005,103.680122],[31.52984,103.679527],[31.529831,103.679237],[31.52985,103.678467],[31.529909,103.678139],[31.529831,103.677742],[31.529591,103.677254],[31.529289,103.676773],[31.52895,103.676277],[31.52866,103.675941],[31.528271,103.675453],[31.527849,103.675003],[31.526911,103.674347],[31.525351,103.67337],[31.5249,103.673058],[31.524019,103.672531],[31.523661,103.672401],[31.52273,103.672012],[31.522129,103.671738],[31.521561,103.671509],[31.521231,103.67131],[31.52075,103.670868],[31.52038,103.670471],[31.520069,103.670227],[31.519911,103.670128],[31.51977,103.670013],[31.518841,103.669434],[31.518539,103.669327],[31.5182,103.669296],[31.516991,103.669312],[31.516451,103.669228],[31.516319,103.669167],[31.51606,103.668999],[31.515751,103.668556],[31.51548,103.668114],[31.515421,103.667801],[31.5154,103.667542],[31.515381,103.666924],[31.515329,103.666283],[31.515261,103.665817],[31.51515,103.665497],[31.51512,103.664787],[31.51515,103.664192],[31.51516,103.66349],[31.51511,103.66272],[31.5149,103.662178],[31.514629,103.661797],[31.514311,103.66124],[31.51392,103.660606],[31.513571,103.660072],[31.51343,103.65992],[31.51298,103.659317],[31.51251,103.658638],[31.512381,103.658386],[31.5123,103.658096],[31.51219,103.657417],[31.5121,103.656967],[31.512091,103.65657],[31.5121,103.656174],[31.51206,103.655632],[31.51227,103.654694],[31.51231,103.653923],[31.51231,103.653488],[31.512251,103.653],[31.51214,103.652657],[31.51195,103.652367],[31.511379,103.651993],[31.51108,103.651909],[31.51009,103.651833],[31.509399,103.651611],[31.509001,103.65139],[31.50861,103.651253],[31.508169,103.651001],[31.50762,103.650551],[31.507179,103.650223],[31.506929,103.650146],[31.506809,103.650017],[31.50654,103.649467],[31.506161,103.648819],[31.505791,103.648247],[31.505501,103.647942],[31.50522,103.647743],[31.50474,103.64743],[31.5044,103.647377],[31.503639,103.647423],[31.50312,103.647408],[31.50276,103.647362],[31.50252,103.647293],[31.502279,103.647186],[31.50178,103.647293],[31.50156,103.647324],[31.501129,103.647163],[31.50087,103.647011],[31.499599,103.646423],[31.499189,103.64592],[31.49877,103.64518],[31.49864,103.644798],[31.498529,103.644257],[31.49844,103.643959],[31.498249,103.643623],[31.49818,103.643509],[31.49803,103.643204],[31.49761,103.642769],[31.49737,103.64241],[31.497351,103.642281],[31.496889,103.641319],[31.49667,103.640373],[31.49663,103.640022],[31.49654,103.639511],[31.49651,103.639214],[31.496559,103.638962],[31.496651,103.638741],[31.496771,103.638527],[31.496889,103.638321],[31.49692,103.638],[31.496679,103.637642],[31.496361,103.637306],[31.49608,103.637123],[31.495819,103.637016],[31.495211,103.636902],[31.495001,103.636887],[31.4946,103.636818],[31.49444,103.636742],[31.49408,103.636436],[31.493879,103.636208],[31.49338,103.635498],[31.493259,103.635101],[31.49325,103.63456],[31.493299,103.634087],[31.49329,103.634064],[31.49328,103.633797],[31.493179,103.633537],[31.49304,103.633362],[31.49292,103.63311],[31.49287,103.632629],[31.492889,103.632347],[31.49287,103.632141],[31.49279,103.631889],[31.49268,103.631683],[31.492519,103.631279],[31.49246,103.631027],[31.49229,103.630524],[31.492279,103.630211],[31.49213,103.629646],[31.49206,103.629494],[31.492041,103.629478],[31.49194,103.629204],[31.49168,103.628479],[31.491529,103.627823],[31.491541,103.627007],[31.491779,103.625931],[31.49194,103.625412],[31.49206,103.625076],[31.49214,103.624893],[31.492161,103.624718],[31.49226,103.624557],[31.49284,103.624184],[31.493641,103.623482],[31.494209,103.622757],[31.49416,103.622543],[31.493589,103.621727],[31.493231,103.621323],[31.492849,103.621063],[31.49229,103.620827],[31.49198,103.62072],[31.491289,103.620644],[31.4911,103.620537],[31.490971,103.62043],[31.49082,103.62014],[31.490959,103.619667],[31.491131,103.619537],[31.49202,103.619431],[31.49262,103.619301],[31.492849,103.619164],[31.493589,103.618568],[31.493971,103.618217],[31.49407,103.618088],[31.49424,103.617722],[31.494249,103.617439],[31.494209,103.61702],[31.49416,103.616814],[31.49394,103.616463],[31.493799,103.616333],[31.49304,103.615288],[31.49287,103.614967],[31.49275,103.614693],[31.49246,103.61438],[31.49251,103.614326],[31.492359,103.614159],[31.4921,103.613907],[31.492029,103.613792],[31.491261,103.612923],[31.49037,103.611641],[31.489941,103.611397],[31.48942,103.611343],[31.489161,103.611237],[31.488001,103.611008],[31.48781,103.611],[31.48749,103.610901],[31.48715,103.610863],[31.48699,103.610863],[31.48642,103.610641],[31.485809,103.610527],[31.485399,103.610321],[31.48514,103.610168],[31.4848,103.609711],[31.48461,103.609352],[31.484529,103.609108],[31.48443,103.608566],[31.484421,103.608223],[31.484249,103.60759],[31.484171,103.60746],[31.484011,103.607246],[31.48378,103.60685],[31.483641,103.606483],[31.48325,103.605629],[31.48311,103.605347],[31.48307,103.605148],[31.48288,103.604584],[31.48271,103.604187],[31.482441,103.603287],[31.482109,103.602463],[31.481991,103.602074],[31.48176,103.601486],[31.481529,103.601044],[31.48126,103.600342],[31.48111,103.60006],[31.480829,103.599457],[31.48035,103.598396],[31.479919,103.597481],[31.479851,103.597382],[31.479401,103.596352],[31.47921,103.596039],[31.47884,103.59549],[31.478701,103.595261],[31.47863,103.59478],[31.478609,103.594254],[31.47863,103.59391],[31.478939,103.591682],[31.47924,103.590721],[31.47921,103.590088],[31.47917,103.589813],[31.479179,103.589661],[31.47929,103.588966],[31.47933,103.588593],[31.479521,103.587677],[31.479679,103.586761],[31.479891,103.585663],[31.47998,103.584953],[31.48003,103.584641],[31.480061,103.584351],[31.480089,103.584023],[31.47991,103.583214],[31.47979,103.58284],[31.47925,103.581673],[31.479031,103.581337],[31.478769,103.580887],[31.478291,103.580223],[31.47813,103.579971],[31.47789,103.579399],[31.477711,103.578911],[31.477579,103.578613],[31.47744,103.57827],[31.477369,103.578049],[31.477171,103.577744],[31.47682,103.577278],[31.476589,103.577057],[31.47645,103.576981],[31.47596,103.576874],[31.475651,103.576843],[31.47522,103.576736],[31.474939,103.576721],[31.474701,103.576691],[31.474701,103.576538],[31.47485,103.57589],[31.47493,103.575394],[31.474899,103.575012],[31.47488,103.574982],[31.474701,103.574913],[31.47438,103.574913],[31.4736,103.574699],[31.47336,103.574677],[31.47287,103.574707],[31.472691,103.574692],[31.472071,103.573463],[31.47057,103.572227],[31.469021,103.570557],[31.467991,103.569771],[31.467079,103.569771],[31.46619,103.570038],[31.46537,103.570297],[31.464979,103.570297],[31.46344,103.569809],[31.46101,103.568909],[31.460279,103.568176],[31.459869,103.566643],[31.459511,103.564423],[31.45912,103.562363],[31.45895,103.561737],[31.45866,103.561172],[31.457279,103.558601],[31.456921,103.557899],[31.45583,103.555847],[31.45546,103.555267],[31.45499,103.554581],[31.454519,103.55394],[31.454309,103.553558],[31.454201,103.552887],[31.454559,103.551971],[31.454941,103.551086],[31.45583,103.549187],[31.45603,103.548561],[31.456051,103.547821],[31.455839,103.54734],[31.45536,103.546867],[31.45483,103.546669],[31.454321,103.546539],[31.45405,103.54644],[31.45322,103.545769],[31.452959,103.545502],[31.45269,103.545273],[31.452419,103.545273],[31.45207,103.545097],[31.45167,103.544968],[31.4515,103.544937],[31.45006,103.544777],[31.449619,103.544678],[31.448759,103.544289],[31.447929,103.543854],[31.446199,103.542969],[31.445761,103.542709],[31.445221,103.542221],[31.44474,103.541649],[31.444201,103.5411],[31.44396,103.540993],[31.44367,103.540916],[31.44301,103.54097],[31.439659,103.541473],[31.43886,103.541656],[31.43778,103.542038],[31.43689,103.542381],[31.436449,103.542473],[31.4356,103.542572],[31.43504,103.542603],[31.43441,103.542709],[31.43392,103.542732],[31.43346,103.542732],[31.433439,103.542702],[31.43302,103.542763],[31.43259,103.542961],[31.42981,103.544456],[31.429331,103.544563],[31.429131,103.54454],[31.428671,103.544243],[31.42819,103.543793],[31.42675,103.542313],[31.42621,103.541862],[31.425631,103.541344],[31.4251,103.540894],[31.42322,103.539574],[31.42255,103.539131],[31.420071,103.537849],[31.419399,103.537537],[31.418791,103.537178],[31.41828,103.536774],[31.41699,103.535599],[31.41613,103.534889],[31.415621,103.534599],[31.415159,103.534439],[31.414471,103.534264],[31.4142,103.534172],[31.4135,103.533989],[31.41247,103.533699],[31.41194,103.533478],[31.4118,103.533379],[31.411671,103.533257],[31.41148,103.533012],[31.411209,103.532547],[31.41111,103.53241],[31.410629,103.531464],[31.41045,103.531174],[31.410061,103.530838],[31.409889,103.530731],[31.40934,103.530617],[31.409149,103.530602],[31.40756,103.530182],[31.405861,103.52977],[31.405149,103.529556],[31.404869,103.529404],[31.40461,103.529167],[31.404289,103.528397],[31.4041,103.527321],[31.403919,103.526123],[31.403549,103.523849],[31.403299,103.523109],[31.403049,103.522797],[31.402411,103.522438],[31.401699,103.522278],[31.4014,103.522232],[31.399179,103.521721],[31.398439,103.52153],[31.39542,103.520851],[31.39481,103.520683],[31.394239,103.520287],[31.39345,103.5196],[31.39155,103.517853],[31.39131,103.517677],[31.38913,103.515678],[31.389139,103.515663],[31.389111,103.515671],[31.38839,103.515022],[31.38792,103.514572],[31.3871,103.513901],[31.386959,103.513748],[31.372419,103.509407],[31.372141,103.509369],[31.37159,103.509079],[31.371031,103.508568],[31.370649,103.508171],[31.370449,103.507912],[31.36974,103.507149],[31.369089,103.506401],[31.36894,103.506187],[31.36865,103.505577],[31.36833,103.5047],[31.36797,103.503563],[31.36692,103.500427],[31.36664,103.499542],[31.366489,103.499138],[31.366409,103.498779],[31.366329,103.49865],[31.366199,103.498291],[31.36598,103.49752],[31.365681,103.49704],[31.364771,103.496407],[31.36245,103.494919],[31.36208,103.494667],[31.361071,103.494041],[31.359541,103.493042],[31.35741,103.491707],[31.35729,103.491661],[31.35708,103.491631],[31.3564,103.4916],[31.355619,103.491638],[31.355021,103.491547],[31.35438,103.491257],[31.35321,103.490623],[31.35268,103.490349],[31.352221,103.490082],[31.35165,103.489799],[31.35129,103.489647],[31.350531,103.489464],[31.34993,103.489326],[31.34919,103.489143],[31.34828,103.488937],[31.347219,103.488564],[31.346821,103.488358],[31.346279,103.488037],[31.34433,103.486763],[31.34374,103.486504],[31.343491,103.486443],[31.342831,103.486427],[31.342421,103.486519],[31.342251,103.486572],[31.34177,103.486649],[31.340799,103.486862],[31.340321,103.486931],[31.339331,103.487167],[31.339029,103.48719],[31.338591,103.487122],[31.33721,103.486099],[31.336519,103.485413],[31.33604,103.484711],[31.33556,103.483917],[31.335421,103.483276],[31.33383,103.480087],[31.333611,103.479721],[31.333361,103.479378],[31.333019,103.479057],[31.332359,103.478569],[31.33135,103.477859],[31.330931,103.477432],[31.33073,103.477013],[31.32996,103.47448],[31.329849,103.474258],[31.32967,103.47403],[31.32946,103.473862],[31.32926,103.473793],[31.328569,103.473801],[31.32366,103.474693],[31.322969,103.474777],[31.322241,103.474907],[31.321489,103.474937],[31.320959,103.47477],[31.320721,103.474617],[31.32004,103.474167],[31.31922,103.473587],[31.31871,103.473312],[31.31826,103.473183],[31.3176,103.473129],[31.31675,103.473099],[31.314791,103.473061],[31.314131,103.472977],[31.313431,103.472839],[31.31291,103.472748],[31.311569,103.472473],[31.31142,103.47245],[31.310841,103.47229],[31.310711,103.472237],[31.31061,103.472168],[31.310511,103.472069],[31.310221,103.471672],[31.30938,103.470322],[31.30928,103.470108],[31.30896,103.469612],[31.30871,103.469307],[31.308189,103.468964],[31.30788,103.468842],[31.30744,103.468697],[31.306231,103.468193],[31.30521,103.467827],[31.303169,103.466942],[31.302691,103.466766],[31.302429,103.46669],[31.301991,103.466507],[31.3016,103.466209],[31.301519,103.466164],[31.3015,103.466057],[31.301161,103.465897],[31.30098,103.465851],[31.300831,103.465759],[31.30061,103.465729],[31.300011,103.465698],[31.299561,103.465477],[31.2994,103.465157],[31.299179,103.464828],[31.29841,103.464378],[31.29821,103.464104],[31.298149,103.463753],[31.29805,103.463463],[31.29759,103.463226],[31.297171,103.462921],[31.295549,103.462402],[31.289801,103.460899],[31.28867,103.461166],[31.280279,103.469017],[31.27939,103.469353],[31.27865,103.470039],[31.277781,103.471283],[31.27607,103.474007],[31.274839,103.474609],[31.273741,103.474922],[31.27346,103.474907],[31.27326,103.474876],[31.273069,103.474823],[31.272539,103.474747],[31.27182,103.475014],[31.271271,103.475098],[31.27033,103.475189],[31.269159,103.475159],[31.26734,103.475319],[31.26685,103.475456],[31.26601,103.475906],[31.26573,103.476089],[31.264391,103.477097],[31.26379,103.477753],[31.26339,103.478279],[31.263041,103.479218],[31.26285,103.479637],[31.26289,103.480217],[31.26284,103.480522],[31.262449,103.481049],[31.261801,103.481667],[31.26133,103.482147],[31.260521,103.482559],[31.25906,103.480049],[31.257441,103.480988],[31.250851,103.486687],[31.249491,103.488113],[31.24909,103.488403],[31.24823,103.488411],[31.2472,103.487907],[31.24691,103.487778],[31.24605,103.487694],[31.231581,103.492683],[31.22551,103.486893],[31.20331,103.497948],[31.17948,103.496834],[31.160801,103.494209],[31.156799,103.491173],[31.148029,103.488243],[31.140209,103.48967],[31.13055,103.494873],[31.122959,103.496063],[31.118771,103.494431],[31.11475,103.489479],[31.11301,103.485519],[31.11005,103.483063],[31.107821,103.481087],[31.10568,103.479523],[31.1042,103.478653],[31.102659,103.478302],[31.1021,103.478157],[31.101521,103.478127],[31.1012,103.478233],[31.10042,103.478691],[31.09967,103.478943],[31.098499,103.479149],[31.098141,103.479118],[31.097481,103.479111],[31.097071,103.479134],[31.096581,103.479263],[31.0959,103.479858],[31.09536,103.480507],[31.09507,103.481194],[31.09473,103.482063],[31.094601,103.482246],[31.09396,103.483131],[31.09333,103.483788],[31.092581,103.484711],[31.091961,103.485336],[31.09182,103.485428],[31.091551,103.485481],[31.09111,103.485313],[31.0909,103.48513],[31.090441,103.484558],[31.09029,103.484444],[31.089769,103.484253],[31.089439,103.484322],[31.089211,103.484489],[31.088739,103.484894],[31.08844,103.485107],[31.08814,103.48526],[31.08798,103.485313],[31.087151,103.485283],[31.08099,103.485023],[31.08004,103.484787],[31.07909,103.484596],[31.07826,103.484528],[31.07803,103.484528],[31.076891,103.484703],[31.076639,103.484787],[31.07621,103.484901],[31.07493,103.485321],[31.07374,103.486191],[31.07304,103.486572],[31.072531,103.4869],[31.072001,103.487381],[31.07168,103.487602],[31.071199,103.487823],[31.07078,103.488029],[31.070181,103.488373],[31.06941,103.488876],[31.06925,103.489197],[31.068439,103.489433],[31.06757,103.489807],[31.06679,103.490547],[31.066259,103.490631],[31.065491,103.490921],[31.06476,103.491257],[31.064449,103.491547],[31.06436,103.491722],[31.064289,103.491898],[31.0641,103.492142],[31.063959,103.492287],[31.06378,103.492561],[31.06341,103.493294],[31.063021,103.494453],[31.04641,103.526978],[31.045561,103.528099],[31.045469,103.528198],[31.044621,103.52887],[31.04331,103.529427],[31.04154,103.529877],[31.03215,103.534622],[31.031231,103.535057],[31.02936,103.535568],[31.028521,103.535843],[31.028061,103.536072],[31.02762,103.536369],[31.0271,103.536819],[31.026369,103.537727],[31.02529,103.539307],[31.024401,103.540733],[31.02223,103.543907],[31.0205,103.546577],[31.01989,103.547508],[31.019421,103.548233],[31.018761,103.549217],[31.01827,103.550056],[31.016239,103.554207],[31,103.586853],[30.998091,103.59005],[30.997681,103.590523],[30.997181,103.590973],[30.996849,103.591232],[30.99613,103.591728],[30.994261,103.592941],[30.99297,103.593803],[30.99185,103.594482],[30.989941,103.594841],[30.988621,103.594322],[30.987591,103.59417],[30.986259,103.593773],[30.98485,103.593773],[30.98218,103.594559],[30.98111,103.594566],[30.979811,103.594269],[30.977461,103.59359],[30.976021,103.5933],[30.975691,103.593277],[30.974489,103.5933],[30.968679,103.594116],[30.964621,103.594727],[30.964001,103.594841],[30.96237,103.595337],[30.96122,103.596024],[30.960211,103.59697],[30.959351,103.598152],[30.958561,103.599762],[30.956551,103.604424],[30.955151,103.607269],[30.95435,103.608627],[30.95089,103.613831],[30.95076,103.614052],[30.950279,103.614952],[30.94981,103.615753],[30.95084,103.615593],[30.95225,103.615532],[30.953581,103.61544],[30.95606,103.615318],[30.95643,103.615288],[30.956989,103.615211],[30.957359,103.615143],[30.957899,103.614998],[30.958441,103.614822],[30.959141,103.614571],[30.959829,103.614304],[30.96102,103.613876],[30.96183,103.613579],[30.962391,103.613373],[30.9631,103.614807],[30.96336,103.615799],[30.963539,103.616302],[30.96368,103.616631],[30.96384,103.616966],[30.965599,103.620323],[30.96623,103.621567],[30.967489,103.624222],[30.9722,103.633148],[30.977289,103.642822],[30.979099,103.645447],[30.978251,103.646347],[30.976589,103.647888],[30.974079,103.650269],[30.97238,103.65197],[30.970909,103.653526],[30.969839,103.654716],[30.968639,103.656143],[30.96751,103.657547],[30.96689,103.658363],[30.96583,103.65979],[30.964109,103.662231],[30.96328,103.663368],[30.962151,103.664833],[30.96097,103.66626],[30.960381,103.667],[30.96023,103.667236],[30.960091,103.667473],[30.95998,103.667747],[30.959789,103.667877],[30.95978,103.667747],[30.959209,103.668411],[30.9589,103.668793],[30.958099,103.669853],[30.957161,103.671143],[30.95595,103.672943],[30.955231,103.674072],[30.952909,103.677902],[30.95179,103.679703],[30.95059,103.681709],[30.949539,103.683418],[30.948919,103.684387],[30.948441,103.685112],[30.946659,103.687637],[30.945499,103.689217],[30.944401,103.690613],[30.94367,103.691513],[30.941299,103.694313],[30.93787,103.698303],[30.9366,103.69986],[30.935209,103.701637],[30.933901,103.703407],[30.933069,103.704597],[30.932249,103.705803],[30.93026,103.708878],[30.92915,103.710564],[30.928301,103.711777],[30.92745,103.712952],[30.926741,103.713837],[30.926001,103.714722],[30.92543,103.715347],[30.924641,103.716148],[30.923651,103.717117],[30.922649,103.718063],[30.92116,103.71936],[30.919451,103.720932],[30.918831,103.721542],[30.91785,103.722572],[30.917471,103.722992],[30.91674,103.723831],[30.91588,103.724892],[30.91522,103.725761],[30.914129,103.727333],[30.913691,103.728027],[30.913139,103.728973],[30.9126,103.729927],[30.912069,103.730949],[30.91169,103.731743],[30.911209,103.732803],[30.91054,103.734383],[30.910151,103.735451],[30.90979,103.736519],[30.907459,103.744202],[30.90659,103.746933],[30.906219,103.747978],[30.90593,103.748749],[30.90542,103.749992],[30.904989,103.750977],[30.904369,103.752274],[30.90366,103.753609],[30.902901,103.754898],[30.902121,103.756119],[30.901489,103.757042],[30.900669,103.758133],[30.900181,103.758751],[30.899691,103.759354],[30.89871,103.760468],[30.897711,103.76152],[30.8972,103.762016],[30.896469,103.762703],[30.895241,103.763748],[30.894569,103.764267],[30.89386,103.764793],[30.892929,103.765442],[30.89245,103.765747],[30.89105,103.766602],[30.888321,103.768097],[30.887011,103.768806],[30.885719,103.769524],[30.884649,103.770149],[30.88401,103.770561],[30.88294,103.771317],[30.88183,103.772202],[30.88139,103.772591],[30.880751,103.773193],[30.87995,103.773979],[30.879379,103.774582],[30.87867,103.775398],[30.87817,103.776016],[30.87768,103.776649],[30.877211,103.777298],[30.87676,103.777946],[30.876011,103.779152],[30.875561,103.779938],[30.875271,103.780487],[30.87471,103.781616],[30.873949,103.783363],[30.873369,103.784813],[30.872669,103.786507],[30.87229,103.787331],[30.871759,103.788399],[30.871731,103.78846],[30.871059,103.789703],[30.87076,103.790207],[30.8703,103.790939],[30.86948,103.792137],[30.869141,103.792603],[30.86861,103.793266],[30.867701,103.794357],[30.867149,103.794991],[30.86639,103.795761],[30.86561,103.796501],[30.864811,103.797203],[30.861601,103.799957],[30.859289,103.80191],[30.858471,103.802628],[30.85726,103.803719],[30.856291,103.804657],[30.85533,103.805634],[30.854509,103.806503],[30.8498,103.811783],[30.848881,103.812798],[30.84778,103.813957],[30.846491,103.815239],[30.84572,103.815941],[30.844299,103.817162],[30.84318,103.818062],[30.842051,103.818932],[30.84137,103.819427],[30.840231,103.820213],[30.8391,103.820953],[30.8354,103.823181],[30.83396,103.824097],[30.833031,103.824722],[30.832359,103.825211],[30.83148,103.825867],[30.83041,103.826736],[30.82938,103.827629],[30.82819,103.828728],[30.8272,103.829712],[30.82618,103.830788],[30.82559,103.831444],[30.824631,103.832573],[30.82229,103.835541],[30.821581,103.836411],[30.82119,103.836853],[30.820379,103.83773],[30.819759,103.838371],[30.81912,103.838989],[30.818251,103.839783],[30.817591,103.840332],[30.81691,103.840874],[30.816,103.841553],[30.81461,103.842506],[30.810249,103.84536],[30.809401,103.845963],[30.808769,103.84642],[30.80835,103.846733],[30.807949,103.847061],[30.807341,103.84758],[30.806721,103.848129],[30.80587,103.848938],[30.80525,103.849564],[30.804661,103.850189],[30.8039,103.851044],[30.80353,103.851471],[30.80266,103.852547],[30.802,103.853439],[30.80117,103.854637],[30.80069,103.8554],[30.79991,103.856697],[30.7966,103.862488],[30.795549,103.864281],[30.79442,103.866318],[30.79245,103.869789],[30.790501,103.873192],[30.78861,103.876472],[30.78834,103.876984],[30.78797,103.877747],[30.7875,103.878838],[30.787291,103.879433],[30.78709,103.88002],[30.786909,103.880638],[30.786751,103.881271],[30.78661,103.881897],[30.786501,103.882553],[30.786409,103.883186],[30.786341,103.883827],[30.786289,103.88446],[30.786261,103.885094],[30.786261,103.886047],[30.78632,103.887306],[30.78647,103.889542],[30.78635,103.891296],[30.78624,103.892967],[30.785839,103.895668],[30.78549,103.897171],[30.78499,103.898582],[30.784599,103.899689],[30.78377,103.901466],[30.783159,103.902473],[30.78298,103.902771],[30.782511,103.903587],[30.78203,103.904282],[30.78134,103.905197],[30.77743,103.910294],[30.773211,103.915771],[30.772129,103.91713],[30.77091,103.91864],[30.769369,103.920647],[30.7686,103.921638],[30.766121,103.924881],[30.7631,103.929024],[30.76078,103.93219],[30.75775,103.936234],[30.757311,103.936577],[30.7565,103.93766],[30.75602,103.938057],[30.755301,103.938583],[30.754761,103.938843],[30.7542,103.939056],[30.75358,103.939201],[30.752729,103.939293],[30.7521,103.939232],[30.75139,103.939072],[30.750839,103.938889],[30.75004,103.938591],[30.748631,103.937691],[30.746429,103.936737],[30.74535,103.936371],[30.74428,103.93605],[30.7437,103.935883],[30.739031,103.934921],[30.736521,103.934418],[30.736271,103.934357],[30.734831,103.934059],[30.73411,103.933907],[30.73082,103.933296],[30.72954,103.933067],[30.729179,103.933006],[30.725719,103.93264],[30.725229,103.932571],[30.72271,103.932442],[30.719419,103.932381],[30.715771,103.932343],[30.712839,103.932167],[30.71044,103.931961],[30.70717,103.931511],[30.702971,103.930763],[30.70075,103.930359],[30.698931,103.930107],[30.6966,103.929947],[30.693951,103.929916],[30.69375,103.929916],[30.69273,103.929947],[30.69128,103.930038],[30.6903,103.930122],[30.685061,103.930573],[30.682341,103.930847],[30.67981,103.931221],[30.676941,103.931831],[30.674351,103.932541],[30.67045,103.93396],[30.66506,103.935852],[30.663919,103.936203],[30.66292,103.936432],[30.66181,103.936653],[30.660431,103.936867],[30.65892,103.936996],[30.65756,103.937042],[30.65484,103.937103],[30.650579,103.93708],[30.648371,103.93718],[30.64661,103.937378],[30.64509,103.937637],[30.64365,103.938019],[30.64196,103.938469],[30.63983,103.939247],[30.63492,103.941093],[30.633631,103.941528],[30.63224,103.941971],[30.630779,103.94239],[30.629311,103.942734],[30.627041,103.943169],[30.62483,103.943512],[30.619511,103.944397],[30.61833,103.944679],[30.616791,103.945107],[30.615311,103.945686],[30.61389,103.946373],[30.61227,103.947456],[30.61113,103.94841],[30.60972,103.949783],[30.60885,103.950798],[30.607639,103.952438],[30.606489,103.954514],[30.605459,103.956711],[30.60393,103.960114],[30.601891,103.964783],[30.60046,103.96785],[30.599171,103.970444],[30.597589,103.973083],[30.59609,103.975372],[30.59486,103.977203],[30.592131,103.981133],[30.591129,103.982712],[30.589991,103.985039],[30.589319,103.986877],[30.58885,103.988724],[30.58856,103.990677],[30.588461,103.992706],[30.58849,103.994728],[30.58868,104.002876],[30.58857,104.005081],[30.588181,104.007187],[30.58745,104.009308],[30.5863,104.011383],[30.584311,104.014137],[30.58374,104.014938],[30.58132,104.018349],[30.5807,104.019234],[30.579081,104.022034],[30.57872,104.02272],[30.578449,104.023232],[30.57793,104.023956],[30.577459,104.024513],[30.57682,104.024979],[30.576241,104.025208],[30.57585,104.025307],[30.575529,104.025391],[30.57468,104.025391],[30.57391,104.025269],[30.57362,104.025162],[30.571671,104.024368],[30.570181,104.023758],[30.56801,104.022743],[30.56468,104.020882],[30.554741,104.014908],[30.55094,104.012497],[30.548651,104.010696],[30.54603,104.008163],[30.54306,104.004494],[30.54019,103.999863],[30.538441,103.997513],[30.536329,103.995216],[30.528799,103.987923],[30.525129,103.984543],[30.522129,103.982224],[30.51981,103.980797],[30.51687,103.979141],[30.51384,103.977158],[30.51082,103.974457],[30.50326,103.967072],[30.50028,103.964706],[30.497601,103.96299],[30.48823,103.958504],[30.482201,103.955002],[30.476259,103.950844],[30.47337,103.948822],[30.470671,103.947304],[30.46776,103.94593],[30.45928,103.942421],[30.455521,103.940567],[30.452351,103.938187],[30.450029,103.935883],[30.44676,103.931976],[30.443501,103.928284],[30.43807,103.92318],[30.42778,103.913887],[30.424299,103.910683],[30.42137,103.908173],[30.418739,103.906342],[30.415751,103.904572],[30.409611,103.900833],[30.408791,103.900307],[30.40811,103.899879],[30.40642,103.89872],[30.406269,103.898613],[30.406139,103.898514],[30.405199,103.897797],[30.404831,103.897507],[30.404539,103.897301],[30.4027,103.895752],[30.402639,103.895714],[30.400829,103.894089],[30.395901,103.889481],[30.38553,103.878517],[30.38382,103.876129],[30.382191,103.873322],[30.381121,103.870064],[30.380699,103.86879],[30.38039,103.867699],[30.379641,103.864769],[30.378071,103.858124],[30.37772,103.856689],[30.376881,103.85466],[30.375919,103.852417],[30.374901,103.850273],[30.3745,103.849602],[30.373409,103.848267],[30.37274,103.847504],[30.371759,103.846527],[30.37007,103.845253],[30.37002,103.845222],[30.36821,103.844131],[30.36706,103.843628],[30.364889,103.842949],[30.362579,103.842438],[30.359209,103.841759],[30.35545,103.841057],[30.351959,103.840683],[30.349331,103.83992],[30.34514,103.838531],[30.342319,103.83725],[30.339621,103.836571],[30.336281,103.835983],[30.332951,103.835632],[30.32992,103.835281],[30.32859,103.835083],[30.3276,103.834839],[30.32691,103.834572],[30.326309,103.834229],[30.325581,103.833733],[30.32482,103.833267],[30.32445,103.833092],[30.324329,103.833061],[30.323629,103.832787],[30.32313,103.832687],[30.322559,103.832611],[30.32193,103.832611],[30.3211,103.83271],[30.32037,103.832901],[30.319811,103.833107],[30.319309,103.833397],[30.318569,103.8339],[30.318041,103.834328],[30.317631,103.834663],[30.31662,103.835457],[30.31559,103.835968],[30.3148,103.836304],[30.31304,103.83699],[30.311819,103.837433],[30.305599,103.839798],[30.303049,103.840767],[30.302441,103.841011],[30.301571,103.841316],[30.300711,103.841667],[30.300541,103.841743],[30.29854,103.842484],[30.29718,103.842903],[30.29463,103.843719],[30.293159,103.843903],[30.29126,103.844063],[30.28908,103.844002],[30.28517,103.843407],[30.279461,103.842461],[30.274309,103.84182],[30.272249,103.841682],[30.26882,103.841507],[30.263081,103.841637],[30.260481,103.841827],[30.25771,103.842117],[30.254551,103.842537],[30.252159,103.842957],[30.244909,103.844063],[30.238979,103.844971],[30.2346,103.845627],[30.228121,103.846626],[30.223459,103.847366],[30.21862,103.847878],[30.21557,103.848358],[30.21253,103.848862],[30.21196,103.848938],[30.21122,103.849037],[30.211149,103.849052],[30.21056,103.849129],[30.20863,103.849457],[30.206671,103.849739],[30.206619,103.849747],[30.20463,103.850037],[30.20118,103.850723],[30.19952,103.850739],[30.19763,103.850632],[30.195299,103.850273],[30.193661,103.849907],[30.192101,103.849403],[30.18655,103.847427],[30.18231,103.845909],[30.17621,103.843719],[30.170601,103.841721],[30.166719,103.840317],[30.161591,103.838501],[30.156549,103.83667],[30.15312,103.835442],[30.149229,103.83403],[30.14525,103.832611],[30.142139,103.831398],[30.139771,103.83033],[30.134809,103.827782],[30.13142,103.825974],[30.12595,103.82296],[30.12237,103.821037],[30.12002,103.819763],[30.11664,103.817947],[30.11326,103.816017],[30.111601,103.815163],[30.10816,103.813248],[30.1056,103.811852],[30.102711,103.810066],[30.099331,103.808411],[30.095301,103.806702],[30.09252,103.805687],[30.086599,103.80368],[30.08601,103.803482],[30.085569,103.803329],[30.08502,103.803139],[30.08182,103.80204],[30.081141,103.801811],[30.079639,103.8013],[30.07716,103.800453],[30.07605,103.800056],[30.074249,103.799438],[30.07411,103.799393],[30.07151,103.798538],[30.06843,103.797859],[30.06653,103.797302],[30.06459,103.796806],[30.062309,103.796303],[30.055731,103.795067],[30.050871,103.794098],[30.04826,103.793358],[30.046261,103.792587],[30.0441,103.791458],[30.042601,103.790527],[30.036551,103.786591],[30.03101,103.782967],[30.029051,103.781616],[30.024891,103.778503],[30.021879,103.775917],[30.0187,103.77298],[30.01498,103.769363],[30.013029,103.767441],[30.011021,103.765747],[30.009581,103.764793],[30.00824,103.764023],[30.00703,103.763443],[30.00528,103.762733],[30.004009,103.762444],[30.0023,103.762123],[30.00091,103.762047],[29.99885,103.762077],[29.996031,103.762238],[29.98945,103.762657],[29.98629,103.762863],[29.985081,103.762993],[29.983101,103.763489],[29.98243,103.763687],[29.9806,103.764481],[29.977921,103.765984],[29.97703,103.766487],[29.97328,103.768593],[29.97217,103.769096],[29.969801,103.769981],[29.969139,103.770142],[29.968201,103.770332],[29.965611,103.770554],[29.96287,103.770348],[29.96159,103.770027],[29.9582,103.769203],[29.956301,103.768723],[29.95241,103.767761],[29.94582,103.766167],[29.941891,103.764954],[29.938259,103.763428],[29.93232,103.760307],[29.9265,103.757187],[29.92123,103.754211],[29.9186,103.752403],[29.916189,103.75061],[29.9119,103.747131],[29.90592,103.742203],[29.90304,103.740356],[29.902201,103.739906],[29.90093,103.739372],[29.89822,103.738579],[29.89192,103.737061],[29.888399,103.735947],[29.886129,103.735092],[29.884081,103.734154],[29.88076,103.732521],[29.877239,103.730759],[29.87343,103.729156],[29.872789,103.728912],[29.86729,103.727081],[29.861521,103.725227],[29.8587,103.724289],[29.856159,103.723618],[29.854139,103.723183],[29.847811,103.72216],[29.84544,103.721687],[29.843941,103.72123],[29.842291,103.720627],[29.841141,103.720047],[29.839939,103.719368],[29.83886,103.718597],[29.834391,103.714973],[29.82803,103.709839],[29.824579,103.706779],[29.82353,103.705704],[29.818701,103.700737],[29.816549,103.699013],[29.81579,103.698471],[29.81492,103.69799],[29.81385,103.697479],[29.81284,103.697067],[29.81114,103.696518],[29.804569,103.694901],[29.801861,103.694099],[29.800591,103.693657],[29.79631,103.691856],[29.79286,103.690376],[29.78804,103.688293],[29.78281,103.686028],[29.7794,103.684883],[29.77482,103.683647],[29.771151,103.68325],[29.76623,103.682564],[29.7612,103.681862],[29.75733,103.680702],[29.752661,103.678726],[29.741501,103.673637],[29.735689,103.670433],[29.730261,103.667122],[29.728109,103.665894],[29.725889,103.665009],[29.723049,103.664223],[29.719179,103.663467],[29.71279,103.661957],[29.70635,103.660027],[29.70294,103.659363],[29.70014,103.659142],[29.68815,103.659363],[29.68462,103.659538],[29.68202,103.660202],[29.67861,103.661789],[29.669941,103.667168],[29.667179,103.669067],[29.66548,103.670013],[29.66226,103.671219],[29.65731,103.672684],[29.654421,103.673882],[29.651899,103.675377],[29.64912,103.677238],[29.64385,103.680489],[29.639219,103.682854],[29.63732,103.683731],[29.63269,103.685913],[29.629339,103.687523],[29.626249,103.68943],[29.62406,103.690987],[29.618151,103.695602],[29.61622,103.696747],[29.61463,103.697456],[29.61256,103.69812],[29.611,103.698418],[29.60833,103.698517],[29.59409,103.697853],[29.59317,103.697777],[29.59227,103.697708],[29.590639,103.697578],[29.589661,103.697533],[29.588791,103.697472],[29.588249,103.697449],[29.57856,103.697304],[29.5669,103.703148],[29.545259,103.705719],[29.533911,103.709663],[29.5194,103.710701],[29.50877,103.719643],[29.49684,103.726669],[29.47427,103.734573],[29.463039,103.741623],[29.456329,103.746758],[29.44392,103.752083],[29.435089,103.758949],[29.42598,103.763763],[29.41267,103.773537],[29.407921,103.7761],[29.388491,103.777473],[29.381571,103.779373],[29.375561,103.784538],[29.367929,103.790733],[29.359091,103.80069],[29.352209,103.809097],[29.335911,103.826767],[29.318411,103.840843],[29.305571,103.847687],[29.294029,103.850273],[29.289061,103.853722],[29.285049,103.858421],[29.28236,103.861847],[29.278641,103.865082],[29.27508,103.866959],[29.27075,103.867813],[29.266239,103.869019],[29.262159,103.871269],[29.25914,103.875252],[29.256281,103.880081],[29.254311,103.88562],[29.25462,103.892014],[29.25462,103.896103],[29.25388,103.89949],[29.25211,103.902519],[29.24992,103.903862],[29.24637,103.904198],[29.239189,103.902817],[29.2363,103.903],[29.2334,103.904572],[29.22904,103.90992],[29.22484,103.915077],[29.22064,103.922813],[29.217951,103.927429],[29.21423,103.930832],[29.210199,103.933403],[29.20557,103.936142],[29.201851,103.936989],[29.19854,103.937851],[29.19643,103.938721],[29.192829,103.940613],[29.18956,103.942139],[29.18597,103.942307],[29.18281,103.943001],[29.178619,103.944717],[29.171591,103.945229],[29.16573,103.945923],[29.161699,103.947372],[29.160009,103.947983],[29.158831,103.948608],[29.15626,103.949867],[29.152901,103.951424],[29.149111,103.953827],[29.1474,103.955566],[29.146151,103.957626],[29.145109,103.960457],[29.142111,103.970154],[29.14106,103.973381],[29.139879,103.975868],[29.13899,103.976921],[29.136841,103.97908],[29.134291,103.981583],[29.13253,103.984039],[29.13093,103.986557],[29.12966,103.987846],[29.12866,103.988503],[29.127199,103.98938],[29.125521,103.990341],[29.124041,103.991127],[29.119749,103.993317],[29.11607,103.995277],[29.11408,103.996292],[29.112249,103.997368],[29.11076,103.998611],[29.10943,104.000572],[29.108459,104.002899],[29.107861,104.005363],[29.107149,104.009163],[29.106421,104.012009],[29.10582,104.014008],[29.104271,104.017776],[29.103621,104.019836],[29.10293,104.023308],[29.102461,104.025742],[29.10177,104.027687],[29.100349,104.030693],[29.099409,104.032883],[29.098749,104.034416],[29.09796,104.036942],[29.097639,104.038231],[29.097269,104.039864],[29.09687,104.041733],[29.096081,104.043922],[29.09543,104.044937],[29.094481,104.04641],[29.093491,104.047684],[29.092251,104.049271],[29.09111,104.051208],[29.090521,104.053123],[29.09025,104.054497],[29.090191,104.055412],[29.09095,104.06636],[29.08976,104.070282],[29.086451,104.075089],[29.084789,104.082336],[29.08194,104.09523],[29.08194,104.100754],[29.083441,104.1138],[29.083441,104.123207],[29.08194,104.130234],[29.081051,104.137589],[29.078979,104.141144],[29.074051,104.144547],[29.07147,104.146637],[29.069349,104.150803],[29.0674,104.15818],[29.06502,104.162086],[29.06082,104.166382],[29.057659,104.171707],[29.053459,104.177032],[29.050289,104.182549],[29.04789,104.189774],[29.044889,104.195938],[29.042179,104.201973],[29.03993,104.212639],[29.03933,104.220207],[29.03903,104.228256],[29.03784,104.231812],[29.03484,104.236618],[29.028379,104.253113],[29.026449,104.257019],[29.021049,104.261993],[29.01655,104.268517],[29.01055,104.274857],[29.00544,104.280022],[29.00108,104.287064],[28.99402,104.295143],[28.98967,104.302856],[28.98292,104.309708],[28.97978,104.313469],[28.970779,104.318787],[28.95965,104.328072],[28.95751,104.330688],[28.9533,104.345627],[28.949699,104.352333],[28.94536,104.363281],[28.933331,104.374786],[28.93166,104.380173],[28.93046,104.396652],[28.928961,104.401611],[28.92506,104.414322],[28.92205,104.426697],[28.92115,104.433708],[28.91231,104.449966],[28.905689,104.457191],[28.902519,104.467171],[28.89502,104.482246],[28.8881,104.49015],[28.88599,104.496696],[28.88163,104.504936],[28.88027,104.513527],[28.873369,104.529999],[28.870211,104.537712],[28.86569,104.545631],[28.864491,104.554916],[28.860729,104.567627],[28.859831,104.576729],[28.857719,104.585152],[28.85787,104.598732],[28.857719,104.609558],[28.859831,104.621941],[28.861771,104.631523],[28.86043,104.638496],[28.857889,104.644302],[28.85685,104.64566],[28.856409,104.645889],[28.855829,104.645912],[28.85532,104.645851],[28.8547,104.645592],[28.854259,104.645401],[28.85355,104.644783],[28.85206,104.6436],[28.85038,104.642418],[28.84877,104.641296],[28.847361,104.64032],[28.84576,104.639198],[28.84403,104.637993],[28.84247,104.636917],[28.84119,104.636147],[28.839411,104.63517],[28.838369,104.634666],[28.83795,104.634483],[28.83754,104.634277],[28.83667,104.633926],[28.836451,104.633842],[28.83535,104.6334],[28.83428,104.63295],[28.833019,104.632332],[28.832069,104.631706],[28.83111,104.630867],[28.830311,104.629936],[28.830179,104.629784],[28.829399,104.628593],[28.82859,104.627098],[28.82773,104.625526],[28.82724,104.624779],[28.826429,104.623734],[28.82542,104.622673],[28.823549,104.621033],[28.82159,104.619324],[28.820299,104.618202],[28.81879,104.61689],[28.8176,104.615837],[28.816589,104.61496],[28.81525,104.6138],[28.81423,104.612862],[28.81304,104.611588],[28.811781,104.610023],[28.81085,104.608841],[28.809839,104.607529],[28.80899,104.606438],[28.80829,104.605591],[28.80397,104.599716],[28.79163,104.60006],[28.77869,104.590103],[28.768459,104.583923],[28.764999,104.582039],[28.75341,104.570534],[28.7498,104.564194],[28.741831,104.551826],[28.73023,104.546158],[28.723009,104.535347],[28.71352,104.533112],[28.71097,104.53157],[28.70705,104.521606],[28.703291,104.519379],[28.69832,104.519897],[28.68597,104.524361],[28.68507,104.523331],[28.682211,104.520752],[28.672421,104.509598],[28.66684,104.501183],[28.664129,104.500328],[28.65494,104.501701],[28.651779,104.500839],[28.63928,104.496384],[28.635811,104.493629],[28.62888,104.483849],[28.62285,104.476982],[28.61788,104.467537],[28.608089,104.457916],[28.599489,104.44368],[28.599649,104.435951],[28.59844,104.429077],[28.600401,104.421021],[28.601,104.411232],[28.603109,104.394073],[28.603109,104.384453],[28.59889,104.372437],[28.587891,104.364723],[28.56769,104.354424],[28.563009,104.348747],[28.56241,104.339653],[28.564819,104.332947],[28.564671,104.32798],[28.558189,104.323517],[28.549589,104.320587],[28.543711,104.312363],[28.544621,104.305489],[28.544769,104.295532],[28.53949,104.285919],[28.53919,104.276817],[28.542509,104.26532],[28.551399,104.260002],[28.55744,104.260857],[28.561199,104.257263],[28.563009,104.246437],[28.562111,104.240433],[28.555321,104.22876],[28.55216,104.226868],[28.5511,104.22155],[28.54492,104.213654],[28.54055,104.20919],[28.536169,104.200607],[28.536631,104.192368],[28.532709,104.189102],[28.52652,104.187729],[28.523661,104.184471],[28.51038,104.181381],[28.502541,104.186867],[28.49575,104.186363],[28.49379,104.184471],[28.491529,104.186012],[28.48896,104.190483],[28.484739,104.192879],[28.48217,104.192368],[28.47765,104.190987],[28.472059,104.191681],[28.46904,104.193222],[28.46467,104.192879],[28.45742,104.191849],[28.45561,104.192711],[28.45335,104.195969],[28.44837,104.196136],[28.446711,104.195107],[28.45335,104.187393],[28.45471,104.190132],[28.45335,104.192543],[28.451691,104.194427],[28.449881,104.194427],[28.44656,104.192711],[28.445049,104.187393],[28.44293,104.185837],[28.438709,104.184982],[28.436899,104.183441],[28.435989,104.179657],[28.43478,104.178802],[28.43207,104.179657],[28.430401,104.178978],[28.429199,104.177429],[28.427691,104.176743],[28.42573,104.176918],[28.41984,104.175369],[28.39855,104.157013],[28.39492,104.150993],[28.3916,104.147049],[28.38798,104.147217],[28.384649,104.147392],[28.38254,104.149452],[28.37635,104.150139],[28.372419,104.15168],[28.36698,104.152367],[28.35928,104.149803],[28.35656,104.14756],[28.350519,104.14035],[28.34553,104.13829],[28.340851,104.133324],[28.33481,104.132797],[28.328911,104.13623],[28.323021,104.135033],[28.318029,104.135536],[28.31501,104.134506],[28.3067,104.136063],[28.30216,104.138474],[28.298389,104.13726],[28.2943,104.138809],[28.2875,104.144302],[28.27949,104.143784],[28.27541,104.145683],[28.268,104.153397],[28.26059,104.152367],[28.254551,104.144989],[28.24925,104.141899],[28.24729,104.140869],[28.244869,104.137444],[28.228689,104.140869],[28.205839,104.139839],[28.204781,104.134506],[28.201611,104.131599],[28.202209,104.124557],[28.200399,104.118378],[28.19994,104.111],[28.188601,104.103104],[28.184361,104.1007],[28.17906,104.096581],[28.17725,104.092461],[28.17165,104.093658],[28.165291,104.094002],[28.16151,104.092796],[28.15213,104.084389],[28.14592,104.083191],[28.141991,104.082672],[28.13608,104.072548],[28.132151,104.072723],[28.1273,104.073227],[28.1273,104.079758],[28.1273,104.082848],[28.12488,104.083878],[28.119579,104.080788],[28.11731,104.081642],[28.114429,104.086792],[28.11458,104.090569],[28.09354,104.131943],[28.09066,104.134003],[28.08672,104.133141],[28.0846,104.133827],[28.074301,104.141899],[28.06855,104.141899],[28.063551,104.144989],[28.05961,104.144653],[28.053101,104.145844],[28.046881,104.143784],[28.04492,104.142593],[28.040979,104.132111],[28.03643,104.125237],[28.03734,104.121811],[28.03931,104.119408],[28.04492,104.104134],[28.04295,104.097778],[28.039459,104.089882],[28.036131,104.079582],[28.027639,104.075638],[28.023701,104.076317],[28.01643,104.066193],[28.01552,104.052979],[28.01749,104.047653],[28.02037,104.036842],[28.01128,104.010918],[28.00491,104.006973],[28.00279,104.00251],[27.992331,103.988777],[27.99157,103.974182],[27.97747,103.962509],[27.97505,103.953934],[27.966101,103.948952],[27.96595,103.941223],[27.963221,103.935913],[27.95549,103.935043],[27.94791,103.919937],[27.93684,103.917374],[27.928499,103.916679],[27.916361,103.915131],[27.904831,103.913254],[27.89315,103.909286],[27.89012,103.912041],[27.884649,103.910843],[27.874941,103.906197],[27.86569,103.89917],[27.861441,103.897621],[27.854151,103.889557],[27.85294,103.88784],[27.853701,103.88475],[27.8496,103.876343],[27.846411,103.875481],[27.84565,103.873253],[27.843229,103.872223],[27.840639,103.867073],[27.83503,103.867409],[27.831989,103.864151],[27.828501,103.863121],[27.824551,103.857109],[27.821369,103.855049],[27.817869,103.855217],[27.81332,103.856941],[27.81135,103.859512],[27.80846,103.858139],[27.804661,103.861923],[27.799959,103.863289],[27.797831,103.864838],[27.79814,103.868271],[27.787661,103.878403],[27.7869,103.880966],[27.77627,103.880287],[27.7749,103.883202],[27.7708,103.883202],[27.76852,103.88681],[27.75865,103.886978],[27.7547,103.88475],[27.749531,103.884918],[27.74634,103.887154],[27.74361,103.887321],[27.73844,103.891273],[27.73601,103.89299],[27.73358,103.895218],[27.732059,103.89196],[27.72872,103.892303],[27.725531,103.896927],[27.715651,103.891441],[27.712761,103.89196],[27.70896,103.889214],[27.703951,103.88681],[27.701361,103.887497],[27.698931,103.886467],[27.696199,103.886292],[27.69376,103.884918],[27.689659,103.884064],[27.686621,103.880463],[27.684799,103.879768],[27.682671,103.877876],[27.680389,103.877022],[27.67902,103.875481],[27.67598,103.874786],[27.67066,103.866722],[27.667311,103.865181],[27.66564,103.856598],[27.66412,103.852303],[27.65789,103.848183],[27.652719,103.846123],[27.65028,103.843552],[27.64694,103.843552],[27.64283,103.842857],[27.63949,103.839943],[27.63797,103.837029],[27.631729,103.83239],[27.628229,103.831017],[27.626101,103.827583],[27.623819,103.826393],[27.623671,103.82209],[27.621849,103.820717],[27.62261,103.816772],[27.61956,103.815567],[27.618191,103.811279],[27.61515,103.806824],[27.61059,103.80407],[27.605419,103.801147],[27.59964,103.800461],[27.59507,103.800461],[27.593861,103.801491],[27.592939,103.803207],[27.590811,103.804916],[27.588989,103.808357],[27.587311,103.807671],[27.588989,103.805267],[27.59005,103.80304],[27.59157,103.801826],[27.59157,103.798576],[27.592939,103.798576],[27.5931,103.795998],[27.587009,103.785873],[27.586399,103.783813],[27.58518,103.783813],[27.58518,103.781921],[27.582291,103.777107],[27.580311,103.774544],[27.57818,103.773682],[27.57773,103.771797],[27.57362,103.770416],[27.573931,103.768883],[27.57469,103.768021],[27.57453,103.765099],[27.57453,103.763039],[27.57469,103.761841],[27.57316,103.759781],[27.57073,103.758583],[27.56982,103.756172],[27.566931,103.756172],[27.56312,103.753937],[27.56053,103.754967],[27.55475,103.754112],[27.54973,103.752571],[27.54668,103.752739],[27.53923,103.748962],[27.53344,103.747589],[27.530701,103.746902],[27.52355,103.739182],[27.51639,103.736778],[27.51137,103.739182],[27.506189,103.740211],[27.50436,103.739349],[27.50071,103.734718],[27.49873,103.730423],[27.495081,103.729393],[27.494619,103.726646],[27.493549,103.726822],[27.491421,103.728203],[27.476191,103.728706],[27.454559,103.719437],[27.44207,103.725273],[27.41617,103.733856],[27.3988,103.720993],[27.38965,103.717033],[27.36128,103.693459],[27.35232,103.692528],[27.351521,103.692436],[27.34355,103.691467],[27.31587,103.685341],[27.29833,103.681534],[27.29615,103.68148],[27.294399,103.681831],[27.28997,103.683388],[27.2887,103.683456],[27.28771,103.683289],[27.269011,103.676178],[27.268061,103.67598],[27.25794,103.676392],[27.25091,103.676598],[27.24836,103.676224],[27.217649,103.667976],[27.210899,103.667221],[27.20487,103.667038],[27.200251,103.666199],[27.196159,103.664726],[27.19311,103.663017],[27.191919,103.662132],[27.182261,103.651466],[27.179991,103.649803],[27.1779,103.648628],[27.175831,103.647827],[27.17329,103.647232],[27.17054,103.647072],[27.167339,103.647293],[27.164,103.647942],[27.15872,103.649628],[27.154169,103.651733],[27.152031,103.652283],[27.147369,103.652802],[27.143101,103.653908],[27.14143,103.653961],[27.14053,103.65387],[27.131121,103.650887],[27.129351,103.650627],[27.127211,103.650993],[27.12598,103.651718],[27.125299,103.65181],[27.124319,103.651947],[27.12398,103.651947],[27.12299,103.651672],[27.12096,103.651001],[27.113211,103.649933],[27.11253,103.649673],[27.110041,103.648109],[27.10898,103.647667],[27.108009,103.647499],[27.104919,103.647614],[27.103239,103.647346],[27.10194,103.646919],[27.09943,103.645592],[27.09831,103.645218],[27.09693,103.645073],[27.095551,103.645157],[27.09359,103.64563],[27.091999,103.646187],[27.088079,103.647491],[27.08704,103.647629],[27.086451,103.647598],[27.08568,103.647453],[27.084551,103.646973],[27.083851,103.6465],[27.083,103.645699],[27.08264,103.645157],[27.082161,103.644569],[27.080271,103.641853],[27.07803,103.639061],[27.07766,103.63871],[27.077499,103.638573],[27.075359,103.636833],[27.07407,103.636208],[27.07329,103.636017],[27.072309,103.636047],[27.071739,103.636208],[27.07119,103.636482],[27.070351,103.637131],[27.0693,103.638069],[27.06863,103.638474],[27.068081,103.638657],[27.066259,103.638893],[27.065479,103.639137],[27.06492,103.639473],[27.064301,103.640038],[27.06389,103.640556],[27.06365,103.640984],[27.06341,103.641617],[27.063271,103.642319],[27.063351,103.645111],[27.06321,103.646027],[27.06299,103.646698],[27.06267,103.647324],[27.06238,103.647667],[27.06175,103.648239],[27.060841,103.64872],[27.06019,103.648888],[27.059589,103.648903],[27.058981,103.648804],[27.05514,103.647217],[27.05409,103.647003],[27.052629,103.647003],[27.051451,103.647293],[27.05052,103.647758],[27.04999,103.648079],[27.047319,103.650131],[27.045959,103.650383],[27.04484,103.650269],[27.043961,103.649933],[27.04318,103.649384],[27.04158,103.647636],[27.040319,103.646759],[27.039061,103.646202],[27.03179,103.644981],[27.0299,103.644348],[27.02809,103.643211],[27.027651,103.64283],[27.026739,103.641541],[27.02565,103.63929],[27.02478,103.638153],[27.023161,103.636528],[27.022461,103.635483],[27.02191,103.634117],[27.0217,103.632423],[27.02203,103.623558],[27.021061,103.613472],[27.02072,103.612587],[27.02059,103.612259],[27.020491,103.612167],[27.020229,103.61161],[27.01918,103.610069],[27.018311,103.6092],[27.01779,103.60881],[27.017229,103.608498],[27.015921,103.607979],[27.01515,103.607826],[27.0135,103.607803],[27.01181,103.608093],[27.011709,103.608093],[27.010019,103.608276],[27.00703,103.607964],[27.005871,103.608063],[27.00322,103.608597],[27.002371,103.60862],[27.00173,103.608582],[27.0007,103.608337],[26.999479,103.607758],[26.99892,103.607384],[26.99749,103.605911],[26.996691,103.604797],[26.99585,103.603188],[26.995411,103.601929],[26.99506,103.599991],[26.994711,103.594978],[26.994341,103.593391],[26.99378,103.592201],[26.990351,103.588181],[26.98736,103.583832],[26.98568,103.582413],[26.984591,103.581718],[26.98411,103.581467],[26.98325,103.581146],[26.98291,103.5811],[26.982059,103.58091],[26.977859,103.581146],[26.976681,103.580917],[26.97571,103.580482],[26.97448,103.579628],[26.97374,103.578789],[26.972731,103.577187],[26.97262,103.577072],[26.96594,103.565643],[26.965549,103.564171],[26.965549,103.561852],[26.96533,103.560837],[26.964781,103.559708],[26.9634,103.55764],[26.96254,103.556923],[26.96184,103.556503],[26.96139,103.556374],[26.951269,103.55677],[26.949631,103.55658],[26.94891,103.556358],[26.94841,103.556068],[26.947809,103.55555],[26.947411,103.555054],[26.94702,103.554291],[26.946119,103.5513],[26.945709,103.550461],[26.94334,103.547234],[26.94191,103.544724],[26.94112,103.543762],[26.94002,103.542824],[26.93877,103.542023],[26.93788,103.541611],[26.937149,103.541367],[26.93611,103.541443],[26.934299,103.541588],[26.933229,103.541473],[26.932819,103.541367],[26.932211,103.541054],[26.93066,103.539978],[26.93,103.539673],[26.92931,103.539543],[26.928841,103.539528],[26.928129,103.539642],[26.926069,103.540443],[26.925381,103.540588],[26.9245,103.540611],[26.923599,103.540489],[26.92186,103.539993],[26.92103,103.539917],[26.92061,103.539963],[26.919809,103.540237],[26.919241,103.540558],[26.9184,103.541283],[26.91699,103.542778],[26.915291,103.544022],[26.914021,103.544777],[26.91256,103.545868],[26.91078,103.547691],[26.907909,103.551788],[26.90708,103.552597],[26.9065,103.552979],[26.90564,103.553337],[26.904961,103.553467],[26.903021,103.553612],[26.90229,103.55378],[26.901381,103.554176],[26.90003,103.554817],[26.899111,103.555107],[26.898161,103.555237],[26.89669,103.555199],[26.89435,103.554764],[26.89176,103.553963],[26.89102,103.553658],[26.890181,103.553383],[26.888451,103.552727],[26.888281,103.552612],[26.882441,103.549599],[26.8783,103.547081],[26.87499,103.545753],[26.873461,103.545357],[26.870871,103.544884],[26.86898,103.544853],[26.866899,103.54525],[26.86474,103.545937],[26.863489,103.546127],[26.86207,103.546089],[26.86063,103.545738],[26.85984,103.545372],[26.85869,103.544601],[26.85038,103.53727],[26.84799,103.535637],[26.846399,103.534782],[26.84396,103.533813],[26.83536,103.531258],[26.8347,103.530968],[26.83407,103.530586],[26.83326,103.530037],[26.832041,103.528839],[26.83091,103.527328],[26.83005,103.525391],[26.82686,103.516579],[26.82457,103.512283],[26.821711,103.508636],[26.820379,103.507294],[26.81715,103.504631],[26.814951,103.502937],[26.812519,103.500366],[26.810841,103.498398],[26.809139,103.496788],[26.80666,103.495071],[26.80418,103.493851],[26.801371,103.493073],[26.79701,103.492371],[26.795879,103.492073],[26.79248,103.490677],[26.79015,103.489326],[26.78669,103.48716],[26.783381,103.485764],[26.78071,103.485107],[26.77058,103.482986],[26.766041,103.481598],[26.76531,103.481339],[26.76446,103.480957],[26.763821,103.480339],[26.76302,103.479523],[26.762051,103.478531],[26.761669,103.478287],[26.76128,103.478104],[26.76041,103.477943],[26.759781,103.477966],[26.759159,103.478119],[26.75857,103.478416],[26.757839,103.478989],[26.75737,103.479553],[26.75712,103.479958],[26.75683,103.480637],[26.756651,103.481377],[26.75659,103.482094],[26.756491,103.483223],[26.75629,103.483994],[26.756069,103.484467],[26.755079,103.486023],[26.753731,103.487671],[26.751841,103.489517],[26.75123,103.489983],[26.750151,103.490578],[26.74922,103.490883],[26.74822,103.491028],[26.747219,103.490982],[26.746269,103.490784],[26.744961,103.490211],[26.743071,103.489067],[26.742649,103.488876],[26.74197,103.488708],[26.74106,103.48864],[26.737221,103.488533],[26.737341,103.487473],[26.736679,103.486862],[26.736601,103.486687],[26.735531,103.485252],[26.734989,103.484703],[26.73424,103.484253],[26.732981,103.483849],[26.732,103.483582],[26.731449,103.483307],[26.7311,103.483078],[26.730499,103.482452],[26.730009,103.481682],[26.729321,103.480247],[26.728939,103.479683],[26.728479,103.479187],[26.728121,103.478951],[26.726521,103.478203],[26.72613,103.477951],[26.72559,103.477501],[26.725121,103.476929],[26.723829,103.474678],[26.72327,103.474121],[26.72208,103.473419],[26.721121,103.472977],[26.72057,103.472603],[26.71909,103.471123],[26.718109,103.470413],[26.716681,103.469528],[26.715919,103.468903],[26.71526,103.468147],[26.710609,103.461243],[26.708389,103.458847],[26.70776,103.457916],[26.70702,103.456749],[26.70652,103.456177],[26.705839,103.455643],[26.704889,103.455193],[26.70277,103.45462],[26.701481,103.454048],[26.691151,103.446541],[26.68638,103.443703],[26.685579,103.443001],[26.68322,103.440132],[26.67824,103.435547],[26.677401,103.43454],[26.67481,103.430267],[26.674141,103.429466],[26.67314,103.428673],[26.670521,103.426804],[26.669189,103.425629],[26.6684,103.424561],[26.668381,103.424461],[26.666929,103.423126],[26.666401,103.422836],[26.66445,103.420998],[26.663811,103.420197],[26.663759,103.41996],[26.66337,103.419403],[26.660549,103.416901],[26.65888,103.414871],[26.65806,103.414238],[26.654551,103.412773],[26.65377,103.41227],[26.65312,103.411682],[26.65242,103.410744],[26.650511,103.407066],[26.65012,103.406532],[26.64963,103.406036],[26.64196,103.400917],[26.638769,103.399353],[26.636061,103.398041],[26.634979,103.397331],[26.63376,103.396317],[26.63225,103.394592],[26.627741,103.389038],[26.62705,103.387947],[26.624969,103.382874],[26.62381,103.379868],[26.623381,103.379211],[26.622931,103.37886],[26.622601,103.378677],[26.62208,103.37851],[26.62118,103.378342],[26.620661,103.378143],[26.620199,103.3778],[26.618971,103.376579],[26.61879,103.376266],[26.6173,103.374977],[26.616819,103.374672],[26.61614,103.374443],[26.615271,103.374283],[26.614929,103.374153],[26.614441,103.373901],[26.613911,103.373398],[26.613041,103.372147],[26.612579,103.37178],[26.61199,103.371429],[26.610559,103.37085],[26.609949,103.370407],[26.60861,103.368393],[26.608141,103.367996],[26.60759,103.36776],[26.607281,103.367691],[26.60648,103.367706],[26.604321,103.368393],[26.603701,103.368401],[26.60276,103.368134],[26.602051,103.367638],[26.600719,103.3666],[26.600389,103.366402],[26.599649,103.366127],[26.594931,103.365623],[26.59449,103.365494],[26.59387,103.365181],[26.59334,103.364754],[26.593019,103.364357],[26.59199,103.363037],[26.58865,103.358833],[26.588079,103.358269],[26.587099,103.357651],[26.586571,103.357437],[26.585621,103.357277],[26.584681,103.357353],[26.58441,103.357368],[26.58337,103.357529],[26.582121,103.357491],[26.58202,103.35746],[26.57988,103.35688],[26.57847,103.356453],[26.576639,103.356483],[26.57616,103.356628],[26.57501,103.357262],[26.573641,103.358566],[26.572889,103.360184],[26.57221,103.361847],[26.57144,103.362839],[26.570829,103.363373],[26.570009,103.363831],[26.56896,103.36412],[26.56839,103.364113],[26.56765,103.364037],[26.56732,103.363983],[26.56605,103.36335],[26.565611,103.363037],[26.561211,103.358841],[26.56068,103.358238],[26.55739,103.352203],[26.55625,103.350777],[26.555281,103.349998],[26.551029,103.347748],[26.54763,103.345238],[26.543949,103.342262],[26.54328,103.341537],[26.54122,103.338219],[26.5352,103.32708],[26.5343,103.326233],[26.53418,103.326141],[26.5306,103.324722],[26.53013,103.324417],[26.52984,103.324158],[26.529591,103.323853],[26.52923,103.323128],[26.529131,103.322723],[26.529091,103.321892],[26.52928,103.32029],[26.529249,103.319679],[26.529091,103.319107],[26.52883,103.318604],[26.5261,103.315666],[26.5256,103.315247],[26.52487,103.314781],[26.52132,103.313271],[26.520399,103.313087],[26.51967,103.313087],[26.513321,103.313911],[26.512739,103.313904],[26.51181,103.31369],[26.511129,103.313377],[26.51038,103.312759],[26.5098,103.312019],[26.50769,103.307098],[26.506969,103.306129],[26.5065,103.305687],[26.505831,103.305313],[26.504841,103.305023],[26.499769,103.305023],[26.49926,103.304916],[26.49859,103.304657],[26.49827,103.304459],[26.49769,103.303886],[26.496719,103.302559],[26.49597,103.301826],[26.49544,103.301514],[26.494869,103.301292],[26.494061,103.301193],[26.49346,103.301247],[26.49209,103.301643],[26.487391,103.30336],[26.484831,103.303802],[26.484209,103.303802],[26.483999,103.303772],[26.482771,103.303909],[26.481871,103.304153],[26.480391,103.304916],[26.47942,103.305557],[26.4783,103.306091],[26.47756,103.306236],[26.477131,103.306213],[26.476629,103.306061],[26.476021,103.305687],[26.474951,103.304581],[26.473909,103.303993],[26.47316,103.30378],[26.472469,103.303741],[26.471979,103.303833],[26.47183,103.303886],[26.47172,103.304001],[26.471331,103.304131],[26.470421,103.304176],[26.46986,103.304047],[26.46932,103.303772],[26.468941,103.303452],[26.468309,103.302727],[26.466181,103.299278],[26.46574,103.298576],[26.46533,103.29808],[26.46483,103.297737],[26.464491,103.297577],[26.463921,103.297493],[26.46352,103.297531],[26.462311,103.297974],[26.460239,103.298714],[26.459629,103.298843],[26.459009,103.298889],[26.45858,103.298851],[26.457951,103.298683],[26.456949,103.298157],[26.456591,103.297897],[26.456091,103.297447],[26.455721,103.296959],[26.45507,103.295624],[26.453449,103.290291],[26.4531,103.289574],[26.45273,103.28907],[26.452141,103.288483],[26.447451,103.285461],[26.447041,103.285057],[26.44672,103.284607],[26.44651,103.284088],[26.44643,103.283531],[26.44644,103.282013],[26.44626,103.281258],[26.44591,103.280571],[26.442511,103.276314],[26.44105,103.274773],[26.42713,103.267792],[26.42532,103.266891],[26.424749,103.266602],[26.424561,103.266487],[26.393221,103.250977],[26.391689,103.250366],[26.391001,103.250252],[26.390511,103.250252],[26.38979,103.250359],[26.389311,103.250511],[26.388599,103.250839],[26.38796,103.251289],[26.387421,103.251831],[26.38199,103.258743],[26.380569,103.260162],[26.3787,103.261597],[26.37796,103.262077],[26.376129,103.262993],[26.374269,103.263718],[26.37236,103.264168],[26.36668,103.265137],[26.36566,103.26519],[26.36433,103.265091],[26.36381,103.264969],[26.36306,103.264641],[26.36236,103.264252],[26.359619,103.262039],[26.358789,103.261551],[26.35813,103.261337],[26.35747,103.261276],[26.355379,103.261307],[26.354601,103.261162],[26.34967,103.258942],[26.348619,103.25872],[26.34795,103.258759],[26.34745,103.258904],[26.34697,103.259163],[26.346371,103.259651],[26.34589,103.260277],[26.34553,103.261009],[26.34346,103.267906],[26.3433,103.269096],[26.343361,103.269836],[26.34374,103.271461],[26.3438,103.272087],[26.34333,103.27475],[26.34334,103.27597],[26.343531,103.277008],[26.34387,103.278038],[26.34478,103.280586],[26.344999,103.281326],[26.34659,103.285301],[26.346701,103.285789],[26.346741,103.28656],[26.346519,103.288887],[26.346769,103.292091],[26.34671,103.29287],[26.34654,103.29332],[26.344839,103.296158],[26.344681,103.296356],[26.34429,103.296669],[26.343599,103.296982],[26.34197,103.297363],[26.34129,103.297623],[26.3395,103.298767],[26.338619,103.299133],[26.334459,103.300262],[26.333811,103.300591],[26.333441,103.30088],[26.332121,103.302429],[26.328951,103.30632],[26.328211,103.307053],[26.327579,103.307518],[26.32666,103.307922],[26.32531,103.308357],[26.32243,103.309929],[26.32165,103.310471],[26.31884,103.314163],[26.31797,103.315041],[26.31698,103.315773],[26.315729,103.316521],[26.315001,103.317123],[26.31403,103.318253],[26.312361,103.320862],[26.31218,103.321312],[26.311239,103.325974],[26.31101,103.326736],[26.309771,103.329491],[26.309549,103.330276],[26.30946,103.330818],[26.30946,103.332451],[26.309401,103.332977],[26.309179,103.33374],[26.30858,103.334938],[26.3076,103.336472],[26.30689,103.338226],[26.30661,103.339333],[26.30633,103.340973],[26.30619,103.341461],[26.305849,103.342163],[26.305531,103.342537],[26.30406,103.343918],[26.30307,103.344681],[26.30007,103.347366],[26.298969,103.348038],[26.29743,103.348663],[26.294941,103.349159],[26.294559,103.349297],[26.29011,103.352043],[26.28854,103.353416],[26.287861,103.354118],[26.287491,103.354378],[26.286869,103.354637],[26.28377,103.355232],[26.283331,103.355377],[26.28273,103.355713],[26.280279,103.358047],[26.279699,103.358467],[26.277109,103.359993],[26.2764,103.360291],[26.27462,103.360687],[26.273331,103.36097],[26.27282,103.361153],[26.27235,103.361397],[26.27169,103.361893],[26.26902,103.364273],[26.26837,103.36467],[26.2679,103.364868],[26.267389,103.36499],[26.266621,103.36499],[26.26524,103.364647],[26.26186,103.363678],[26.261129,103.363548],[26.260429,103.363541],[26.26001,103.363602],[26.25942,103.363823],[26.257891,103.364769],[26.257271,103.365021],[26.256359,103.365173],[26.253691,103.365349],[26.25301,103.365479],[26.24645,103.367821],[26.244711,103.368767],[26.24288,103.370148],[26.238939,103.373947],[26.2377,103.375526],[26.236839,103.377007],[26.235729,103.379669],[26.235359,103.38105],[26.234341,103.389236],[26.23395,103.390549],[26.23344,103.39151],[26.233101,103.391953],[26.23229,103.392693],[26.23144,103.393372],[26.230499,103.394333],[26.229891,103.395218],[26.22916,103.396698],[26.22888,103.397476],[26.228121,103.400261],[26.227501,103.40213],[26.227301,103.402931],[26.227091,103.403427],[26.226641,103.404121],[26.22611,103.404709],[26.22547,103.405182],[26.224661,103.405533],[26.221069,103.406113],[26.219521,103.406143],[26.218451,103.40596],[26.21789,103.405693],[26.215919,103.404037],[26.21559,103.403633],[26.21291,103.401031],[26.21072,103.399094],[26.207279,103.39798],[26.203951,103.398811],[26.2036,103.399063],[26.203199,103.3992],[26.202829,103.399406],[26.20146,103.399971],[26.200609,103.400146],[26.19997,103.400192],[26.19912,103.400063],[26.19795,103.399513],[26.196461,103.398643],[26.195471,103.398148],[26.19492,103.397797],[26.194241,103.397324],[26.194031,103.397247],[26.19183,103.396027],[26.190729,103.39579],[26.189899,103.395866],[26.188931,103.396301],[26.18684,103.397659],[26.1859,103.39827],[26.18556,103.398376],[26.183399,103.398598],[26.18268,103.398857],[26.181829,103.399399],[26.18091,103.400352],[26.178711,103.403313],[26.17831,103.403709],[26.177891,103.403923],[26.177549,103.403999],[26.177019,103.403893],[26.176781,103.403763],[26.176559,103.403557],[26.176319,103.403137],[26.17622,103.402802],[26.17618,103.402283],[26.176229,103.401787],[26.176371,103.4011],[26.17642,103.400589],[26.17622,103.398972],[26.17621,103.397568],[26.17647,103.39576],[26.176189,103.393623],[26.175739,103.391579],[26.175739,103.391418],[26.17531,103.390739],[26.174931,103.390457],[26.174641,103.390373],[26.174351,103.390373],[26.17407,103.390442],[26.173679,103.390701],[26.173361,103.391098],[26.173,103.391907],[26.172779,103.392677],[26.172409,103.393379],[26.17231,103.393494],[26.17207,103.393646],[26.171659,103.393723],[26.168779,103.393097],[26.168171,103.392822],[26.16744,103.392273],[26.167351,103.392174],[26.166031,103.391159],[26.16197,103.38813],[26.160919,103.387016],[26.160311,103.386307],[26.15793,103.384117],[26.157539,103.383659],[26.155451,103.380707],[26.154449,103.379318],[26.153799,103.377769],[26.153231,103.375031],[26.153231,103.374878],[26.15317,103.374748],[26.15295,103.374046],[26.152229,103.373108],[26.151541,103.372322],[26.15114,103.371468],[26.1509,103.370163],[26.150761,103.369881],[26.15069,103.36956],[26.15045,103.369148],[26.14999,103.368767],[26.149561,103.368652],[26.14912,103.368683],[26.1486,103.368927],[26.147631,103.369682],[26.147181,103.369873],[26.14687,103.369904],[26.146391,103.369827],[26.14535,103.369431],[26.14488,103.36937],[26.144581,103.369408],[26.144341,103.36953],[26.14411,103.369728],[26.14381,103.370247],[26.143709,103.370888],[26.143721,103.372162],[26.1436,103.372597],[26.143379,103.373001],[26.1432,103.373222],[26.142719,103.373543],[26.14189,103.373787],[26.137711,103.373772],[26.136459,103.373596],[26.135691,103.373672],[26.13501,103.373833],[26.12385,103.377121],[26.122641,103.377708],[26.11801,103.381523],[26.116779,103.382263],[26.1161,103.38253],[26.11503,103.382759],[26.113741,103.382843],[26.111959,103.382561],[26.11124,103.382233],[26.110331,103.381683],[26.110001,103.381363],[26.108641,103.379333],[26.10817,103.378563],[26.107849,103.377998],[26.107479,103.377693],[26.10696,103.377563],[26.10442,103.377533],[26.10367,103.377296],[26.102921,103.376793],[26.102301,103.376068],[26.100321,103.372772],[26.099701,103.371986],[26.099489,103.371803],[26.09893,103.371521],[26.098669,103.371498],[26.098049,103.371613],[26.097521,103.371902],[26.096581,103.372757],[26.095949,103.373337],[26.09532,103.373833],[26.09458,103.3741],[26.09387,103.374077],[26.09329,103.373894],[26.090401,103.372589],[26.083139,103.368111],[26.082951,103.368011],[26.07933,103.364166],[26.078779,103.363388],[26.078369,103.362213],[26.078131,103.361214],[26.07766,103.360123],[26.07703,103.359161],[26.07538,103.356583],[26.07522,103.356468],[26.07472,103.356041],[26.074341,103.355797],[26.07395,103.355652],[26.07341,103.355598],[26.07279,103.35569],[26.066151,103.35788],[26.06604,103.357964],[26.06423,103.358704],[26.054621,103.363274],[26.05266,103.3638],[26.05201,103.364159],[26.051319,103.364777],[26.05094,103.365219],[26.050579,103.365707],[26.050171,103.366112],[26.049669,103.366417],[26.04929,103.366547],[26.048889,103.366623],[26.04748,103.36657],[26.04694,103.366669],[26.04641,103.36689],[26.045811,103.367363],[26.043739,103.369476],[26.042669,103.370308],[26.037701,103.373703],[26.03702,103.373978],[26.036551,103.374069],[26.035601,103.374107],[26.03249,103.37413],[26.030939,103.374496],[26.027519,103.375816],[26.02634,103.376213],[26.025709,103.376297],[26.02487,103.376244],[26.02202,103.375542],[26.015551,103.374832],[26.014351,103.374496],[26.01321,103.374023],[26.0124,103.373756],[26.011789,103.373688],[26.007721,103.373962],[26.00436,103.373741],[26.00349,103.37384],[26.000931,103.374496],[26.00028,103.374527],[25.99984,103.374474],[25.99917,103.374283],[25.99048,103.369667],[25.98843,103.368462],[25.987419,103.367493],[25.98374,103.362061],[25.98126,103.359642],[25.974859,103.354439],[25.97471,103.354286],[25.968161,103.348991],[25.967581,103.348373],[25.967051,103.347679],[25.96632,103.346207],[25.966,103.34536],[25.965891,103.344963],[25.965139,103.343102],[25.96468,103.3423],[25.96401,103.341583],[25.96048,103.339149],[25.95989,103.338921],[25.95927,103.33886],[25.95841,103.338966],[25.95583,103.339653],[25.954,103.339706],[25.95211,103.339279],[25.95129,103.339073],[25.95068,103.339043],[25.950279,103.339081],[25.949671,103.339279],[25.94873,103.339767],[25.94838,103.340057],[25.946369,103.342346],[25.945511,103.343246],[25.945009,103.343643],[25.944611,103.343849],[25.944201,103.343979],[25.943991,103.344009],[25.943371,103.343933],[25.942789,103.343681],[25.94227,103.343277],[25.941629,103.34256],[25.937929,103.337509],[25.93656,103.335693],[25.935539,103.334587],[25.934219,103.33329],[25.933281,103.33181],[25.93195,103.32885],[25.93116,103.327721],[25.93108,103.327606],[25.930941,103.327522],[25.93082,103.32737],[25.93,103.326981],[25.928551,103.326042],[25.92778,103.325394],[25.926069,103.323463],[25.925529,103.323059],[25.924589,103.322632],[25.92318,103.322243],[25.922449,103.3218],[25.921789,103.321243],[25.920389,103.319901],[25.920111,103.319733],[25.919769,103.319641],[25.91926,103.319649],[25.915279,103.321182],[25.9137,103.321838],[25.91114,103.321938],[25.91078,103.319809],[25.91044,103.316429],[25.910641,103.316177],[25.910789,103.315857],[25.911779,103.314079],[25.912121,103.313232],[25.912319,103.312576],[25.9126,103.310478],[25.913059,103.308723],[25.913099,103.308289],[25.912689,103.306068],[25.91288,103.303902],[25.912809,103.303436],[25.912411,103.302567],[25.91205,103.302177],[25.911591,103.301903],[25.91148,103.301888],[25.910851,103.301537],[25.910299,103.301361],[25.908951,103.300728],[25.9088,103.300598],[25.906731,103.299622],[25.905649,103.299858],[25.905439,103.300003],[25.905359,103.299957],[25.904671,103.300102],[25.903919,103.300034],[25.903509,103.299767],[25.90321,103.299316],[25.902201,103.295471],[25.90147,103.293877],[25.90085,103.293854],[25.90065,103.293762],[25.90052,103.293427],[25.900061,103.292648],[25.89992,103.291634],[25.899891,103.291107],[25.899771,103.290756],[25.899521,103.290352],[25.89922,103.290131],[25.899059,103.290092],[25.89883,103.290108],[25.89856,103.290039],[25.897209,103.290359],[25.8962,103.290253],[25.895651,103.289963],[25.89509,103.289436],[25.894699,103.288834],[25.894199,103.287666],[25.893629,103.287033],[25.893419,103.28688],[25.89274,103.286728],[25.89192,103.286789],[25.890381,103.287148],[25.8895,103.287239],[25.887739,103.286926],[25.88566,103.286507],[25.88493,103.286583],[25.883249,103.287277],[25.88265,103.287369],[25.881981,103.287216],[25.879101,103.28566],[25.87722,103.284523],[25.876011,103.284119],[25.871019,103.283287],[25.86895,103.283157],[25.86727,103.282509],[25.86611,103.281937],[25.865749,103.28183],[25.86347,103.281464],[25.86125,103.280663],[25.85948,103.280479],[25.856489,103.280434],[25.854349,103.280251],[25.8536,103.279984],[25.853001,103.279556],[25.852051,103.278236],[25.850981,103.276466],[25.850651,103.276039],[25.8494,103.275017],[25.849079,103.274834],[25.84857,103.274673],[25.848049,103.274628],[25.847309,103.274696],[25.84659,103.274849],[25.845449,103.274872],[25.84498,103.274757],[25.844231,103.274399],[25.843599,103.274246],[25.84259,103.274292],[25.838961,103.274857],[25.837351,103.274857],[25.83423,103.273956],[25.833731,103.273933],[25.833059,103.274109],[25.832451,103.27446],[25.8311,103.275482],[25.83045,103.275703],[25.829679,103.275757],[25.827801,103.275658],[25.82725,103.275711],[25.826559,103.275932],[25.82596,103.27626],[25.82546,103.276657],[25.82526,103.276878],[25.8204,103.277748],[25.8202,103.277733],[25.820049,103.277649],[25.81978,103.277359],[25.81876,103.276527],[25.8181,103.276207],[25.817751,103.276108],[25.816999,103.276108],[25.81418,103.276428],[25.81275,103.276459],[25.810659,103.276108],[25.80863,103.276161],[25.803711,103.276512],[25.799,103.275848],[25.797159,103.275597],[25.796749,103.275597],[25.796009,103.275749],[25.7952,103.276108],[25.79451,103.276657],[25.79405,103.277161],[25.793079,103.278763],[25.79258,103.279327],[25.79213,103.279648],[25.791451,103.279907],[25.790899,103.279999],[25.790331,103.279953],[25.789801,103.279778],[25.78635,103.277962],[25.78553,103.277649],[25.784929,103.277496],[25.784149,103.277458],[25.78261,103.277557],[25.78163,103.277496],[25.78021,103.277199],[25.77636,103.276031],[25.771879,103.274979],[25.77083,103.274529],[25.769979,103.274109],[25.769329,103.273857],[25.76755,103.273407],[25.76668,103.273247],[25.76523,103.272781],[25.76408,103.272308],[25.763359,103.272102],[25.762831,103.272057],[25.762381,103.272133],[25.76111,103.27253],[25.7603,103.272797],[25.75943,103.272858],[25.759081,103.272781],[25.7582,103.272346],[25.75625,103.271156],[25.755899,103.271004],[25.75555,103.270882],[25.75481,103.27076],[25.75461,103.27076],[25.75441,103.270798],[25.75098,103.27066],[25.74658,103.27095],[25.745951,103.270882],[25.74535,103.270699],[25.741751,103.269157],[25.740379,103.268951],[25.727909,103.269653],[25.72686,103.269577],[25.72611,103.269402],[25.72541,103.269096],[25.723101,103.267998],[25.722099,103.267677],[25.721081,103.267548],[25.72028,103.267563],[25.719259,103.267677],[25.7166,103.267754],[25.714849,103.267647],[25.71176,103.267097],[25.709009,103.26635],[25.708229,103.266197],[25.70643,103.266159],[25.703899,103.266403],[25.70166,103.266502],[25.695101,103.266151],[25.69413,103.26593],[25.69368,103.265709],[25.692631,103.26506],[25.69173,103.264702],[25.69101,103.26458],[25.6898,103.264664],[25.68721,103.265106],[25.685909,103.265381],[25.6849,103.265511],[25.68416,103.26548],[25.683701,103.265358],[25.681999,103.264557],[25.68136,103.264351],[25.68075,103.264259],[25.67716,103.265152],[25.676611,103.265182],[25.67605,103.265083],[25.67461,103.264557],[25.67281,103.263763],[25.67136,103.26326],[25.668329,103.262451],[25.667351,103.261978],[25.665979,103.261162],[25.665279,103.260902],[25.664801,103.260811],[25.664061,103.260811],[25.661209,103.261253],[25.66028,103.261253],[25.65893,103.261002],[25.65873,103.260933],[25.657881,103.26078],[25.65686,103.260857],[25.65041,103.263283],[25.64731,103.264412],[25.64706,103.264481],[25.646259,103.264603],[25.645109,103.264549],[25.64435,103.264412],[25.63361,103.261147],[25.63203,103.260757],[25.63093,103.260399],[25.62985,103.259933],[25.628759,103.259354],[25.62656,103.257698],[25.62546,103.256607],[25.62421,103.254982],[25.62351,103.25383],[25.62183,103.250664],[25.620859,103.249229],[25.61961,103.247726],[25.607679,103.235161],[25.599199,103.226303],[25.597651,103.224983],[25.595449,103.223511],[25.5819,103.217506],[25.5807,103.217133],[25.57921,103.216927],[25.578711,103.216911],[25.577959,103.216927],[25.57568,103.216881],[25.574659,103.216698],[25.566509,103.214333],[25.5655,103.213852],[25.5634,103.212646],[25.5632,103.212509],[25.55838,103.209663],[25.556431,103.208527],[25.55505,103.207977],[25.553829,103.20768],[25.550329,103.207092],[25.54949,103.206947],[25.549971,103.207581],[25.55011,103.207863],[25.55036,103.208107],[25.550711,103.208153],[25.551161,103.208252],[25.551571,103.208557],[25.55184,103.206657],[25.55212,103.2062],[25.552441,103.206009],[25.55271,103.205597],[25.552811,103.204437],[25.55295,103.201317],[25.55307,103.197433],[25.553141,103.196373],[25.553471,103.191902],[25.55352,103.191704],[25.55443,103.188454],[25.55512,103.185707],[25.55559,103.183983],[25.556129,103.182167],[25.556459,103.181473],[25.556829,103.180923],[25.557421,103.18029],[25.557961,103.179893],[25.558849,103.179443],[25.56251,103.177856],[25.56278,103.177696],[25.563021,103.177513],[25.56337,103.176979],[25.56349,103.176689],[25.56361,103.176163],[25.5637,103.175423],[25.56385,103.174667],[25.566589,103.167618],[25.56706,103.166313],[25.56739,103.165588],[25.568171,103.164452],[25.568741,103.163582],[25.569189,103.163292],[25.57011,103.16304],[25.57065,103.162827],[25.57196,103.16214],[25.572519,103.161873],[25.573351,103.16143],[25.573721,103.161507],[25.5742,103.161903],[25.57464,103.161949],[25.574829,103.161812],[25.57535,103.161179],[25.57547,103.160851],[25.575331,103.160667],[25.57497,103.160606],[25.57469,103.160347],[25.574699,103.15976],[25.5748,103.159492],[25.57592,103.158859],[25.57621,103.158661],[25.576571,103.158234],[25.57695,103.157837],[25.57728,103.157677],[25.57756,103.157677],[25.577869,103.1576],[25.578381,103.15728],[25.578501,103.157158],[25.578569,103.156998],[25.578751,103.156227],[25.57889,103.155884],[25.578951,103.155617],[25.578899,103.155373],[25.57851,103.154999],[25.578341,103.154762],[25.5783,103.154556],[25.578291,103.153717],[25.578421,103.153511],[25.578581,103.153572],[25.578779,103.153908],[25.57897,103.154114],[25.579531,103.154411],[25.5797,103.154297],[25.579691,103.154083],[25.57925,103.153549],[25.579029,103.153137],[25.57893,103.152763],[25.57901,103.152313],[25.579121,103.152031],[25.57951,103.151489],[25.57963,103.15123],[25.57971,103.150513],[25.57984,103.15023],[25.580021,103.15023],[25.58012,103.150337],[25.580151,103.150909],[25.58033,103.151741],[25.580509,103.15197],[25.580709,103.152061],[25.58091,103.152077],[25.58124,103.151878],[25.582331,103.149551],[25.583521,103.147102],[25.58371,103.146568],[25.583759,103.14608],[25.58305,103.142853],[25.582661,103.141586],[25.582661,103.141121],[25.583111,103.139793],[25.58313,103.139458],[25.58235,103.136772],[25.581261,103.134132],[25.58086,103.133087],[25.580469,103.132187],[25.58016,103.131752],[25.57819,103.130074],[25.57766,103.129532],[25.577579,103.129402],[25.57732,103.128807],[25.576981,103.127869],[25.57686,103.127609],[25.576509,103.127213],[25.57601,103.126793],[25.575859,103.126587],[25.57546,103.125763],[25.575029,103.125343],[25.574381,103.125191],[25.57383,103.125221],[25.573139,103.125366],[25.572701,103.125343],[25.572411,103.12513],[25.572041,103.124657],[25.57058,103.12236],[25.570129,103.121719],[25.56999,103.121452],[25.56992,103.12104],[25.570089,103.120644],[25.57011,103.120171],[25.569851,103.119743],[25.569521,103.119537],[25.567829,103.119141],[25.567499,103.11882],[25.567249,103.118172],[25.566469,103.117126],[25.566259,103.116653],[25.566311,103.116257],[25.56665,103.115494],[25.566719,103.114906],[25.5667,103.11467],[25.566521,103.114182],[25.56608,103.113403],[25.56568,103.112846],[25.565281,103.112373],[25.56498,103.112122],[25.563419,103.111099],[25.55805,103.107399],[25.55769,103.107231],[25.5539,103.105881],[25.5509,103.104362],[25.54928,103.103989],[25.54875,103.103996],[25.548,103.10421],[25.547489,103.104179],[25.546881,103.103958],[25.546,103.103523],[25.54587,103.103317],[25.5459,103.103203],[25.546021,103.102921],[25.54619,103.10276],[25.546551,103.102676],[25.547609,103.102509],[25.54808,103.102531],[25.548491,103.102364],[25.548651,103.102249],[25.548809,103.101883],[25.54903,103.101791],[25.549311,103.102112],[25.549601,103.102226],[25.55043,103.102081],[25.55094,103.101936],[25.55117,103.101807],[25.55135,103.101593],[25.551689,103.101341],[25.55188,103.101341],[25.55261,103.101448],[25.552971,103.101334],[25.553209,103.101028],[25.55323,103.100754],[25.552891,103.099854],[25.55262,103.099663],[25.55237,103.099602],[25.55221,103.099319],[25.552,103.098473],[25.551741,103.097923],[25.55172,103.097511],[25.55191,103.097099],[25.552271,103.096809],[25.5527,103.09684],[25.552879,103.096947],[25.553631,103.097603],[25.554001,103.097733],[25.555149,103.097931],[25.555559,103.098129],[25.55596,103.098267],[25.55673,103.097969],[25.55715,103.097763],[25.557779,103.097687],[25.558451,103.097481],[25.559259,103.096878],[25.559469,103.096367],[25.55983,103.096092],[25.55995,103.09584],[25.559891,103.095459],[25.55999,103.095337],[25.56019,103.095222],[25.56027,103.094994],[25.560261,103.09491],[25.56045,103.094612],[25.56053,103.094597],[25.560789,103.094353],[25.56094,103.093941],[25.561159,103.093773],[25.56131,103.093964],[25.56152,103.094498],[25.561859,103.094933],[25.562401,103.095062],[25.562771,103.095047],[25.563141,103.09494],[25.56348,103.094719],[25.564951,103.093613],[25.565281,103.093552],[25.56558,103.093719],[25.56576,103.093781],[25.566071,103.093773],[25.56847,103.093002],[25.568859,103.09269],[25.570089,103.091476],[25.570459,103.091301],[25.570709,103.091263],[25.571011,103.09111],[25.571091,103.090919],[25.571091,103.090347],[25.57073,103.089706],[25.570801,103.089394],[25.57111,103.089249],[25.571381,103.08902],[25.57136,103.088783],[25.570959,103.088074],[25.57095,103.087837],[25.571119,103.087791],[25.57139,103.087784],[25.572081,103.087608],[25.57238,103.08741],[25.57251,103.087021],[25.572309,103.083817],[25.57247,103.082024],[25.572451,103.081833],[25.572371,103.081642],[25.571899,103.080872],[25.57159,103.080421],[25.571381,103.08004],[25.57136,103.079712],[25.571541,103.079498],[25.571911,103.079277],[25.572201,103.078949],[25.57238,103.078491],[25.572651,103.078102],[25.573219,103.077606],[25.57412,103.076927],[25.57445,103.076408],[25.57472,103.075829],[25.57514,103.07444],[25.57538,103.073853],[25.576191,103.072327],[25.576509,103.071617],[25.576969,103.070282],[25.57692,103.069893],[25.57634,103.068428],[25.576241,103.068283],[25.57583,103.067947],[25.575491,103.067886],[25.57477,103.067917],[25.57431,103.067993],[25.573549,103.068024],[25.573231,103.067886],[25.573071,103.067589],[25.572729,103.06546],[25.572651,103.065163],[25.572309,103.064743],[25.571779,103.064262],[25.571659,103.063957],[25.57176,103.063797],[25.573151,103.062553],[25.57329,103.062248],[25.57332,103.058449],[25.57328,103.057503],[25.573191,103.056824],[25.572861,103.05513],[25.57259,103.054642],[25.5718,103.053482],[25.57119,103.052803],[25.57078,103.052467],[25.5707,103.052429],[25.5704,103.052116],[25.57029,103.051788],[25.570129,103.051514],[25.56991,103.051277],[25.569401,103.051086],[25.56897,103.051041],[25.568569,103.050858],[25.568251,103.050484],[25.56826,103.050209],[25.568439,103.050117],[25.56875,103.050163],[25.56941,103.050034],[25.56971,103.049828],[25.570129,103.049744],[25.57021,103.049751],[25.57085,103.049637],[25.57099,103.049553],[25.571159,103.049057],[25.571171,103.048843],[25.5711,103.048607],[25.57073,103.047859],[25.57004,103.046677],[25.56974,103.046463],[25.56904,103.04615],[25.56856,103.04583],[25.56805,103.045403],[25.56785,103.045097],[25.567631,103.044533],[25.567249,103.044243],[25.566759,103.044067],[25.56636,103.044167],[25.56559,103.044731],[25.56531,103.044678],[25.565241,103.043938],[25.56517,103.043663],[25.565241,103.043167],[25.565371,103.042923],[25.56538,103.042542],[25.565269,103.042374],[25.56428,103.041054],[25.563749,103.040413],[25.562929,103.039612],[25.562571,103.03894],[25.56245,103.038544],[25.562031,103.037956],[25.561899,103.037437],[25.561741,103.037323],[25.561319,103.037193],[25.56114,103.037109],[25.56098,103.036812],[25.561119,103.036598],[25.56152,103.036247],[25.56159,103.036003],[25.56147,103.035896],[25.561171,103.035744],[25.56093,103.035667],[25.56032,103.035713],[25.56004,103.035538],[25.55975,103.035011],[25.55949,103.034401],[25.55925,103.034157],[25.55895,103.033997],[25.55879,103.033691],[25.558889,103.033432],[25.55932,103.032944],[25.559469,103.032471],[25.55938,103.032204],[25.55883,103.031616],[25.55821,103.031197],[25.55794,103.030731],[25.55785,103.030411],[25.5576,103.030113],[25.556141,103.029617],[25.555771,103.029457],[25.555401,103.02948],[25.555309,103.029533],[25.554899,103.029587],[25.55475,103.029381],[25.554729,103.028687],[25.554689,103.028503],[25.554489,103.028358],[25.55349,103.028343],[25.55323,103.028152],[25.55324,103.027718],[25.55316,103.027229],[25.55294,103.026657],[25.5527,103.026413],[25.55253,103.026337],[25.552259,103.025993],[25.552361,103.025703],[25.552589,103.025459],[25.55295,103.025337],[25.55312,103.025436],[25.553419,103.025757],[25.55369,103.025909],[25.555309,103.025841],[25.55563,103.025673],[25.55615,103.025169],[25.556259,103.024849],[25.55616,103.024689],[25.55513,103.023552],[25.555019,103.023193],[25.55521,103.023087],[25.555559,103.023102],[25.556179,103.022926],[25.556749,103.02269],[25.55724,103.022552],[25.55743,103.022537],[25.557711,103.022598],[25.55817,103.022781],[25.559549,103.023666],[25.56052,103.024246],[25.561411,103.024841],[25.562189,103.025307],[25.56303,103.025551],[25.56348,103.025864],[25.563971,103.025993],[25.56423,103.026016],[25.564751,103.025917],[25.565861,103.025681],[25.566389,103.025398],[25.566771,103.025307],[25.567551,103.025284],[25.567841,103.025299],[25.56811,103.025513],[25.568371,103.02594],[25.568729,103.026199],[25.568899,103.026283],[25.569241,103.026222],[25.569469,103.026047],[25.569651,103.025772],[25.569889,103.0252],[25.569969,103.024673],[25.57015,103.024231],[25.570391,103.023933],[25.57065,103.023376],[25.57066,103.022972],[25.570589,103.022568],[25.57069,103.022057],[25.57078,103.021828],[25.570761,103.021362],[25.570669,103.021133],[25.570669,103.020638],[25.570841,103.019882],[25.570829,103.019081],[25.570971,103.018578],[25.57155,103.017769],[25.572029,103.017174],[25.572241,103.016777],[25.573,103.014839],[25.573151,103.01416],[25.573271,103.013031],[25.573271,103.012833],[25.57338,103.012459],[25.573601,103.012138],[25.5737,103.011833],[25.57345,103.011597],[25.57276,103.011101],[25.572639,103.010773],[25.57287,103.010193],[25.57291,103.009628],[25.5728,103.008873],[25.572901,103.008636],[25.573071,103.00869],[25.574011,103.009239],[25.57431,103.009277],[25.574421,103.009071],[25.574459,103.00782],[25.574369,103.007431],[25.574089,103.00692],[25.57399,103.006683],[25.57394,103.006271],[25.573971,103.005928],[25.5744,103.004807],[25.574659,103.003403],[25.574949,103.002617],[25.575359,103.001923],[25.5756,103.001801],[25.5758,103.001961],[25.576151,103.002373],[25.5765,103.002541],[25.57749,103.001961],[25.577869,103.0019],[25.578369,103.001999],[25.57873,103.001869],[25.57901,103.001549],[25.579069,103.001289],[25.577009,102.99852],[25.57688,102.998253],[25.57686,102.997772],[25.577089,102.996407],[25.57708,102.996094],[25.57691,102.995811],[25.5767,102.995773],[25.576521,102.995819],[25.575609,102.996269],[25.575411,102.99617],[25.57548,102.996048],[25.5763,102.995232],[25.57654,102.995064],[25.57675,102.995033],[25.57715,102.995049],[25.577591,102.99514],[25.57785,102.995064],[25.57794,102.99482],[25.57836,102.993217],[25.578449,102.992981],[25.578621,102.992683],[25.578791,102.992439],[25.579309,102.991913],[25.5812,102.990082],[25.58205,102.989059],[25.582279,102.988907],[25.58251,102.988792],[25.58301,102.988663],[25.583771,102.988411],[25.58437,102.988167],[25.5846,102.988037],[25.585039,102.987671],[25.58606,102.98629],[25.58633,102.986267],[25.586519,102.986343],[25.58758,102.986969],[25.587811,102.987312],[25.587959,102.987717],[25.58802,102.988091],[25.588169,102.988327],[25.588539,102.988564],[25.58975,102.988907],[25.590191,102.988777],[25.590389,102.988503],[25.590839,102.987663],[25.59111,102.987282],[25.591299,102.987152],[25.591869,102.987137],[25.592039,102.986992],[25.59201,102.986649],[25.59215,102.986328],[25.592461,102.986252],[25.5931,102.986252],[25.59341,102.986153],[25.593769,102.985893],[25.594481,102.985092],[25.59498,102.984711],[25.595209,102.984337],[25.595329,102.98391],[25.59564,102.983597],[25.59643,102.983238],[25.59668,102.983063],[25.597679,102.981483],[25.59775,102.98114],[25.597561,102.980873],[25.59642,102.979721],[25.59584,102.979057],[25.59581,102.978737],[25.59623,102.977921],[25.596569,102.977707],[25.597219,102.977814],[25.59786,102.978073],[25.59832,102.978287],[25.599661,102.9786],[25.599911,102.978561],[25.60006,102.97834],[25.6001,102.977921],[25.599991,102.977463],[25.599779,102.976967],[25.5998,102.976639],[25.600031,102.976479],[25.60071,102.976173],[25.60117,102.975754],[25.60154,102.975067],[25.601641,102.974602],[25.601561,102.974007],[25.60165,102.973717],[25.60182,102.973747],[25.602051,102.974007],[25.60243,102.97509],[25.6024,102.975471],[25.60183,102.976227],[25.60181,102.976547],[25.602011,102.976547],[25.603609,102.975906],[25.603821,102.975647],[25.603769,102.97541],[25.603359,102.974609],[25.603331,102.974472],[25.60346,102.974319],[25.604481,102.974373],[25.604771,102.974297],[25.60491,102.974197],[25.605009,102.973938],[25.60498,102.973549],[25.60494,102.973457],[25.604691,102.973167],[25.604469,102.973106],[25.60416,102.973312],[25.603689,102.973396],[25.603491,102.973343],[25.60321,102.973167],[25.60293,102.972801],[25.60251,102.972412],[25.60206,102.972237],[25.601959,102.97213],[25.601971,102.971931],[25.602171,102.971863],[25.602819,102.971992],[25.60317,102.972214],[25.60331,102.972351],[25.603649,102.972473],[25.60388,102.972321],[25.60404,102.972183],[25.60442,102.972023],[25.60486,102.972092],[25.60602,102.972649],[25.60634,102.972748],[25.606899,102.97274],[25.60745,102.972878],[25.607981,102.972961],[25.608231,102.972862],[25.60829,102.972633],[25.608471,102.972298],[25.60874,102.972343],[25.608879,102.972397],[25.60988,102.972366],[25.610029,102.972321],[25.610189,102.972076],[25.61021,102.971901],[25.610331,102.971603],[25.61055,102.971573],[25.61134,102.971786],[25.61194,102.972267],[25.612289,102.972359],[25.613131,102.972153],[25.613319,102.972054],[25.61364,102.971764],[25.613831,102.971558],[25.614111,102.971474],[25.614429,102.97155],[25.615049,102.971512],[25.615311,102.971291],[25.6154,102.971161],[25.61553,102.971077],[25.615829,102.971008],[25.615959,102.970932],[25.616211,102.970627],[25.616461,102.970528],[25.616739,102.970497],[25.617399,102.969994],[25.61771,102.969803],[25.617941,102.969498],[25.61805,102.969223],[25.618219,102.969032],[25.61842,102.969048],[25.618561,102.969223],[25.618561,102.969383],[25.618481,102.970016],[25.618481,102.970551],[25.618549,102.971062],[25.618759,102.971489],[25.618971,102.971657],[25.619221,102.97171],[25.61978,102.971733],[25.62006,102.971626],[25.620211,102.971413],[25.62038,102.970863],[25.620449,102.970512],[25.620649,102.970238],[25.62126,102.969719],[25.62174,102.969093],[25.6222,102.968323],[25.622499,102.968132],[25.62294,102.96814],[25.6234,102.968117],[25.62351,102.968178],[25.623699,102.968407],[25.623911,102.96859],[25.625469,102.967621],[25.627781,102.966187],[25.627621,102.965813],[25.627621,102.965477],[25.627859,102.96505],[25.6283,102.964462],[25.628889,102.963753],[25.629,102.963387],[25.629089,102.962563],[25.62904,102.962257],[25.628839,102.961777],[25.62862,102.961403],[25.62833,102.961143],[25.62796,102.960907],[25.627819,102.960747],[25.62731,102.959862],[25.62722,102.959396],[25.62723,102.959007],[25.627291,102.958633],[25.627211,102.958298],[25.62694,102.95784],[25.62648,102.957329],[25.62628,102.956963],[25.62595,102.956596],[25.625601,102.956352],[25.62553,102.956039],[25.62541,102.955711],[25.62524,102.955406],[25.62499,102.955162],[25.62484,102.955063],[25.623581,102.954483],[25.62315,102.954224],[25.622629,102.953583],[25.62224,102.953362],[25.62196,102.953468],[25.62182,102.953552],[25.621469,102.953529],[25.620239,102.952423],[25.61982,102.951881],[25.61858,102.950859],[25.61842,102.95076],[25.618259,102.9505],[25.61829,102.950073],[25.61845,102.949753],[25.618719,102.949577],[25.61883,102.949387],[25.618811,102.949226],[25.618719,102.948967],[25.618641,102.948402],[25.618441,102.947952],[25.61828,102.94735],[25.618179,102.946892],[25.61812,102.94632],[25.617769,102.945633],[25.61768,102.945137],[25.61776,102.94471],[25.617649,102.944382],[25.617491,102.944077],[25.61746,102.943748],[25.617781,102.942963],[25.617809,102.942078],[25.61795,102.941742],[25.61797,102.941528],[25.617781,102.94117],[25.61776,102.940407],[25.617861,102.939972],[25.617901,102.939339],[25.6178,102.938782],[25.61771,102.938461],[25.61768,102.937958],[25.617781,102.937714],[25.617821,102.937241],[25.618,102.936813],[25.61805,102.936348],[25.618099,102.935249],[25.617941,102.934036],[25.61797,102.933632],[25.617861,102.932953],[25.617729,102.932457],[25.617479,102.932083],[25.617371,102.931808],[25.617081,102.931541],[25.616779,102.931427],[25.61676,102.931282],[25.61688,102.931107],[25.61673,102.930267],[25.616631,102.929993],[25.616199,102.929237],[25.615931,102.928963],[25.614639,102.928253],[25.61445,102.928078],[25.613991,102.927422],[25.613489,102.927032],[25.6127,102.92659],[25.61248,102.926521],[25.61199,102.926628],[25.61153,102.926666],[25.611259,102.926537],[25.61105,102.925926],[25.610781,102.925697],[25.610479,102.925613],[25.6103,102.925392],[25.610371,102.924728],[25.610371,102.924301],[25.61043,102.923973],[25.610491,102.923828],[25.610439,102.9235],[25.610201,102.923363],[25.609949,102.923264],[25.609461,102.923233],[25.60914,102.923157],[25.6084,102.922737],[25.60824,102.922859],[25.608191,102.923111],[25.608259,102.923241],[25.608219,102.923508],[25.60812,102.923492],[25.607941,102.923561],[25.607849,102.923927],[25.607771,102.924011],[25.60762,102.92395],[25.60759,102.923622],[25.607691,102.922592],[25.60787,102.922256],[25.60795,102.921982],[25.607821,102.921707],[25.607491,102.921211],[25.60722,102.921173],[25.607071,102.921188],[25.60692,102.921127],[25.60644,102.92083],[25.606291,102.920807],[25.606211,102.920982],[25.606159,102.921494],[25.606091,102.921577],[25.605961,102.921516],[25.60586,102.921082],[25.60568,102.92099],[25.605619,102.920792],[25.60569,102.920547],[25.60565,102.92009],[25.60545,102.919838],[25.604271,102.91967],[25.60396,102.91951],[25.60379,102.919617],[25.60364,102.919807],[25.603559,102.920151],[25.603359,102.920151],[25.602989,102.919861],[25.60272,102.919739],[25.602579,102.919456],[25.60223,102.919037],[25.60183,102.918709],[25.60136,102.918083],[25.601191,102.917763],[25.600969,102.917557],[25.60087,102.917397],[25.600599,102.917236],[25.6003,102.917297],[25.600161,102.917664],[25.600241,102.918022],[25.60009,102.918243],[25.599541,102.918098],[25.59934,102.918182],[25.599211,102.918518],[25.599051,102.918556],[25.5989,102.918793],[25.59885,102.918968],[25.59865,102.919121],[25.59852,102.918968],[25.598511,102.918709],[25.59864,102.918373],[25.59866,102.918228],[25.598579,102.918022],[25.598511,102.917908],[25.598511,102.917587],[25.598379,102.917328],[25.598351,102.917107],[25.59819,102.916779],[25.59796,102.916611],[25.59761,102.916496],[25.59729,102.916458],[25.596769,102.916283],[25.59659,102.916077],[25.59671,102.915573],[25.596649,102.914948],[25.596519,102.914742],[25.596359,102.914711],[25.59586,102.914703],[25.59573,102.914757],[25.5954,102.915154],[25.59506,102.91571],[25.59487,102.915878],[25.59474,102.915932],[25.594431,102.915878],[25.59407,102.915756],[25.593691,102.915382],[25.593519,102.914993],[25.592871,102.914192],[25.592609,102.913803],[25.59234,102.913513],[25.59211,102.912987],[25.59197,102.912491],[25.591669,102.911789],[25.59071,102.91037],[25.590469,102.91021],[25.590071,102.910103],[25.58975,102.90995],[25.58959,102.909912],[25.589211,102.909927],[25.58868,102.910004],[25.5884,102.909897],[25.588261,102.909798],[25.58798,102.909813],[25.58782,102.909859],[25.5875,102.909882],[25.58699,102.90976],[25.585819,102.909187],[25.585449,102.908943],[25.58544,102.908699],[25.5858,102.908569],[25.586081,102.908386],[25.586241,102.908234],[25.586269,102.908043],[25.58604,102.907837],[25.585581,102.90773],[25.584961,102.907799],[25.584629,102.907753],[25.58371,102.907288],[25.583099,102.906822],[25.58275,102.906807],[25.582661,102.906822],[25.58205,102.906647],[25.58185,102.90641],[25.58164,102.905609],[25.581699,102.905273],[25.58185,102.905029],[25.581779,102.904793],[25.58152,102.904533],[25.58119,102.904556],[25.58087,102.904472],[25.580669,102.904457],[25.5804,102.904388],[25.580099,102.904373],[25.580009,102.904198],[25.58032,102.903831],[25.58083,102.903282],[25.580879,102.903183],[25.580811,102.903053],[25.580469,102.902924],[25.57958,102.902191],[25.57937,102.901939],[25.57925,102.901649],[25.57921,102.901337],[25.5791,102.901031],[25.57893,102.901062],[25.578751,102.90136],[25.578501,102.901573],[25.578369,102.901543],[25.57807,102.90139],[25.57753,102.900818],[25.577379,102.900467],[25.577169,102.899788],[25.57715,102.899384],[25.5774,102.899071],[25.57745,102.898804],[25.577271,102.898483],[25.577089,102.898247],[25.57703,102.897957],[25.577141,102.897652],[25.577379,102.897438],[25.577539,102.897362],[25.577721,102.897148],[25.577629,102.897003],[25.57741,102.896973],[25.577209,102.897003],[25.576229,102.897469],[25.57593,102.897659],[25.5756,102.897598],[25.57543,102.897522],[25.57514,102.897453],[25.57485,102.897209],[25.57473,102.896812],[25.57469,102.896591],[25.57452,102.896301],[25.57415,102.896103],[25.573811,102.896027],[25.572241,102.896133],[25.572001,102.896263],[25.57193,102.896683],[25.57172,102.896973],[25.57151,102.897011],[25.57128,102.896873],[25.571131,102.896721],[25.57074,102.896187],[25.570379,102.89521],[25.57044,102.89476],[25.57066,102.894417],[25.57089,102.894234],[25.57114,102.894127],[25.57148,102.894119],[25.571859,102.893997],[25.572029,102.893837],[25.571951,102.893669],[25.571739,102.893547],[25.57148,102.893463],[25.57128,102.893227],[25.57128,102.89296],[25.5714,102.892723],[25.571951,102.892273],[25.57198,102.892021],[25.57176,102.891647],[25.57155,102.891586],[25.571421,102.891663],[25.571011,102.891693],[25.570869,102.891327],[25.57057,102.891052],[25.57011,102.890793],[25.569719,102.890694],[25.569361,102.89035],[25.568489,102.889229],[25.567909,102.887688],[25.56793,102.88752],[25.567909,102.886253],[25.567949,102.885918],[25.56806,102.885567],[25.568069,102.885399],[25.56794,102.885048],[25.56743,102.884483],[25.567261,102.884377],[25.567141,102.884232],[25.566931,102.883827],[25.56671,102.883163],[25.566589,102.882423],[25.56633,102.881477],[25.56632,102.881042],[25.56641,102.880409],[25.56662,102.880058],[25.56691,102.879951],[25.5672,102.879997],[25.567471,102.880219],[25.567591,102.88018],[25.56765,102.878922],[25.567579,102.878487],[25.56748,102.878326],[25.5672,102.87812],[25.56711,102.877892],[25.56727,102.877777],[25.567751,102.877922],[25.56814,102.878143],[25.56839,102.878052],[25.568529,102.877747],[25.56867,102.877533],[25.568661,102.877319],[25.56848,102.877167],[25.56822,102.876717],[25.567921,102.875954],[25.56743,102.875412],[25.567089,102.874863],[25.56694,102.874687],[25.566811,102.874443],[25.56683,102.873787],[25.566799,102.873581],[25.566589,102.873062],[25.566509,102.872383],[25.566549,102.872101],[25.56629,102.871712],[25.56604,102.871521],[25.565519,102.871399],[25.565491,102.871338],[25.56555,102.87114],[25.56568,102.871109],[25.566219,102.871094],[25.566681,102.871117],[25.566839,102.871063],[25.56694,102.870743],[25.567181,102.870689],[25.567419,102.870743],[25.56765,102.870598],[25.5679,102.870247],[25.56834,102.87001],[25.56852,102.869949],[25.56879,102.869957],[25.568951,102.869881],[25.568781,102.86982],[25.56852,102.869843],[25.568211,102.869904],[25.56769,102.870216],[25.56748,102.870209],[25.567341,102.870003],[25.567181,102.869881],[25.56711,102.869911],[25.566959,102.869873],[25.56674,102.869568],[25.566549,102.869568],[25.5662,102.869759],[25.565901,102.869751],[25.565769,102.869553],[25.565639,102.869141],[25.565439,102.868973],[25.565161,102.86927],[25.56481,102.869278],[25.564409,102.869057],[25.56431,102.868896],[25.564449,102.868843],[25.564699,102.869011],[25.56496,102.868927],[25.56514,102.868698],[25.565149,102.86824],[25.565331,102.867973],[25.56554,102.867981],[25.565651,102.868149],[25.56567,102.868233],[25.56596,102.868752],[25.566059,102.86882],[25.56624,102.868729],[25.56636,102.8685],[25.56641,102.868118],[25.566561,102.867844],[25.566719,102.867844],[25.56735,102.867981],[25.56756,102.868156],[25.567579,102.868401],[25.56781,102.868553],[25.568159,102.86853],[25.568399,102.868423],[25.56855,102.868217],[25.568529,102.867973],[25.568211,102.867592],[25.568029,102.867249],[25.56786,102.867027],[25.567881,102.866783],[25.568911,102.866707],[25.569241,102.866783],[25.570761,102.86763],[25.57093,102.867523],[25.570921,102.867348],[25.57099,102.867012],[25.571159,102.86647],[25.57136,102.866241],[25.57143,102.866257],[25.571569,102.866379],[25.57169,102.866524],[25.57197,102.866653],[25.572149,102.866577],[25.572069,102.866501],[25.57164,102.866364],[25.57136,102.866058],[25.571199,102.865608],[25.571171,102.864967],[25.57122,102.864708],[25.57115,102.864471],[25.570881,102.864357],[25.570511,102.864471],[25.57025,102.864342],[25.57019,102.864197],[25.569851,102.863907],[25.569229,102.86396],[25.568859,102.863937],[25.568781,102.863853],[25.56867,102.863609],[25.568251,102.863373],[25.56687,102.86322],[25.56637,102.86319],[25.566031,102.863022],[25.565651,102.862617],[25.56531,102.862083],[25.56517,102.861656],[25.56525,102.86129],[25.565519,102.860847],[25.565741,102.860687],[25.56608,102.860863],[25.56629,102.860771],[25.566311,102.860611],[25.566139,102.860527],[25.565479,102.860512],[25.565109,102.860558],[25.56468,102.860573],[25.564329,102.860741],[25.56365,102.861557],[25.563601,102.861717],[25.563629,102.861923],[25.563789,102.862122],[25.563881,102.862328],[25.563761,102.862427],[25.563601,102.862373],[25.56307,102.861832],[25.562429,102.861343],[25.561569,102.860893],[25.561119,102.860367],[25.560459,102.859528],[25.56015,102.859093],[25.56003,102.85833],[25.559959,102.857964],[25.559919,102.857437],[25.559719,102.856163],[25.55953,102.855972],[25.55942,102.855942],[25.55896,102.855942],[25.55772,102.856003],[25.55703,102.855904],[25.55681,102.855904],[25.55654,102.855782],[25.55633,102.855614],[25.55617,102.855263],[25.55599,102.855133],[25.555901,102.855164],[25.555651,102.855431],[25.555321,102.855392],[25.55456,102.85511],[25.554291,102.855057],[25.553921,102.855179],[25.553591,102.855324],[25.553341,102.855362],[25.55294,102.855301],[25.552679,102.855202],[25.55188,102.855217],[25.55147,102.855087],[25.550859,102.854698],[25.54953,102.853508],[25.54875,102.852898],[25.548559,102.852814],[25.54796,102.852661],[25.547449,102.852577],[25.546801,102.852379],[25.546551,102.852379],[25.54578,102.852631],[25.54534,102.85257],[25.544741,102.852402],[25.544359,102.852173],[25.543779,102.85141],[25.543341,102.850937],[25.542999,102.850693],[25.54266,102.850594],[25.54203,102.850563],[25.54142,102.850288],[25.54101,102.849953],[25.540751,102.849663],[25.540251,102.849312],[25.53968,102.849091],[25.539049,102.8489],[25.53875,102.848778],[25.53825,102.848732],[25.537319,102.848907],[25.53697,102.848846],[25.53651,102.848648],[25.53606,102.848587],[25.53561,102.848587],[25.53496,102.84845],[25.53355,102.848106],[25.53294,102.847832],[25.532459,102.847412],[25.53199,102.846916],[25.53117,102.846443],[25.53091,102.846397],[25.530769,102.846527],[25.530701,102.846657],[25.530491,102.846817],[25.52914,102.847054],[25.52866,102.846939],[25.528021,102.846474],[25.526331,102.84597],[25.525669,102.845963],[25.52438,102.845863],[25.5235,102.845863],[25.521919,102.845772],[25.521441,102.845711],[25.520981,102.845543],[25.520729,102.845329],[25.520269,102.84507],[25.519991,102.844971],[25.51977,102.84494],[25.51848,102.845047],[25.51799,102.845009],[25.517521,102.844788],[25.51539,102.843437],[25.515289,102.843292],[25.51527,102.84272],[25.51557,102.841843],[25.51557,102.841537],[25.5149,102.840942],[25.514481,102.840714],[25.514111,102.840759],[25.513929,102.840874],[25.513559,102.841217],[25.513269,102.841309],[25.513109,102.841232],[25.51281,102.841003],[25.512461,102.8405],[25.51214,102.840179],[25.51178,102.839981],[25.511009,102.840279],[25.50868,102.841408],[25.507601,102.841782],[25.5072,102.841812],[25.50643,102.841499],[25.505911,102.841209],[25.50576,102.84108],[25.50568,102.840912],[25.50565,102.840752],[25.505659,102.840363],[25.50563,102.840202],[25.505501,102.840057],[25.50535,102.839996],[25.504881,102.840202],[25.50456,102.840401],[25.50433,102.840698],[25.50415,102.841026],[25.504129,102.841652],[25.504061,102.84185],[25.50346,102.842682],[25.503401,102.84285],[25.50321,102.843002],[25.50305,102.84301],[25.502899,102.842857],[25.5028,102.842712],[25.50263,102.842163],[25.502251,102.841728],[25.50206,102.841614],[25.501881,102.84156],[25.50173,102.841629],[25.50161,102.841751],[25.501551,102.841911],[25.50153,102.842102],[25.501699,102.842911],[25.50173,102.843353],[25.5016,102.843964],[25.501631,102.844162],[25.501949,102.844704],[25.502001,102.844856],[25.50201,102.845062],[25.501961,102.845253],[25.501881,102.845398],[25.50091,102.845932],[25.500811,102.846062],[25.50058,102.846848],[25.50036,102.84716],[25.500231,102.84726],[25.50005,102.847298],[25.499531,102.847183],[25.498911,102.846977],[25.498529,102.846832],[25.498199,102.846657],[25.497431,102.846008],[25.49725,102.846008],[25.497061,102.846153],[25.496731,102.846649],[25.49658,102.846779],[25.496401,102.846878],[25.49621,102.846901],[25.49605,102.846802],[25.49593,102.846649],[25.495649,102.8461],[25.49518,102.845451],[25.495001,102.845131],[25.494949,102.844948],[25.494949,102.844711],[25.495131,102.844299],[25.495461,102.84388],[25.495529,102.843681],[25.49548,102.843483],[25.495279,102.843407],[25.49511,102.843452],[25.494909,102.843552],[25.494711,102.843559],[25.49456,102.843483],[25.494431,102.843353],[25.494129,102.842613],[25.493851,102.842361],[25.49333,102.842079],[25.492979,102.842056],[25.492781,102.842102],[25.491449,102.842697],[25.491261,102.842728],[25.49066,102.842682],[25.49048,102.842712],[25.490351,102.84285],[25.49028,102.843033],[25.49025,102.843262],[25.490259,102.843498],[25.49033,102.843758],[25.49045,102.843979],[25.49118,102.844856],[25.491461,102.845497],[25.491579,102.84568],[25.492001,102.846497],[25.492149,102.846931],[25.492149,102.847107],[25.49206,102.847298],[25.491211,102.848328],[25.491131,102.84848],[25.4911,102.848663],[25.49118,102.848877],[25.492599,102.849213],[25.492929,102.849411],[25.49305,102.849602],[25.493059,102.849762],[25.492979,102.849998],[25.49276,102.850098],[25.4921,102.850159],[25.49176,102.850311],[25.491449,102.850578],[25.491261,102.850861],[25.49118,102.851227],[25.491199,102.851608],[25.491501,102.853897],[25.491631,102.854309],[25.492001,102.854851],[25.492149,102.854958],[25.492611,102.855202],[25.493151,102.855362],[25.49333,102.855461],[25.49346,102.855598],[25.493629,102.855713],[25.49371,102.855827],[25.493759,102.856033],[25.49371,102.856232],[25.49328,102.857147],[25.493151,102.857277],[25.49301,102.857353],[25.492701,102.857353],[25.49131,102.857033],[25.49065,102.856781],[25.490499,102.856781],[25.49036,102.85688],[25.49025,102.857033],[25.49,102.857529],[25.489611,102.858009],[25.48958,102.8582],[25.489651,102.858528],[25.48966,102.858711],[25.48963,102.858963],[25.489429,102.859299],[25.489309,102.859428],[25.488501,102.860626],[25.48835,102.860809],[25.48811,102.861008],[25.4869,102.861458],[25.486309,102.861809],[25.48605,102.862099],[25.485649,102.8629],[25.485399,102.863228],[25.48378,102.864662],[25.48358,102.864731],[25.4834,102.864632],[25.48321,102.864349],[25.48316,102.864159],[25.48311,102.863579],[25.482929,102.863258],[25.482731,102.863152],[25.482559,102.863007],[25.482531,102.862801],[25.48255,102.862549],[25.482599,102.862381],[25.482599,102.862183],[25.48255,102.861961],[25.48246,102.861801],[25.48225,102.861702],[25.4821,102.861763],[25.481661,102.862099],[25.48148,102.862152],[25.48131,102.862099],[25.48101,102.8619],[25.48085,102.861847],[25.4807,102.861847],[25.479509,102.862251],[25.479111,102.862358],[25.478609,102.86235],[25.478559,102.862152],[25.47875,102.861504],[25.478649,102.860329],[25.4786,102.86013],[25.47851,102.859947],[25.478331,102.859802],[25.47753,102.859261],[25.47735,102.859261],[25.477261,102.859413],[25.477261,102.860153],[25.477501,102.860397],[25.477831,102.860603],[25.47805,102.860832],[25.47806,102.861],[25.478029,102.861183],[25.477949,102.861351],[25.47761,102.861801],[25.47753,102.861977],[25.47748,102.862228],[25.47735,102.86261],[25.47736,102.862808],[25.477409,102.862999],[25.47806,102.863533],[25.478251,102.863564],[25.47891,102.863503],[25.47913,102.863411],[25.47933,102.863403],[25.47953,102.863449],[25.47961,102.863663],[25.4795,102.864311],[25.479259,102.864883],[25.47893,102.865448],[25.478809,102.865578],[25.478661,102.865662],[25.47813,102.865753],[25.4769,102.865433],[25.476549,102.86541],[25.47576,102.865562],[25.47558,102.86573],[25.47566,102.865913],[25.4758,102.866051],[25.476049,102.866379],[25.47608,102.866547],[25.476049,102.866707],[25.47596,102.866882],[25.47571,102.867126],[25.4744,102.868561],[25.47431,102.868759],[25.474331,102.868927],[25.4744,102.86911],[25.47456,102.869263],[25.47488,102.869331],[25.47506,102.869476],[25.47513,102.869713],[25.475109,102.869904],[25.47493,102.870232],[25.47411,102.87101],[25.47381,102.871529],[25.47368,102.871658],[25.473551,102.871712],[25.473181,102.871696],[25.473,102.871727],[25.47283,102.871803],[25.472731,102.871948],[25.47266,102.87236],[25.472759,102.87291],[25.4729,102.8731],[25.47308,102.873131],[25.47341,102.873062],[25.473579,102.873062],[25.473749,102.873207],[25.473881,102.873734],[25.47385,102.874153],[25.47378,102.874352],[25.473499,102.874611],[25.4734,102.874748],[25.473249,102.875282],[25.473129,102.875481],[25.473,102.875557],[25.472799,102.875633],[25.47246,102.875664],[25.47233,102.875732],[25.472231,102.875908],[25.47226,102.876083],[25.472349,102.876228],[25.472509,102.876381],[25.47296,102.87661],[25.47303,102.876762],[25.473,102.876953],[25.47278,102.87735],[25.472811,102.877548],[25.47291,102.877747],[25.473249,102.878059],[25.47333,102.878258],[25.473351,102.878433],[25.473301,102.878609],[25.4732,102.878761],[25.47295,102.878998],[25.47263,102.879112],[25.472281,102.879128],[25.471979,102.879333],[25.471901,102.879501],[25.471861,102.879677],[25.471951,102.879913],[25.47208,102.880051],[25.472361,102.880257],[25.47258,102.8806],[25.472731,102.880707],[25.473961,102.881401],[25.47415,102.881332],[25.474279,102.881203],[25.47476,102.880508],[25.474899,102.880402],[25.4751,102.880333],[25.475281,102.880432],[25.475349,102.880653],[25.47525,102.881012],[25.474911,102.881432],[25.47423,102.881828],[25.473909,102.882057],[25.473749,102.882133],[25.47356,102.882149],[25.47341,102.882103],[25.471951,102.881058],[25.47163,102.880852],[25.47106,102.880859],[25.470329,102.881081],[25.470011,102.881081],[25.46986,102.881012],[25.469761,102.880852],[25.469761,102.880661],[25.469931,102.88031],[25.47015,102.879349],[25.47028,102.879181],[25.470631,102.879051],[25.470831,102.878906],[25.47093,102.8787],[25.470949,102.878532],[25.470751,102.877808],[25.470659,102.877632],[25.47053,102.87751],[25.469311,102.876862],[25.46911,102.876801],[25.46891,102.876778],[25.46871,102.876831],[25.468081,102.877312],[25.467911,102.877861],[25.46788,102.878082],[25.467779,102.87825],[25.466949,102.879158],[25.466749,102.879227],[25.466579,102.87925],[25.46641,102.879211],[25.466129,102.87896],[25.46583,102.878448],[25.4657,102.878326],[25.465549,102.878258],[25.465401,102.87825],[25.46493,102.878311],[25.46476,102.87825],[25.464649,102.878113],[25.4646,102.87793],[25.4646,102.877731],[25.464531,102.87735],[25.464411,102.877251],[25.46426,102.877182],[25.46298,102.877258],[25.462259,102.876953],[25.461411,102.876801],[25.46125,102.87661],[25.461229,102.87645],[25.461309,102.876297],[25.46216,102.875549],[25.462311,102.875381],[25.462811,102.874962],[25.46335,102.874832],[25.463511,102.874763],[25.463631,102.874657],[25.46373,102.874512],[25.46385,102.87413],[25.46406,102.873802],[25.464211,102.873779],[25.46493,102.873901],[25.465111,102.873863],[25.465231,102.873749],[25.4653,102.87355],[25.46533,102.873352],[25.4652,102.873161],[25.464729,102.873001],[25.464581,102.87291],[25.46446,102.87278],[25.46406,102.872147],[25.463909,102.872002],[25.46356,102.87178],[25.462851,102.871513],[25.4627,102.871407],[25.46258,102.871277],[25.462379,102.870979],[25.461849,102.870407],[25.46151,102.870262],[25.4608,102.870033],[25.460461,102.869881],[25.460329,102.869759],[25.45993,102.869049],[25.45923,102.868309],[25.4587,102.868134],[25.45853,102.868027],[25.458401,102.867897],[25.45816,102.867561],[25.45788,102.866852],[25.457781,102.866699],[25.4575,102.866402],[25.457411,102.866226],[25.457399,102.866051],[25.457451,102.865463],[25.45743,102.864883],[25.457199,102.864357],[25.4571,102.863602],[25.45698,102.863449],[25.45653,102.863258],[25.456181,102.863258],[25.45583,102.863129],[25.455709,102.862984],[25.455629,102.862801],[25.45566,102.86261],[25.455851,102.862129],[25.455851,102.861954],[25.455759,102.861763],[25.455231,102.86145],[25.454981,102.861061],[25.454651,102.86071],[25.454359,102.860558],[25.45381,102.86013],[25.453501,102.859932],[25.452881,102.859734],[25.45211,102.859901],[25.45195,102.859978],[25.45178,102.860107],[25.45166,102.86026],[25.45155,102.860611],[25.4515,102.861214],[25.45145,102.861382],[25.451361,102.861526],[25.451031,102.861748],[25.450661,102.861877],[25.44981,102.862411],[25.44965,102.862556],[25.44873,102.863228],[25.447849,102.863831],[25.44751,102.863998],[25.44698,102.864159],[25.44636,102.864182],[25.44566,102.864281],[25.445311,102.86425],[25.44516,102.864159],[25.44491,102.863899],[25.44475,102.863808],[25.444401,102.863762],[25.44418,102.863808],[25.44401,102.863899],[25.44385,102.864029],[25.44346,102.864449],[25.44326,102.864563],[25.44306,102.864609],[25.44265,102.864632],[25.44243,102.864609],[25.44228,102.864563],[25.441481,102.864502],[25.441059,102.864502],[25.440861,102.864548],[25.440359,102.864807],[25.440201,102.864799],[25.440029,102.864708],[25.439581,102.864227],[25.43918,102.863983],[25.438959,102.86393],[25.438749,102.863953],[25.43853,102.864014],[25.43811,102.864197],[25.437929,102.86425],[25.4377,102.864258],[25.43751,102.864357],[25.437229,102.864754],[25.436661,102.866081],[25.43648,102.86618],[25.4363,102.86618],[25.436131,102.866081],[25.436029,102.865898],[25.435961,102.865677],[25.43586,102.865013],[25.435961,102.864311],[25.435949,102.863708],[25.436001,102.86351],[25.436279,102.862808],[25.436279,102.862633],[25.43618,102.862511],[25.436029,102.862427],[25.435881,102.862396],[25.43536,102.862381],[25.43516,102.862297],[25.435011,102.86216],[25.43471,102.861603],[25.434561,102.861427],[25.433929,102.861099],[25.43343,102.860611],[25.43306,102.860382],[25.43128,102.859863],[25.430349,102.859657],[25.43,102.85968],[25.429359,102.859863],[25.42898,102.859833],[25.4284,102.859848],[25.428209,102.859909],[25.42803,102.860031],[25.427879,102.860184],[25.427759,102.860359],[25.427731,102.86058],[25.427759,102.860802],[25.42828,102.862396],[25.42823,102.862579],[25.428101,102.862701],[25.42786,102.862709],[25.42775,102.862633],[25.427629,102.86248],[25.427481,102.862106],[25.427361,102.861931],[25.427151,102.861351],[25.427059,102.861183],[25.426809,102.860878],[25.426611,102.860558],[25.426359,102.860352],[25.4258,102.859497],[25.42568,102.859001],[25.425659,102.858482],[25.4256,102.858261],[25.425501,102.858101],[25.42535,102.857964],[25.42518,102.857857],[25.424311,102.857552],[25.42363,102.85733],[25.423401,102.8573],[25.423161,102.857307],[25.422029,102.857483],[25.42161,102.857384],[25.42083,102.857002],[25.420059,102.856499],[25.419701,102.856201],[25.4195,102.856079],[25.419081,102.855957],[25.41791,102.855911],[25.41675,102.855782],[25.416531,102.855698],[25.416349,102.855583],[25.41605,102.855278],[25.41556,102.854599],[25.41531,102.853363],[25.41511,102.852951],[25.414961,102.852783],[25.414631,102.852531],[25.413759,102.85218],[25.413309,102.851929],[25.41258,102.851334],[25.412251,102.850998],[25.411699,102.850212],[25.41028,102.848152],[25.409849,102.847504],[25.409679,102.847298],[25.409401,102.846863],[25.4091,102.846481],[25.408279,102.84568],[25.40801,102.845253],[25.407801,102.84481],[25.40765,102.84465],[25.40731,102.844383],[25.4069,102.844254],[25.406731,102.844162],[25.406561,102.844002],[25.40645,102.843811],[25.406099,102.842812],[25.40543,102.841782],[25.40526,102.841614],[25.4046,102.84108],[25.4042,102.841011],[25.404011,102.841026],[25.403851,102.840958],[25.403749,102.840828],[25.4037,102.84063],[25.403629,102.839958],[25.403549,102.839752],[25.403231,102.839432],[25.403049,102.839333],[25.402849,102.839302],[25.402651,102.83931],[25.40205,102.8395],[25.401831,102.839478],[25.401649,102.839378],[25.401461,102.839211],[25.40118,102.838852],[25.400949,102.838432],[25.400551,102.83786],[25.40011,102.83741],[25.399799,102.837196],[25.399509,102.837151],[25.399111,102.837181],[25.39893,102.83725],[25.3983,102.83741],[25.3981,102.83741],[25.397079,102.837151],[25.39666,102.837158],[25.396259,102.83725],[25.395309,102.837646],[25.394609,102.838028],[25.394279,102.838058],[25.39415,102.838013],[25.39385,102.837807],[25.39315,102.837379],[25.39286,102.837112],[25.392679,102.836731],[25.39233,102.836159],[25.392151,102.835747],[25.39205,102.835327],[25.391781,102.834534],[25.3915,102.83416],[25.388599,102.83271],[25.38818,102.832428],[25.387711,102.831909],[25.38728,102.830551],[25.38706,102.830101],[25.386909,102.829613],[25.386909,102.829399],[25.38703,102.828911],[25.38703,102.828697],[25.38698,102.828499],[25.38686,102.828346],[25.386101,102.827682],[25.3855,102.826782],[25.38496,102.825996],[25.38435,102.824959],[25.384211,102.824753],[25.38353,102.823349],[25.38341,102.823128],[25.38328,102.823029],[25.38295,102.822678],[25.382799,102.822433],[25.38241,102.821632],[25.38208,102.821159],[25.38188,102.820961],[25.381451,102.82061],[25.3806,102.82],[25.380381,102.819878],[25.37966,102.819252],[25.37941,102.81913],[25.378929,102.819061],[25.37793,102.81913],[25.37746,102.81926],[25.3766,102.81971],[25.375759,102.820084],[25.375549,102.820213],[25.375311,102.820297],[25.37466,102.820213],[25.373779,102.819809],[25.373329,102.819809],[25.371929,102.820152],[25.371679,102.820259],[25.37105,102.820633],[25.370449,102.82106],[25.369749,102.8218],[25.368879,102.822632],[25.368311,102.82296],[25.368111,102.823013],[25.36688,102.823463],[25.36648,102.823509],[25.365629,102.823448],[25.365499,102.823311],[25.365379,102.823112],[25.365179,102.822479],[25.36491,102.8218],[25.36458,102.820801],[25.36446,102.820549],[25.36393,102.819061],[25.3638,102.818878],[25.363649,102.818581],[25.36335,102.817749],[25.36265,102.816528],[25.36178,102.814552],[25.361549,102.813408],[25.36161,102.81295],[25.361879,102.811958],[25.36203,102.811501],[25.362061,102.811028],[25.3619,102.809761],[25.3619,102.809196],[25.36198,102.808327],[25.362181,102.805733],[25.36215,102.805511],[25.36198,102.805099],[25.36161,102.804459],[25.36153,102.804001],[25.361549,102.803726],[25.361429,102.803261],[25.3612,102.802811],[25.36083,102.801811],[25.36063,102.800056],[25.360531,102.79985],[25.36006,102.799309],[25.35881,102.798058],[25.35746,102.795761],[25.357,102.795113],[25.356331,102.79451],[25.35531,102.793701],[25.35508,102.793411],[25.355009,102.793198],[25.355009,102.792198],[25.35533,102.790901],[25.35535,102.790398],[25.355129,102.78878],[25.355181,102.786247],[25.35511,102.785751],[25.3549,102.785332],[25.354759,102.785133],[25.354259,102.78418],[25.35335,102.782707],[25.353201,102.782562],[25.35285,102.782303],[25.352551,102.781883],[25.352051,102.781357],[25.35166,102.781197],[25.35148,102.781181],[25.35108,102.78125],[25.350901,102.781258],[25.3507,102.781197],[25.35051,102.781097],[25.350361,102.78093],[25.3501,102.780533],[25.349751,102.780312],[25.349609,102.780159],[25.349449,102.779877],[25.3491,102.779411],[25.348579,102.779114],[25.34816,102.77903],[25.347561,102.779129],[25.34738,102.779251],[25.347231,102.779411],[25.347,102.779846],[25.346861,102.780006],[25.34668,102.780128],[25.345711,102.78035],[25.344999,102.780563],[25.3444,102.780884],[25.343981,102.781029],[25.3438,102.781128],[25.343451,102.781433],[25.342911,102.782227],[25.342751,102.782303],[25.34256,102.782303],[25.342381,102.782249],[25.341379,102.781799],[25.340401,102.780952],[25.339411,102.779709],[25.33926,102.779549],[25.339149,102.779358],[25.3389,102.779053],[25.338699,102.7789],[25.338511,102.778847],[25.33835,102.778862],[25.33798,102.77906],[25.337681,102.779182],[25.33713,102.779282],[25.33671,102.779228],[25.335751,102.778976],[25.334999,102.778748],[25.33411,102.778229],[25.33375,102.778152],[25.3332,102.778198],[25.332109,102.778458],[25.33078,102.77903],[25.329651,102.779747],[25.329109,102.780182],[25.328581,102.78038],[25.328159,102.780403],[25.32778,102.780296],[25.327459,102.780029],[25.327101,102.779297],[25.3269,102.778999],[25.326759,102.778877],[25.32641,102.778709],[25.32626,102.778709],[25.32546,102.778847],[25.32505,102.778862],[25.32481,102.778809],[25.324249,102.778603],[25.32403,102.77858],[25.32296,102.778801],[25.32276,102.778801],[25.32201,102.778458],[25.320801,102.778099],[25.3204,102.777901],[25.31953,102.777107],[25.31885,102.7761],[25.318029,102.775299],[25.3179,102.775131],[25.317801,102.774902],[25.317751,102.774658],[25.317711,102.774178],[25.317579,102.773697],[25.31743,102.773514],[25.317101,102.773201],[25.31636,102.772697],[25.31525,102.771652],[25.314301,102.770958],[25.313709,102.770607],[25.313061,102.770683],[25.312851,102.77066],[25.311979,102.770409],[25.311359,102.770302],[25.30946,102.769798],[25.30933,102.769707],[25.30883,102.769157],[25.30838,102.768501],[25.308109,102.767357],[25.308149,102.765984],[25.30813,102.76503],[25.307949,102.764412],[25.307699,102.764076],[25.30756,102.763977],[25.306709,102.762749],[25.3062,102.762283],[25.305599,102.761902],[25.30525,102.761581],[25.305149,102.761383],[25.30501,102.76091],[25.30493,102.760429],[25.3048,102.760231],[25.304609,102.760078],[25.303801,102.759712],[25.3027,102.759331],[25.30253,102.759209],[25.30241,102.759048],[25.30233,102.758827],[25.30221,102.758148],[25.3022,102.757431],[25.30213,102.75721],[25.301979,102.757057],[25.301611,102.756882],[25.301479,102.756729],[25.301081,102.755898],[25.300461,102.754181],[25.3002,102.753799],[25.300011,102.753632],[25.299101,102.752998],[25.298161,102.752251],[25.297831,102.75193],[25.29756,102.751534],[25.296909,102.750809],[25.29673,102.750702],[25.29631,102.750633],[25.295959,102.750458],[25.295811,102.750313],[25.295549,102.749947],[25.29483,102.749382],[25.29401,102.749008],[25.293579,102.748901],[25.29213,102.748711],[25.2918,102.748528],[25.289631,102.747597],[25.288031,102.7472],[25.286249,102.746384],[25.285561,102.746201],[25.28441,102.745758],[25.28348,102.745483],[25.282261,102.745361],[25.282009,102.7453],[25.281601,102.745148],[25.28043,102.744957],[25.279409,102.745033],[25.27891,102.744911],[25.27791,102.744728],[25.2775,102.744583],[25.277309,102.744453],[25.276699,102.743713],[25.276501,102.743584],[25.276331,102.74353],[25.27615,102.743553],[25.27533,102.743752],[25.27416,102.74411],[25.27375,102.744377],[25.27355,102.744476],[25.273331,102.74453],[25.272881,102.744461],[25.27243,102.744431],[25.27141,102.744263],[25.27063,102.744202],[25.26993,102.7444],[25.26943,102.744408],[25.268709,102.744331],[25.26803,102.744263],[25.26738,102.744247],[25.267179,102.744308],[25.26638,102.744659],[25.266159,102.744682],[25.26573,102.744553],[25.2649,102.74408],[25.264681,102.744034],[25.2642,102.74398],[25.263729,102.743797],[25.26333,102.74353],[25.262911,102.742996],[25.26273,102.742607],[25.26263,102.742012],[25.26255,102.741852],[25.26235,102.74176],[25.26218,102.741882],[25.261999,102.74221],[25.261829,102.74231],[25.2614,102.742279],[25.261181,102.742302],[25.260981,102.742363],[25.260799,102.742477],[25.260611,102.742554],[25.26041,102.742531],[25.260031,102.742348],[25.25985,102.742203],[25.25935,102.741982],[25.25881,102.741859],[25.25831,102.741814],[25.25808,102.74173],[25.257111,102.741249],[25.25668,102.740982],[25.256451,102.740898],[25.256201,102.740883],[25.25573,102.740952],[25.25548,102.740959],[25.254749,102.741096],[25.254511,102.741096],[25.253901,102.740807],[25.25366,102.740761],[25.252911,102.740898],[25.252159,102.740959],[25.25168,102.740883],[25.251129,102.740631],[25.250759,102.740601],[25.250111,102.740707],[25.2498,102.740646],[25.249359,102.740402],[25.249201,102.740356],[25.24901,102.740356],[25.24855,102.740601],[25.24818,102.740631],[25.24753,102.740608],[25.24736,102.740646],[25.247129,102.740578],[25.246811,102.740402],[25.24625,102.739906],[25.24605,102.739777],[25.245609,102.739662],[25.24523,102.739449],[25.245001,102.739197],[25.244551,102.7388],[25.24441,102.738731],[25.2442,102.738747],[25.243811,102.738899],[25.24361,102.738876],[25.2435,102.738777],[25.243299,102.73851],[25.24305,102.738281],[25.24271,102.738129],[25.24238,102.73806],[25.241579,102.738113],[25.241211,102.738159],[25.24103,102.738129],[25.2409,102.738029],[25.24078,102.737862],[25.24066,102.737747],[25.240179,102.737511],[25.240009,102.73748],[25.239229,102.73745],[25.238729,102.737282],[25.23835,102.737251],[25.237881,102.737297],[25.237221,102.737343],[25.235609,102.736977],[25.234329,102.736778],[25.2339,102.736633],[25.233561,102.73645],[25.23329,102.736298],[25.23288,102.736214],[25.23233,102.73616],[25.230209,102.736107],[25.229759,102.736511],[25.229549,102.736862],[25.22921,102.737083],[25.22872,102.737267],[25.228609,102.737549],[25.2286,102.737953],[25.228479,102.738281],[25.2283,102.738564],[25.2281,102.738861],[25.228081,102.739014],[25.22818,102.739159],[25.228359,102.739212],[25.22863,102.739128],[25.229,102.738701],[25.229481,102.738197],[25.229851,102.738068],[25.230709,102.738083],[25.231279,102.738281],[25.231649,102.738281],[25.231859,102.738297],[25.2321,102.738564],[25.23221,102.738762],[25.23258,102.738907],[25.232929,102.738853],[25.233179,102.739014],[25.23344,102.739212],[25.233629,102.739616],[25.23385,102.739777],[25.23403,102.73983],[25.23436,102.739761],[25.234619,102.739822],[25.235109,102.740349],[25.23571,102.740593],[25.23596,102.740913],[25.235979,102.74115],[25.235941,102.74144],[25.23563,102.741623],[25.235201,102.741631],[25.23461,102.741753],[25.234079,102.742081],[25.233801,102.742172],[25.233379,102.742126],[25.23267,102.742027],[25.2323,102.742172],[25.232019,102.742378],[25.23185,102.742706],[25.231701,102.74308],[25.231529,102.743401],[25.231359,102.743507],[25.2311,102.743477],[25.230749,102.74321],[25.230709,102.742867],[25.230579,102.742317],[25.230129,102.742027],[25.229601,102.741783],[25.22872,102.741814],[25.227989,102.741661],[25.227409,102.741661],[25.22665,102.741447],[25.226259,102.741127],[25.225981,102.74073],[25.225731,102.740448],[25.225559,102.740402],[25.22541,102.74041],[25.22529,102.740593],[25.225189,102.74073],[25.224751,102.741013],[25.22418,102.741211],[25.223949,102.741653],[25.22373,102.741837],[25.22183,102.742447],[25.219999,102.742653],[25.21899,102.742851],[25.21788,102.742699],[25.2171,102.742561],[25.215811,102.742683],[25.214781,102.742683],[25.21406,102.742882],[25.21328,102.742981],[25.21253,102.742828],[25.212231,102.743088],[25.211861,102.743858],[25.21159,102.744217],[25.211161,102.744347],[25.211029,102.744209],[25.210899,102.743446],[25.210871,102.742729],[25.21055,102.742264],[25.21018,102.74202],[25.20965,102.741982],[25.20941,102.742279],[25.209459,102.742699],[25.209351,102.742912],[25.20911,102.742943],[25.207479,102.742851],[25.205999,102.742462],[25.20532,102.742371],[25.204309,102.741959],[25.20381,102.741859],[25.203341,102.741959],[25.202749,102.741966],[25.20096,102.741631],[25.19952,102.741211],[25.19906,102.74118],[25.19445,102.741096],[25.192699,102.740768],[25.192181,102.7407],[25.191839,102.740784],[25.19108,102.741158],[25.19055,102.741158],[25.189501,102.741226],[25.18906,102.741074],[25.18828,102.740822],[25.187519,102.740784],[25.186279,102.740784],[25.185511,102.740677],[25.18507,102.740356],[25.184259,102.739868],[25.182449,102.73896],[25.180901,102.738281],[25.17981,102.737999],[25.17901,102.737846],[25.178101,102.737534],[25.177349,102.737221],[25.17658,102.736443],[25.176279,102.736061],[25.17568,102.73568],[25.17518,102.735573],[25.174761,102.735382],[25.17448,102.73513],[25.174141,102.734596],[25.174101,102.734512],[25.174061,102.734062],[25.17408,102.733528],[25.17395,102.733047],[25.173759,102.732803],[25.173281,102.732712],[25.171709,102.733147],[25.17136,102.733078],[25.170719,102.732887],[25.17041,102.73288],[25.17008,102.733032],[25.16971,102.733414],[25.169359,102.733856],[25.169081,102.734032],[25.16876,102.734001],[25.167959,102.733429],[25.166889,102.73288],[25.16662,102.732826],[25.166071,102.732826],[25.165831,102.73275],[25.16568,102.73243],[25.165621,102.732117],[25.165449,102.731796],[25.165211,102.731827],[25.16507,102.732018],[25.16501,102.732109],[25.16511,102.732559],[25.1654,102.733002],[25.16581,102.733147],[25.16637,102.733238],[25.1667,102.733253],[25.166901,102.733482],[25.16687,102.73362],[25.16671,102.733849],[25.166439,102.733757],[25.165951,102.73349],[25.165461,102.733429],[25.165001,102.733307],[25.16473,102.733078],[25.164579,102.73278],[25.164591,102.732483],[25.164579,102.732147],[25.164551,102.731758],[25.16436,102.731583],[25.16415,102.731651],[25.16408,102.731979],[25.1642,102.732529],[25.16419,102.732811],[25.164301,102.733307],[25.16448,102.733551],[25.164829,102.733658],[25.16518,102.733711],[25.165421,102.733833],[25.16543,102.734154],[25.1653,102.734283],[25.165001,102.734253],[25.16433,102.73391],[25.16366,102.733597],[25.1635,102.73317],[25.16338,102.732651],[25.163231,102.732201],[25.16297,102.731949],[25.162689,102.73188],[25.162411,102.732079],[25.16213,102.73278],[25.16194,102.733513],[25.161711,102.733711],[25.160521,102.734306],[25.1602,102.734238],[25.15971,102.733849],[25.15906,102.733299],[25.158609,102.73307],[25.158409,102.733078],[25.158159,102.732979],[25.157909,102.732857],[25.157761,102.732536],[25.157579,102.732353],[25.157471,102.732361],[25.157301,102.732452],[25.15723,102.732613],[25.1572,102.732948],[25.15723,102.733299],[25.157459,102.733528],[25.15806,102.733688],[25.15843,102.733833],[25.158751,102.734261],[25.15893,102.734871],[25.15921,102.735603],[25.15962,102.735992],[25.160009,102.736122],[25.160339,102.736259],[25.1609,102.736732],[25.161659,102.737053],[25.16231,102.737183],[25.162661,102.73716],[25.162769,102.737213],[25.162979,102.73735],[25.163139,102.73777],[25.1632,102.737846],[25.1633,102.738113],[25.16328,102.73838],[25.163059,102.738678],[25.162661,102.739052],[25.16227,102.739311],[25.161751,102.739433],[25.16147,102.739403],[25.16116,102.739403],[25.161051,102.739372],[25.160629,102.73925],[25.160061,102.739029],[25.15967,102.738876],[25.15741,102.738419],[25.156481,102.738129],[25.15554,102.737587],[25.153151,102.736588],[25.150579,102.735527],[25.149429,102.735031],[25.148701,102.734787],[25.14473,102.733528],[25.143021,102.73275],[25.141371,102.732208],[25.136999,102.730568],[25.130501,102.728256],[25.12912,102.727676],[25.12747,102.726837],[25.12598,102.725861],[25.12476,102.72522],[25.123051,102.724701],[25.121719,102.72422],[25.119909,102.72393],[25.118311,102.723679],[25.117149,102.723381],[25.11606,102.723129],[25.11553,102.723099],[25.115311,102.723259],[25.11496,102.724297],[25.114599,102.725632],[25.114111,102.72641],[25.11356,102.727448],[25.1129,102.728729],[25.108379,102.726807],[25.10449,102.725151],[25.101049,102.723686],[25.10005,102.72654],[25.09898,102.729637],[25.09713,102.73497],[25.096161,102.737579],[25.09581,102.737534],[25.09334,102.736557],[25.09148,102.735909],[25.09123,102.735817],[25.0889,102.73497],[25.08815,102.734673],[25.087391,102.734383],[25.085621,102.732613],[25.0839,102.730911],[25.081699,102.733963],[25.08021,102.736153],[25.07494,102.743919],[25.074869,102.744019],[25.071899,102.74762],[25.07069,102.749336],[25.07015,102.751411],[25.067841,102.750389],[25.066681,102.749413],[25.065109,102.747681],[25.063669,102.746552],[25.06233,102.745644],[25.060631,102.744438],[25.060289,102.744202],[25.057619,102.742691],[25.057409,102.742462],[25.05604,102.742752],[25.051701,102.742897],[25.049891,102.742989],[25.04567,102.743103],[25.04431,102.743134],[25.0413,102.743263],[25.03709,102.743469],[25.035601,102.743599],[25.033911,102.743767],[25.03154,102.74382],[25.030161,102.74353],[25.02953,102.743271],[25.02825,102.742767],[25.026091,102.741898],[25.025089,102.741814],[25.0238,102.74205],[25.0231,102.742233],[25.022341,102.742371],[25.02179,102.742477],[25.021219,102.742592],[25.01985,102.742943],[25.01964,102.743042],[25.019501,102.743187],[25.019449,102.743347],[25.01948,102.743477],[25.01955,102.74366],[25.0198,102.74395],[25.01992,102.744102],[25.02,102.744362],[25.020029,102.744621],[25.01989,102.745796],[25.01976,102.746368],[25.01919,102.749313],[25.01759,102.755577],[25.017191,102.756592],[25.01643,102.757927],[25.01516,102.759399],[25.01408,102.760368],[25.00745,102.764168],[25.005659,102.76519],[25.004789,102.765747],[25.004169,102.766327],[25.00341,102.767403],[25.00296,102.768417],[25.00198,102.770973],[25.00152,102.771751],[25.0009,102.772476],[24.9932,102.778389],[24.992041,102.779327],[24.99118,102.779999],[24.990601,102.780243],[24.98991,102.780342],[24.98925,102.780243],[24.98415,102.778168],[24.982491,102.777603],[24.98114,102.777588],[24.978029,102.777863],[24.973841,102.778633],[24.973101,102.778778],[24.972031,102.779068],[24.971201,102.779381],[24.96909,102.780296],[24.967541,102.781143],[24.966209,102.781967],[24.957451,102.787659],[24.956369,102.788292],[24.955509,102.788712],[24.95487,102.788963],[24.95372,102.78936],[24.951731,102.789703],[24.95056,102.78978],[24.93424,102.789619],[24.926109,102.788887],[24.924629,102.788948],[24.923161,102.789169],[24.92104,102.789757],[24.919081,102.79068],[24.917391,102.791763],[24.904909,102.800919],[24.90271,102.802032],[24.900499,102.802696],[24.898359,102.802963],[24.89703,102.80323],[24.895639,102.803741],[24.894461,102.804321],[24.89431,102.804398],[24.89344,102.804947],[24.89315,102.805153],[24.891251,102.806808],[24.88316,102.814201],[24.880819,102.815666],[24.878929,102.816467],[24.876221,102.817123],[24.874001,102.817291],[24.84852,102.817581],[24.84655,102.81736],[24.84318,102.816437],[24.839991,102.814957],[24.830021,102.808449],[24.828449,102.807693],[24.82411,102.806129],[24.822969,102.805481],[24.819901,102.802963],[24.817209,102.801666],[24.81572,102.801048],[24.814489,102.800247],[24.81016,102.795677],[24.8069,102.793289],[24.8011,102.787453],[24.800039,102.78669],[24.79859,102.785896],[24.79657,102.785118],[24.795799,102.784828],[24.785509,102.780983],[24.784889,102.780609],[24.784161,102.780037],[24.783541,102.779297],[24.78186,102.776398],[24.779381,102.77179],[24.77845,102.770477],[24.77702,102.76889],[24.776011,102.768021],[24.77453,102.766991],[24.77227,102.765877],[24.770599,102.765327],[24.76366,102.764069],[24.734501,102.754677],[24.732719,102.753777],[24.73086,102.752457],[24.72957,102.751198],[24.709591,102.725899],[24.69681,102.713463],[24.696119,102.712807],[24.694839,102.710548],[24.69313,102.706947],[24.69272,102.706306],[24.69241,102.705963],[24.691811,102.705513],[24.69121,102.70517],[24.68935,102.704407],[24.688761,102.704002],[24.68825,102.703491],[24.68782,102.702888],[24.68749,102.70192],[24.685551,102.695763],[24.678829,102.681763],[24.67807,102.680649],[24.67717,102.67971],[24.67095,102.675392],[24.670059,102.674568],[24.669491,102.67379],[24.668909,102.672684],[24.668631,102.671654],[24.664829,102.653343],[24.66445,102.65229],[24.66386,102.651253],[24.66073,102.647186],[24.65988,102.646393],[24.6506,102.638947],[24.643311,102.630211],[24.64097,102.628479],[24.627899,102.623543],[24.627211,102.623138],[24.626381,102.622452],[24.62466,102.620277],[24.623949,102.619698],[24.617371,102.616913],[24.61204,102.614761],[24.605829,102.610237],[24.601089,102.607674],[24.599501,102.606468],[24.597919,102.604881],[24.58987,102.595268],[24.579691,102.585068],[24.57741,102.583359],[24.57579,102.58242],[24.56934,102.579987],[24.55953,102.577469],[24.555241,102.575607],[24.554131,102.57534],[24.549549,102.575256],[24.54882,102.575157],[24.54788,102.574913],[24.542219,102.572319],[24.541121,102.571609],[24.54015,102.570663],[24.53915,102.569366],[24.53838,102.568626],[24.537069,102.567719],[24.53651,102.567162],[24.536051,102.566528],[24.53557,102.565552],[24.535021,102.56356],[24.5345,102.56234],[24.53392,102.56147],[24.533079,102.560638],[24.53204,102.55999],[24.53105,102.559647],[24.52458,102.558792],[24.523661,102.558517],[24.522989,102.558189],[24.52256,102.557877],[24.519461,102.555054],[24.51862,102.554459],[24.517719,102.554039],[24.516569,102.553757],[24.515289,102.553772],[24.514521,102.55397],[24.50947,102.556023],[24.50729,102.556717],[24.50609,102.557312],[24.500919,102.560722],[24.5002,102.561043],[24.494989,102.561996],[24.493891,102.562347],[24.49102,102.563553],[24.489889,102.563797],[24.488701,102.563843],[24.487949,102.563721],[24.487209,102.563522],[24.485359,102.562782],[24.484381,102.562553],[24.481859,102.562187],[24.481131,102.561974],[24.48068,102.561729],[24.47967,102.560867],[24.47547,102.556763],[24.471451,102.554123],[24.470181,102.55291],[24.468599,102.550987],[24.467661,102.550163],[24.466789,102.549622],[24.466089,102.549316],[24.46512,102.549049],[24.41419,102.541649],[24.40333,102.539558],[24.399929,102.53891],[24.398029,102.538544],[24.391729,102.537331],[24.390289,102.537117],[24.37652,102.535439],[24.37458,102.534958],[24.370319,102.533524],[24.359261,102.530693],[24.3577,102.530441],[24.35693,102.530312],[24.355539,102.53009],[24.353239,102.529762],[24.350981,102.529442],[24.349449,102.529114],[24.34881,102.528976],[24.33872,102.52536],[24.335779,102.523987],[24.331289,102.521278],[24.328819,102.519768],[24.32793,102.519234],[24.324511,102.517273],[24.32218,102.516609],[24.317949,102.515617],[24.316759,102.515068],[24.31604,102.514557],[24.315069,102.513573],[24.3137,102.511871],[24.312799,102.511147],[24.31176,102.510597],[24.30479,102.508911],[24.3043,102.508743],[24.30143,102.507187],[24.291599,102.50116],[24.290791,102.500458],[24.29007,102.499619],[24.28937,102.498367],[24.288759,102.497108],[24.288271,102.496353],[24.2878,102.495827],[24.28723,102.495407],[24.286591,102.495087],[24.285919,102.494888],[24.28525,102.494797],[24.282829,102.494797],[24.282221,102.494743],[24.28142,102.494476],[24.280569,102.493973],[24.2794,102.492844],[24.276489,102.4879],[24.27578,102.487053],[24.274691,102.486198],[24.273609,102.485657],[24.272449,102.485382],[24.26977,102.485046],[24.268471,102.48465],[24.26585,102.483528],[24.26474,102.483238],[24.26259,102.483109],[24.25843,102.483162],[24.25771,102.483017],[24.25713,102.482857],[24.25701,102.482826],[24.25679,102.48275],[24.256611,102.482689],[24.256069,102.482513],[24.25515,102.482117],[24.253349,102.48143],[24.25172,102.480797],[24.250879,102.480476],[24.25012,102.480263],[24.248831,102.480049],[24.247219,102.480019],[24.23737,102.481071],[24.235371,102.480927],[24.224079,102.478661],[24.212351,102.474663],[24.210661,102.473763],[24.20948,102.472878],[24.20829,102.471649],[24.204809,102.466621],[24.203409,102.46524],[24.20174,102.464043],[24.196659,102.461678],[24.19556,102.460876],[24.194941,102.460243],[24.19416,102.459106],[24.193331,102.457581],[24.191719,102.455399],[24.191389,102.454742],[24.191139,102.454033],[24.19101,102.45327],[24.19099,102.452591],[24.19091,102.45002],[24.190901,102.449692],[24.19076,102.444458],[24.19109,102.441818],[24.191771,102.437843],[24.19174,102.436836],[24.191641,102.436348],[24.19136,102.435623],[24.191099,102.435181],[24.18651,102.43042],[24.185989,102.429581],[24.185711,102.428879],[24.184311,102.419518],[24.183969,102.418533],[24.183371,102.417389],[24.182409,102.415947],[24.181881,102.414803],[24.18154,102.413551],[24.1812,102.403793],[24.180929,102.402191],[24.18042,102.400688],[24.177509,102.395042],[24.176331,102.392754],[24.17631,102.392723],[24.176149,102.392403],[24.17314,102.386574],[24.172701,102.385933],[24.170879,102.384216],[24.17062,102.383812],[24.17046,102.383347],[24.170179,102.381378],[24.16997,102.380669],[24.169609,102.380043],[24.169121,102.379478],[24.16855,102.379021],[24.16753,102.378349],[24.167021,102.377808],[24.166389,102.377007],[24.166019,102.376701],[24.165569,102.376472],[24.16416,102.376099],[24.16374,102.3759],[24.163389,102.375603],[24.163139,102.375191],[24.162661,102.374092],[24.162411,102.373703],[24.162251,102.37352],[24.16185,102.373238],[24.161409,102.373077],[24.15999,102.37294],[24.15954,102.372833],[24.159321,102.372726],[24.158939,102.372467],[24.15859,102.372147],[24.158319,102.371773],[24.15811,102.37133],[24.15798,102.37085],[24.157841,102.369583],[24.15766,102.368828],[24.157379,102.368118],[24.15666,102.367088],[24.156179,102.366371],[24.155479,102.364662],[24.15521,102.364029],[24.154329,102.363487],[24.153721,102.363167],[24.152889,102.362442],[24.15229,102.361687],[24.15196,102.361397],[24.15155,102.361153],[24.15045,102.360817],[24.149799,102.360527],[24.149441,102.360222],[24.149151,102.35984],[24.14892,102.359413],[24.14876,102.358917],[24.148399,102.356651],[24.148041,102.355782],[24.14629,102.353394],[24.14595,102.35276],[24.145611,102.35183],[24.14521,102.350128],[24.145029,102.349693],[24.14465,102.349068],[24.14324,102.347618],[24.142731,102.346786],[24.1418,102.344177],[24.14126,102.343384],[24.140659,102.342873],[24.140129,102.342621],[24.13954,102.342499],[24.138929,102.342506],[24.136841,102.342957],[24.1362,102.343002],[24.135571,102.342903],[24.13516,102.342743],[24.132589,102.340973],[24.13216,102.340759],[24.131701,102.340622],[24.130989,102.340523],[24.127661,102.340523],[24.12628,102.340202],[24.124981,102.339577],[24.12085,102.33638],[24.117701,102.334648],[24.11706,102.334412],[24.11635,102.334328],[24.11565,102.334381],[24.114941,102.334572],[24.114281,102.334923],[24.113449,102.33548],[24.11302,102.335693],[24.11256,102.335808],[24.11208,102.335823],[24.11161,102.335716],[24.111179,102.335503],[24.10861,102.333557],[24.106741,102.33268],[24.10528,102.331383],[24.10442,102.330612],[24.102909,102.329628],[24.10244,102.329132],[24.102039,102.328522],[24.101669,102.327477],[24.101049,102.32486],[24.10013,102.319603],[24.09733,102.308762],[24.097191,102.307899],[24.096939,102.306992],[24.09639,102.305817],[24.09561,102.304764],[24.094851,102.304039],[24.093651,102.30307],[24.093321,102.302711],[24.09306,102.302307],[24.092791,102.301651],[24.092609,102.300667],[24.092541,102.29995],[24.092421,102.29953],[24.092239,102.299141],[24.091841,102.298592],[24.09063,102.297256],[24.0902,102.296577],[24.08963,102.295433],[24.08935,102.295059],[24.08901,102.294746],[24.0886,102.294563],[24.088381,102.29451],[24.087959,102.294518],[24.087219,102.29483],[24.08667,102.295097],[24.08625,102.295174],[24.08585,102.295242],[24.082951,102.296356],[24.082621,102.296516],[24.08209,102.296532],[24.0816,102.296417],[24.081181,102.296318],[24.08079,102.296112],[24.08042,102.295807],[24.08012,102.295441],[24.07991,102.295013],[24.07976,102.29454],[24.079679,102.294022],[24.0797,102.293243],[24.0802,102.290543],[24.08024,102.290009],[24.08013,102.28923],[24.079941,102.288757],[24.07933,102.287903],[24.077909,102.28611],[24.0777,102.285744],[24.0776,102.285332],[24.07761,102.284912],[24.077709,102.2845],[24.077909,102.284126],[24.078409,102.283669],[24.078991,102.283257],[24.079321,102.282921],[24.07955,102.282509],[24.07966,102.282051],[24.07967,102.281578],[24.07852,102.277153],[24.07806,102.276161],[24.075491,102.272011],[24.075199,102.271309],[24.0748,102.269821],[24.074591,102.269386],[24.074459,102.269173],[24.073931,102.2686],[24.07037,102.266113],[24.069981,102.265747],[24.06966,102.26532],[24.06941,102.264839],[24.069151,102.264069],[24.06813,102.258057],[24.067631,102.25647],[24.063391,102.248207],[24.063089,102.247742],[24.06238,102.246918],[24.06155,102.246246],[24.059299,102.244904],[24.057791,102.243858],[24.057039,102.243134],[24.05673,102.242722],[24.05632,102.242027],[24.05582,102.240761],[24.054319,102.236038],[24.05357,102.234596],[24.05155,102.231468],[24.050631,102.22953],[24.04875,102.224281],[24.048401,102.223633],[24.04619,102.221077],[24.04599,102.220711],[24.045799,102.220093],[24.045759,102.219177],[24.045759,102.21759],[24.045759,102.217461],[24.04575,102.214523],[24.04575,102.213913],[24.045691,102.207733],[24.045561,102.206467],[24.045349,102.205673],[24.04513,102.205132],[24.04483,102.204391],[24.044189,102.203178],[24.037531,102.195297],[24.036949,102.194763],[24.03628,102.194359],[24.031691,102.192528],[24.03071,102.192322],[24.029181,102.192192],[24.02747,102.192032],[24.026331,102.191757],[24.02446,102.191139],[24.023439,102.190964],[24.014271,102.191002],[24.01329,102.190872],[24.0121,102.190483],[24.0112,102.189987],[24.010401,102.189377],[24.00802,102.186996],[24.007721,102.186577],[24.00737,102.18586],[24.006901,102.18457],[24.00667,102.18409],[24.006371,102.183662],[24.005791,102.183144],[24.005569,102.182983],[24.00429,102.182053],[24.004009,102.181839],[24.00309,102.181152],[24.002621,102.180801],[23.999161,102.178482],[23.99815,102.178101],[23.997219,102.177979],[23.993441,102.17823],[23.991911,102.17807],[23.98851,102.17717],[23.987881,102.177116],[23.98723,102.17717],[23.986589,102.17733],[23.98562,102.177834],[23.98452,102.178513],[23.983761,102.178818],[23.982731,102.178993],[23.981871,102.178902],[23.98102,102.178642],[23.979971,102.178177],[23.979059,102.177948],[23.9765,102.177856],[23.975559,102.177658],[23.97468,102.177238],[23.974079,102.176819],[23.971951,102.174683],[23.97135,102.174232],[23.96685,102.171967],[23.96616,102.171738],[23.965191,102.171669],[23.96447,102.171761],[23.963039,102.172127],[23.962561,102.172188],[23.96209,102.172127],[23.96162,102.171944],[23.96122,102.171661],[23.958651,102.168922],[23.95356,102.16555],[23.953131,102.16507],[23.952921,102.164711],[23.952669,102.163879],[23.95248,102.162537],[23.952339,102.162109],[23.952101,102.161728],[23.95179,102.161423],[23.946501,102.158653],[23.94496,102.157494],[23.942419,102.154846],[23.9419,102.154488],[23.941311,102.154297],[23.94047,102.154228],[23.93947,102.154266],[23.939091,102.154243],[23.93854,102.154083],[23.937599,102.153488],[23.93655,102.152649],[23.935699,102.152184],[23.93387,102.15155],[23.933331,102.151237],[23.932699,102.150703],[23.932409,102.150391],[23.931231,102.148399],[23.93082,102.14798],[23.93018,102.147568],[23.929529,102.147186],[23.92911,102.146828],[23.92877,102.146393],[23.928169,102.145157],[23.92758,102.144363],[23.926809,102.14373],[23.92609,102.143349],[23.91666,102.14122],[23.914061,102.140831],[23.913349,102.140778],[23.908159,102.14093],[23.90766,102.140877],[23.897499,102.139458],[23.89678,102.139381],[23.896061,102.139252],[23.89463,102.13871],[23.89208,102.137512],[23.890499,102.136703],[23.88798,102.134712],[23.887449,102.134132],[23.88703,102.133453],[23.88681,102.132957],[23.886379,102.13176],[23.885281,102.129013],[23.877159,102.123848],[23.876949,102.123734],[23.87628,102.123627],[23.874849,102.12368],[23.874399,102.12365],[23.87398,102.123482],[23.87368,102.123154],[23.873461,102.12278],[23.872881,102.121277],[23.872459,102.120659],[23.87211,102.1203],[23.870911,102.119453],[23.87038,102.118896],[23.87023,102.118698],[23.86998,102.118233],[23.86936,102.116547],[23.86911,102.11615],[23.86895,102.115959],[23.868561,102.115646],[23.86725,102.114952],[23.865561,102.113297],[23.864361,102.11203],[23.86401,102.11145],[23.863859,102.110832],[23.86388,102.110413],[23.864111,102.10981],[23.864361,102.109459],[23.86471,102.109177],[23.86515,102.109001],[23.867279,102.108498],[23.86791,102.108231],[23.868099,102.108109],[23.868401,102.107727],[23.86895,102.106552],[23.869209,102.10611],[23.869551,102.105713],[23.869949,102.105431],[23.870399,102.105209],[23.87126,102.104851],[23.871599,102.104584],[23.871849,102.104279],[23.871929,102.104057],[23.87195,102.103851],[23.87188,102.103378],[23.87175,102.103012],[23.871481,102.102699],[23.871111,102.102448],[23.870911,102.102364],[23.870501,102.102333],[23.87026,102.102379],[23.86981,102.1026],[23.86916,102.102798],[23.86871,102.102829],[23.8685,102.102814],[23.867149,102.102249],[23.86648,102.10183],[23.865879,102.101303],[23.86536,102.100647],[23.86388,102.098213],[23.86368,102.09761],[23.863661,102.097412],[23.8638,102.096764],[23.864031,102.096359],[23.86445,102.095848],[23.864981,102.095001],[23.865299,102.094254],[23.865681,102.093201],[23.86581,102.092934],[23.866131,102.092484],[23.86668,102.091904],[23.867149,102.091263],[23.867399,102.090759],[23.86763,102.089981],[23.867781,102.088951],[23.86775,102.088509],[23.867701,102.088303],[23.867479,102.087929],[23.867149,102.087646],[23.8666,102.087448],[23.8664,102.087448],[23.86618,102.087509],[23.865761,102.087761],[23.86545,102.088081],[23.865259,102.088478],[23.865049,102.0896],[23.864811,102.090233],[23.864599,102.090599],[23.864059,102.091103],[23.861059,102.092583],[23.86046,102.092957],[23.860161,102.093208],[23.85955,102.094032],[23.85935,102.094452],[23.859079,102.09481],[23.85873,102.095154],[23.857849,102.095581],[23.85738,102.095703],[23.857161,102.095711],[23.85676,102.095901],[23.856409,102.096161],[23.85626,102.096313],[23.856159,102.096497],[23.85605,102.096626],[23.85606,102.0989],[23.85601,102.099152],[23.855801,102.099579],[23.855511,102.099983],[23.85516,102.100304],[23.85471,102.100906],[23.854309,102.101929],[23.854,102.102547],[23.853701,102.102913],[23.853161,102.10331],[23.852949,102.103401],[23.85203,102.10363],[23.85128,102.103683],[23.85055,102.1036],[23.84981,102.103409],[23.84853,102.10321],[23.84803,102.103027],[23.847799,102.102913],[23.847401,102.102577],[23.846701,102.101784],[23.84593,102.101196],[23.84486,102.100601],[23.84428,102.100159],[23.843531,102.099258],[23.84318,102.09893],[23.842779,102.098663],[23.841961,102.098312],[23.84136,102.097954],[23.841181,102.097809],[23.84103,102.097633],[23.8407,102.096977],[23.84058,102.096527],[23.8403,102.095161],[23.840151,102.094727],[23.84005,102.094551],[23.83938,102.093979],[23.839199,102.093857],[23.837481,102.093353],[23.83728,102.093262],[23.835831,102.092857],[23.835409,102.092659],[23.835011,102.092377],[23.834681,102.092049],[23.83445,102.091698],[23.834129,102.090881],[23.8332,102.088898],[23.83288,102.08831],[23.830799,102.084099],[23.83016,102.083054],[23.829861,102.08271],[23.82933,102.082359],[23.828329,102.081863],[23.822161,102.078331],[23.82205,102.078178],[23.82181,102.077698],[23.821199,102.076813],[23.82086,102.076462],[23.8188,102.074661],[23.818331,102.074333],[23.817829,102.074112],[23.817329,102.074013],[23.81706,102.074051],[23.81608,102.073959],[23.81583,102.073883],[23.815359,102.073601],[23.81246,102.070953],[23.811911,102.070358],[23.810949,102.069153],[23.810579,102.068832],[23.81036,102.06871],[23.809879,102.068527],[23.809629,102.068497],[23.80913,102.06855],[23.808661,102.068703],[23.80765,102.069527],[23.80718,102.069809],[23.806931,102.069908],[23.806431,102.069977],[23.805929,102.069809],[23.8057,102.069702],[23.805111,102.069206],[23.804449,102.068359],[23.804079,102.067978],[23.80345,102.067581],[23.80213,102.067047],[23.80155,102.066658],[23.801029,102.0662],[23.79903,102.064003],[23.798861,102.06385],[23.79821,102.063148],[23.797501,102.062531],[23.79648,102.061852],[23.795851,102.061501],[23.79565,102.061363],[23.79418,102.060448],[23.792999,102.059502],[23.791599,102.058357],[23.79055,102.057701],[23.78875,102.056847],[23.78598,102.056],[23.78591,102.055946],[23.785601,102.055771],[23.785271,102.05555],[23.78495,102.055313],[23.784639,102.055054],[23.78433,102.054779],[23.783991,102.054497],[23.78377,102.054321],[23.783541,102.054138],[23.7833,102.053963],[23.78306,102.05378],[23.78281,102.053612],[23.78229,102.053284],[23.782021,102.053123],[23.78175,102.052963],[23.781481,102.052818],[23.7812,102.052673],[23.780661,102.052353],[23.78039,102.052193],[23.780121,102.05204],[23.77984,102.05188],[23.77957,102.05172],[23.779301,102.051559],[23.77903,102.051399],[23.77877,102.051224],[23.778509,102.051064],[23.778259,102.05088],[23.778009,102.05069],[23.777769,102.050507],[23.77754,102.050323],[23.777309,102.050117],[23.777081,102.049919],[23.776859,102.049721],[23.77664,102.049507],[23.77643,102.049316],[23.77622,102.049118],[23.77602,102.04892],[23.77581,102.048721],[23.775511,102.048431],[23.7752,102.048141],[23.7749,102.047859],[23.77459,102.047569],[23.77438,102.047371],[23.774179,102.04718],[23.773979,102.046982],[23.77376,102.046783],[23.77355,102.046593],[23.77322,102.046303],[23.772989,102.046112],[23.77276,102.045937],[23.77252,102.045761],[23.77227,102.045593],[23.77202,102.045433],[23.77178,102.045273],[23.771521,102.04512],[23.771271,102.044983],[23.771021,102.04483],[23.770769,102.044693],[23.77051,102.04454],[23.77026,102.044403],[23.77002,102.044243],[23.76977,102.044098],[23.76952,102.043953],[23.76927,102.043793],[23.76902,102.043663],[23.76878,102.04351],[23.76853,102.043373],[23.76829,102.043221],[23.76804,102.043083],[23.767799,102.042938],[23.76755,102.042801],[23.767309,102.042664],[23.767071,102.042503],[23.76683,102.042351],[23.7666,102.042198],[23.766371,102.042038],[23.766041,102.041786],[23.76582,102.041618],[23.76549,102.041344],[23.76528,102.041161],[23.76507,102.04097],[23.76486,102.040771],[23.76465,102.040573],[23.764441,102.040367],[23.764231,102.040161],[23.76403,102.039963],[23.763821,102.039757],[23.76362,102.039551],[23.76321,102.039162],[23.76289,102.038918],[23.76255,102.038696],[23.762199,102.038513],[23.76182,102.038368],[23.761419,102.038277],[23.761141,102.038239],[23.76086,102.038223],[23.760571,102.038193],[23.760269,102.038147],[23.759979,102.038116],[23.759689,102.038078],[23.757641,102.03775],[23.757311,102.037598],[23.756981,102.03743],[23.756651,102.037262],[23.756321,102.037079],[23.755989,102.036888],[23.755011,102.036324],[23.754681,102.036102],[23.75433,102.035889],[23.753969,102.03569],[23.753599,102.035492],[23.753241,102.035309],[23.752871,102.035103],[23.75251,102.034882],[23.75218,102.034607],[23.7519,102.034271],[23.751671,102.033897],[23.751459,102.033508],[23.75127,102.033119],[23.75107,102.032738],[23.750851,102.032372],[23.750629,102.032013],[23.75038,102.031677],[23.75012,102.031349],[23.749861,102.031029],[23.74958,102.030724],[23.7493,102.030403],[23.74902,102.030083],[23.748791,102.029701],[23.74864,102.029289],[23.748581,102.028877],[23.748619,102.028458],[23.74872,102.028053],[23.74893,102.027687],[23.74921,102.02739],[23.74954,102.027168],[23.749901,102.027031],[23.750259,102.026939],[23.750629,102.026894],[23.750999,102.026817],[23.75135,102.026718],[23.751659,102.026527],[23.751909,102.026268],[23.75206,102.025917],[23.752131,102.025558],[23.752119,102.025169],[23.75209,102.024773],[23.75205,102.024353],[23.752041,102.023933],[23.752081,102.023499],[23.75218,102.023071],[23.7523,102.022659],[23.752541,102.021828],[23.75256,102.021408],[23.752501,102.021004],[23.75231,102.020653],[23.75205,102.020363],[23.75172,102.02021],[23.751369,102.020126],[23.75102,102.020172],[23.750681,102.020287],[23.75042,102.020561],[23.75021,102.020889],[23.75001,102.02124],[23.74964,102.021957],[23.749451,102.022324],[23.74926,102.022667],[23.749041,102.023003],[23.748739,102.023247],[23.748409,102.02343],[23.74807,102.023537],[23.747721,102.023613],[23.74737,102.023666],[23.74703,102.023781],[23.746719,102.023956],[23.74645,102.024193],[23.74621,102.024467],[23.745991,102.024773],[23.74575,102.02507],[23.74552,102.02536],[23.74523,102.025597],[23.74489,102.025787],[23.74453,102.025871],[23.744169,102.02581],[23.74382,102.025681],[23.74349,102.02549],[23.743179,102.025299],[23.74287,102.025101],[23.742559,102.024902],[23.74225,102.024696],[23.74193,102.024513],[23.74161,102.024307],[23.741289,102.024109],[23.74095,102.023911],[23.740601,102.02372],[23.740259,102.023529],[23.73991,102.023338],[23.739571,102.023163],[23.739229,102.022987],[23.738899,102.022812],[23.73856,102.022629],[23.738239,102.022461],[23.737909,102.022293],[23.737579,102.022118],[23.737261,102.021942],[23.736931,102.021767],[23.736589,102.021599],[23.73625,102.021431],[23.73591,102.021248],[23.735571,102.021057],[23.735241,102.020844],[23.73493,102.020592],[23.734631,102.020317],[23.73436,102.020027],[23.734131,102.019699],[23.73391,102.019363],[23.733709,102.019028],[23.73349,102.0187],[23.733231,102.018402],[23.73295,102.01815],[23.73263,102.01799],[23.732281,102.017921],[23.73192,102.01796],[23.731581,102.018059],[23.73127,102.018257],[23.73101,102.018532],[23.73082,102.01886],[23.730709,102.019241],[23.730671,102.019638],[23.73073,102.020042],[23.73086,102.020432],[23.731039,102.020798],[23.73127,102.021141],[23.731501,102.021477],[23.73172,102.021843],[23.731939,102.022202],[23.73214,102.02256],[23.73234,102.022926],[23.73254,102.023277],[23.732731,102.023651],[23.732901,102.024033],[23.73307,102.024406],[23.733231,102.024803],[23.733379,102.0252],[23.73353,102.025597],[23.733681,102.026009],[23.73382,102.026413],[23.733959,102.02681],[23.73411,102.027206],[23.734249,102.027611],[23.73439,102.028023],[23.734541,102.028419],[23.734699,102.028816],[23.73485,102.029213],[23.735001,102.02961],[23.73514,102.030022],[23.735229,102.030441],[23.73527,102.030884],[23.73526,102.031319],[23.73522,102.031761],[23.73513,102.032173],[23.734989,102.03257],[23.7348,102.032944],[23.734591,102.033287],[23.734341,102.033592],[23.734051,102.033867],[23.733749,102.034103],[23.733419,102.034286],[23.73308,102.034439],[23.732719,102.034561],[23.732349,102.034653],[23.731979,102.034683],[23.7316,102.034668],[23.731199,102.034607],[23.730789,102.034538],[23.73037,102.034447],[23.729919,102.03437],[23.729469,102.034286],[23.72901,102.034233],[23.728559,102.03418],[23.728109,102.034126],[23.727659,102.034103],[23.7272,102.03405],[23.726749,102.033997],[23.726311,102.033928],[23.72587,102.033821],[23.725451,102.033691],[23.725031,102.033539],[23.724621,102.033371],[23.724211,102.033188],[23.723789,102.03302],[23.723351,102.032913],[23.7229,102.032883],[23.72246,102.032944],[23.72204,102.033089],[23.721649,102.03331],[23.721291,102.033546],[23.72093,102.033798],[23.72056,102.034027],[23.7202,102.034264],[23.71983,102.034462],[23.71946,102.034668],[23.71908,102.034866],[23.71871,102.035072],[23.71833,102.035263],[23.717951,102.035461],[23.71756,102.035637],[23.717171,102.035828],[23.716789,102.036011],[23.716419,102.036209],[23.71603,102.036308],[23.71563,102.036346],[23.71525,102.036301],[23.714899,102.036148],[23.714581,102.035927],[23.714291,102.035683],[23.71402,102.035408],[23.71372,102.035156],[23.713409,102.03492],[23.713079,102.034714],[23.712721,102.034538],[23.71236,102.034393],[23.711981,102.034264],[23.711599,102.034103],[23.711229,102.033951],[23.710871,102.033783],[23.71052,102.033577],[23.71019,102.033363],[23.709869,102.033119],[23.70957,102.032867],[23.709261,102.032623],[23.708941,102.032402],[23.708611,102.032211],[23.70826,102.032066],[23.707911,102.03196],[23.70755,102.031891],[23.70718,102.031853],[23.70681,102.031837],[23.70644,102.031822],[23.70606,102.031792],[23.7057,102.031723],[23.705351,102.031593],[23.705009,102.031433],[23.704691,102.031227],[23.704399,102.030983],[23.704121,102.030693],[23.703871,102.03038],[23.70363,102.030052],[23.703381,102.029716],[23.703119,102.029404],[23.70257,102.028763],[23.70228,102.02845],[23.701969,102.028137],[23.70167,102.027847],[23.701361,102.02755],[23.70105,102.02726],[23.700741,102.026993],[23.70059,102.026863],[23.70014,102.026466],[23.699841,102.02623],[23.699539,102.025978],[23.699261,102.025703],[23.698999,102.025414],[23.698771,102.025078],[23.69857,102.024727],[23.698389,102.024361],[23.69825,102.023987],[23.698139,102.023598],[23.698071,102.023209],[23.698021,102.022812],[23.698009,102.022423],[23.698021,102.022034],[23.698021,102.021652],[23.69804,102.021271],[23.69805,102.020889],[23.698059,102.020493],[23.698071,102.020103],[23.69809,102.019676],[23.698099,102.019257],[23.698099,102.018837],[23.698099,102.018417],[23.69808,102.017982],[23.69805,102.017548],[23.698009,102.017113],[23.69796,102.01667],[23.697889,102.016228],[23.697809,102.015793],[23.697729,102.01535],[23.69763,102.014923],[23.697531,102.014503],[23.69742,102.014076],[23.697321,102.01368],[23.69721,102.013283],[23.697109,102.012894],[23.69701,102.012489],[23.696911,102.012093],[23.6968,102.011703],[23.696699,102.011307],[23.69659,102.01091],[23.696489,102.010513],[23.69639,102.010117],[23.696289,102.009727],[23.69619,102.009331],[23.696079,102.008942],[23.69598,102.008537],[23.695869,102.008148],[23.69577,102.007751],[23.695669,102.007362],[23.69557,102.006973],[23.695471,102.006577],[23.69537,102.006203],[23.695271,102.005829],[23.695169,102.005463],[23.69507,102.005089],[23.694969,102.004723],[23.69488,102.004356],[23.69478,102.00399],[23.694679,102.003616],[23.69458,102.003242],[23.694481,102.002869],[23.694389,102.002487],[23.69429,102.002121],[23.694189,102.001747],[23.69409,102.001373],[23.693991,102.000999],[23.693899,102.000633],[23.6938,102.000259],[23.693701,101.999893],[23.693609,101.999542],[23.69352,101.999191],[23.693411,101.998848],[23.693279,101.998497],[23.69315,101.998154],[23.69301,101.997803],[23.692869,101.997437],[23.692711,101.99707],[23.692539,101.996696],[23.692381,101.996323],[23.6922,101.995949],[23.692011,101.995567],[23.69183,101.995193],[23.691641,101.994797],[23.691441,101.994423],[23.69125,101.994034],[23.69105,101.993637],[23.690861,101.993248],[23.69066,101.992859],[23.69047,101.992462],[23.690281,101.992073],[23.6901,101.991653],[23.689939,101.991241],[23.689791,101.990822],[23.68964,101.990387],[23.689501,101.989967],[23.689369,101.989563],[23.689251,101.989128],[23.68915,101.988708],[23.689051,101.988281],[23.688971,101.987862],[23.68889,101.987442],[23.68882,101.987022],[23.688761,101.986603],[23.688721,101.986183],[23.688681,101.985764],[23.68865,101.985352],[23.688629,101.98494],[23.68861,101.984528],[23.688589,101.984123],[23.68858,101.983711],[23.68856,101.983307],[23.688551,101.98291],[23.68852,101.982513],[23.68849,101.982101],[23.68845,101.981697],[23.688391,101.981293],[23.688311,101.980888],[23.688219,101.980492],[23.68811,101.980087],[23.68799,101.979691],[23.687851,101.979301],[23.687691,101.978912],[23.687531,101.978523],[23.68737,101.978127],[23.68722,101.977753],[23.687059,101.977364],[23.686899,101.976967],[23.686741,101.976593],[23.68659,101.976212],[23.68643,101.97583],[23.686279,101.975456],[23.686131,101.975098],[23.685961,101.974747],[23.68578,101.974442],[23.685579,101.974136],[23.68536,101.973877],[23.68512,101.973633],[23.684879,101.973412],[23.684629,101.973221],[23.68438,101.973053],[23.684151,101.9729],[23.68383,101.972603],[23.683571,101.972458],[23.68306,101.972168],[23.682819,101.971977],[23.682501,101.971779],[23.682249,101.971626],[23.681971,101.971443],[23.681641,101.971237],[23.681391,101.971077],[23.68115,101.970932],[23.680889,101.970779],[23.68063,101.970627],[23.680349,101.970459],[23.680071,101.970284],[23.679779,101.970108],[23.679489,101.969933],[23.67918,101.969757],[23.678881,101.969597],[23.67857,101.969452],[23.678261,101.96933],[23.67794,101.969223],[23.67762,101.969131],[23.677299,101.969063],[23.67697,101.969009],[23.67663,101.968971],[23.676291,101.968933],[23.675949,101.968887],[23.6756,101.968826],[23.67527,101.968727],[23.67462,101.968483],[23.67432,101.968277],[23.67403,101.968079],[23.67374,101.967857],[23.67345,101.967644],[23.673161,101.96743],[23.672859,101.967239],[23.67255,101.967056],[23.672239,101.966927],[23.67193,101.96682],[23.671619,101.966743],[23.67131,101.966667],[23.671021,101.966621],[23.67075,101.966614],[23.670349,101.966614],[23.66995,101.966637],[23.66091,101.97168],[23.660431,101.971909],[23.66013,101.972076],[23.659809,101.972214],[23.659479,101.972313],[23.65914,101.972366],[23.658791,101.972412],[23.658449,101.97242],[23.65773,101.972427],[23.65737,101.97242],[23.657,101.972412],[23.65662,101.972397],[23.65624,101.972389],[23.655849,101.972366],[23.65547,101.972298],[23.6551,101.97216],[23.654751,101.97197],[23.65443,101.971764],[23.65411,101.971542],[23.65379,101.971336],[23.65346,101.971184],[23.65312,101.971046],[23.652769,101.970978],[23.652399,101.970947],[23.65204,101.970963],[23.651661,101.970993],[23.65127,101.971024],[23.650909,101.971001],[23.65053,101.970917],[23.650181,101.970757],[23.649851,101.970558],[23.649561,101.970299],[23.649281,101.970032],[23.64901,101.969772],[23.64875,101.969513],[23.648491,101.969261],[23.64823,101.969002],[23.64797,101.96875],[23.647699,101.968491],[23.64743,101.968231],[23.64716,101.967957],[23.646891,101.967682],[23.646641,101.967377],[23.64642,101.967056],[23.64624,101.966698],[23.646099,101.966316],[23.645969,101.965927],[23.64583,101.965553],[23.6457,101.965149],[23.645559,101.964767],[23.645399,101.964409],[23.64522,101.964088],[23.644991,101.963814],[23.644739,101.963562],[23.64447,101.963341],[23.643101,101.962318],[23.64275,101.96209],[23.64241,101.961853],[23.642071,101.961632],[23.641741,101.961411],[23.641399,101.961182],[23.641069,101.96096],[23.640751,101.960716],[23.64043,101.96048],[23.640141,101.96022],[23.63987,101.959953],[23.63962,101.959686],[23.638901,101.958862],[23.63866,101.958588],[23.638479,101.958397],[23.63728,101.957024],[23.63489,101.954277],[23.63361,101.952621],[23.633329,101.951576],[23.63299,101.948517],[23.632059,101.946426],[23.63175,101.945503],[23.632021,101.944267],[23.63216,101.943573],[23.632389,101.942902],[23.63249,101.942574],[23.632521,101.942223],[23.632259,101.93898],[23.632299,101.938667],[23.632351,101.938339],[23.63238,101.938011],[23.632401,101.937683],[23.632401,101.937332],[23.63241,101.936653],[23.632389,101.936287],[23.63237,101.935944],[23.632351,101.935593],[23.632339,101.935226],[23.63236,101.934883],[23.63245,101.934517],[23.632561,101.934174],[23.63269,101.93383],[23.63283,101.933472],[23.63298,101.933113],[23.633129,101.932747],[23.633289,101.932404],[23.633591,101.931664],[23.63368,101.931267],[23.633711,101.930862],[23.63368,101.930473],[23.633631,101.930069],[23.63357,101.929688],[23.633459,101.929329],[23.633369,101.92897],[23.63332,101.928612],[23.63331,101.928253],[23.633329,101.927528],[23.63336,101.927162],[23.633511,101.926819],[23.633711,101.926514],[23.63435,101.925613],[23.635139,101.924377],[23.635309,101.923653],[23.63538,101.923286],[23.635441,101.92292],[23.6355,101.922546],[23.635559,101.922188],[23.63562,101.921806],[23.635691,101.921448],[23.635771,101.921082],[23.635851,101.920723],[23.63595,101.920349],[23.636061,101.919983],[23.636169,101.919609],[23.63629,101.919243],[23.63641,101.918869],[23.63653,101.918503],[23.636641,101.918121],[23.636761,101.917747],[23.636869,101.917374],[23.63698,101.917],[23.63711,101.916634],[23.637251,101.916267],[23.637409,101.915909],[23.637581,101.915573],[23.637791,101.915253],[23.63802,101.914963],[23.63826,101.914673],[23.638519,101.914398],[23.638809,101.914162],[23.63909,101.913933],[23.639971,101.913269],[23.640249,101.913033],[23.640499,101.912773],[23.640751,101.912514],[23.64097,101.912216],[23.641159,101.911926],[23.641331,101.911613],[23.64147,101.911301],[23.641581,101.91098],[23.64167,101.91066],[23.641729,101.910339],[23.641781,101.910027],[23.64183,101.909714],[23.64188,101.909401],[23.64193,101.909103],[23.641979,101.908813],[23.64201,101.908386],[23.642031,101.90799],[23.64205,101.9076],[23.642071,101.907204],[23.64213,101.906799],[23.642191,101.906387],[23.64225,101.905983],[23.6423,101.905571],[23.64238,101.905151],[23.642521,101.904739],[23.642651,101.904472],[23.642799,101.904221],[23.642969,101.903976],[23.64316,101.903763],[23.64337,101.903542],[23.643591,101.903343],[23.64382,101.903152],[23.644039,101.902946],[23.64427,101.90274],[23.64447,101.902519],[23.644661,101.902283],[23.644831,101.902023],[23.645029,101.901604],[23.64513,101.901299],[23.64521,101.900993],[23.645281,101.900658],[23.64535,101.900337],[23.64542,101.900009],[23.6455,101.899681],[23.645611,101.899353],[23.645729,101.89904],[23.64588,101.898743],[23.646061,101.898438],[23.646259,101.898163],[23.646469,101.897881],[23.646681,101.897598],[23.646891,101.897301],[23.647091,101.897003],[23.647261,101.896683],[23.647421,101.896362],[23.647539,101.896019],[23.64765,101.895683],[23.64773,101.895317],[23.647791,101.894958],[23.647829,101.894592],[23.647881,101.894234],[23.647921,101.893852],[23.647961,101.893494],[23.64802,101.89312],[23.6481,101.892761],[23.648199,101.892403],[23.648319,101.892067],[23.648451,101.891739],[23.6486,101.891434],[23.64876,101.891121],[23.64893,101.890831],[23.64909,101.890533],[23.64922,101.890244],[23.649361,101.889954],[23.64949,101.889671],[23.649639,101.889397],[23.649771,101.889122],[23.64991,101.888847],[23.650049,101.888573],[23.65019,101.888298],[23.65033,101.888023],[23.650471,101.887733],[23.65062,101.887428],[23.65077,101.887123],[23.650921,101.88681],[23.65107,101.886497],[23.65123,101.886177],[23.65139,101.885849],[23.65156,101.885521],[23.65172,101.885178],[23.65189,101.884842],[23.65204,101.884499],[23.65221,101.884163],[23.65237,101.88382],[23.65254,101.883492],[23.6527,101.883179],[23.652849,101.882874],[23.653009,101.882584],[23.653151,101.882294],[23.653299,101.882019],[23.653521,101.88163],[23.65366,101.881378],[23.653799,101.881149],[23.6539,101.880768],[23.6546,101.878288],[23.65497,101.877052],[23.65519,101.876587],[23.65564,101.875954],[23.657261,101.874313],[23.657681,101.873672],[23.657881,101.873199],[23.65803,101.8722],[23.658001,101.868111],[23.65777,101.867126],[23.657431,101.866409],[23.656799,101.865631],[23.65568,101.864571],[23.65534,101.864098],[23.655069,101.863403],[23.654449,101.860573],[23.653891,101.859253],[23.65309,101.857887],[23.652849,101.857109],[23.6527,101.855202],[23.652519,101.854607],[23.652201,101.854088],[23.65103,101.852982],[23.650789,101.852661],[23.650499,101.851913],[23.65053,101.851082],[23.650631,101.85022],[23.6506,101.849571],[23.650471,101.849152],[23.650129,101.848633],[23.649679,101.848213],[23.647881,101.847023],[23.64748,101.846626],[23.647169,101.846169],[23.64691,101.845627],[23.64591,101.842331],[23.64588,101.841537],[23.646021,101.840973],[23.646509,101.839737],[23.64658,101.839371],[23.646561,101.838982],[23.646391,101.838463],[23.6462,101.838158],[23.645679,101.837677],[23.644739,101.836983],[23.64422,101.836113],[23.643431,101.833298],[23.643379,101.832687],[23.643419,101.832283],[23.643539,101.831909],[23.64373,101.831596],[23.64398,101.831306],[23.644661,101.830681],[23.645029,101.830032],[23.64509,101.829674],[23.645069,101.829277],[23.644979,101.828918],[23.64468,101.82843],[23.64443,101.828194],[23.64377,101.827888],[23.64187,101.827499],[23.641439,101.827347],[23.641121,101.827271],[23.64064,101.827003],[23.64023,101.82666],[23.6397,101.825867],[23.638741,101.824013],[23.63851,101.823723],[23.63822,101.823479],[23.63772,101.823273],[23.634621,101.822853],[23.63373,101.822456],[23.633289,101.822166],[23.63265,101.821503],[23.632271,101.820862],[23.63167,101.819717],[23.631189,101.819206],[23.630751,101.818939],[23.63028,101.818771],[23.629459,101.818718],[23.628241,101.818901],[23.627939,101.818893],[23.62748,101.818764],[23.62705,101.818542],[23.626699,101.818192],[23.62628,101.817398],[23.625401,101.815086],[23.625311,101.814537],[23.62536,101.813812],[23.62553,101.813271],[23.62578,101.812782],[23.627951,101.810028],[23.628139,101.809547],[23.628189,101.809029],[23.62818,101.808868],[23.627979,101.808357],[23.627661,101.807938],[23.627119,101.807632],[23.62405,101.80632],[23.625191,101.808884],[23.62512,101.809036],[23.625,101.80941],[23.624729,101.809753],[23.624331,101.8106],[23.623581,101.811707],[23.623159,101.811996],[23.622641,101.812172],[23.62188,101.81218],[23.619591,101.811241],[23.618839,101.811234],[23.61693,101.811867],[23.616489,101.81189],[23.616039,101.811752],[23.61566,101.81147],[23.615379,101.811073],[23.615351,101.810913],[23.615259,101.810677],[23.61528,101.810501],[23.61525,101.810333],[23.6154,101.809113],[23.61533,101.808052],[23.615101,101.807381],[23.61482,101.806931],[23.61384,101.805931],[23.61338,101.804947],[23.612089,101.804108],[23.606489,101.800911],[23.60602,101.800377],[23.605721,101.79985],[23.60515,101.798477],[23.60471,101.798012],[23.603531,101.797302],[23.602871,101.79673],[23.601749,101.795517],[23.601049,101.794998],[23.600031,101.794533],[23.59981,101.794533],[23.597759,101.793373],[23.59746,101.793297],[23.59713,101.79306],[23.596479,101.792343],[23.59548,101.790649],[23.59395,101.787376],[23.593281,101.787666],[23.593069,101.787567],[23.59271,101.787483],[23.59218,101.787453],[23.591379,101.787331],[23.591049,101.787209],[23.59067,101.786911],[23.588079,101.784103],[23.58736,101.783546],[23.583599,101.781487],[23.58288,101.780853],[23.58206,101.779671],[23.581341,101.77845],[23.579889,101.77681],[23.57777,101.773178],[23.57704,101.772392],[23.57626,101.771942],[23.574301,101.771294],[23.57362,101.770897],[23.569811,101.767776],[23.568859,101.767281],[23.56444,101.765839],[23.563801,101.765472],[23.56325,101.764969],[23.56292,101.764526],[23.56076,101.761436],[23.56049,101.761147],[23.560011,101.760841],[23.559481,101.760651],[23.55802,101.760628],[23.557501,101.760529],[23.55702,101.760277],[23.556749,101.760063],[23.556431,101.759598],[23.55628,101.759247],[23.55587,101.756828],[23.555571,101.756027],[23.55514,101.75531],[23.554581,101.754723],[23.55154,101.752617],[23.55105,101.752113],[23.55064,101.751312],[23.549629,101.747353],[23.5494,101.746819],[23.54907,101.746384],[23.54847,101.745941],[23.547041,101.74514],[23.54565,101.743851],[23.540291,101.738487],[23.52383,101.719322],[23.52364,101.719063],[23.523529,101.718758],[23.523479,101.718697],[23.52347,101.718613],[23.523279,101.718323],[23.522591,101.716637],[23.521999,101.715767],[23.52058,101.714523],[23.52,101.713913],[23.519779,101.713562],[23.51964,101.71315],[23.5196,101.712479],[23.519739,101.711777],[23.521111,101.707848],[23.52124,101.70697],[23.521231,101.706749],[23.52112,101.706306],[23.520889,101.705887],[23.52058,101.705521],[23.520399,101.70536],[23.51824,101.70433],[23.51787,101.704071],[23.51755,101.703743],[23.51734,101.703331],[23.51722,101.702873],[23.51722,101.7024],[23.517321,101.701958],[23.518999,101.698547],[23.51775,101.698097],[23.51767,101.6978],[23.517309,101.697159],[23.51687,101.69648],[23.516701,101.695976],[23.516529,101.69442],[23.51643,101.693939],[23.516211,101.693497],[23.515921,101.693123],[23.515539,101.692818],[23.515129,101.692596],[23.51243,101.691757],[23.51194,101.691704],[23.51141,101.691719],[23.51091,101.691818],[23.50996,101.692207],[23.507971,101.693314],[23.507601,101.693588],[23.50729,101.693932],[23.507059,101.694366],[23.50691,101.694847],[23.506861,101.695351],[23.507,101.696098],[23.50742,101.697243],[23.5075,101.697701],[23.507481,101.698158],[23.507339,101.698608],[23.507099,101.699013],[23.506781,101.699333],[23.506161,101.699654],[23.50526,101.700027],[23.504829,101.700287],[23.504471,101.700638],[23.50415,101.701057],[23.503901,101.701538],[23.503441,101.703049],[23.503309,101.703537],[23.50313,101.703979],[23.50301,101.704163],[23.50268,101.704491],[23.502291,101.70472],[23.501909,101.704857],[23.501499,101.704849],[23.50091,101.704697],[23.50058,101.704491],[23.500111,101.704033],[23.49843,101.701653],[23.498051,101.700943],[23.49762,101.699638],[23.497089,101.697792],[23.49687,101.697281],[23.496441,101.696579],[23.49609,101.696167],[23.493389,101.694],[23.492741,101.693573],[23.49201,101.69326],[23.491501,101.693169],[23.49099,101.693161],[23.49048,101.693253],[23.49,101.69342],[23.482491,101.698227],[23.481791,101.698517],[23.481319,101.698624],[23.47983,101.698692],[23.47933,101.698769],[23.478849,101.698921],[23.47797,101.699402],[23.476339,101.700623],[23.47547,101.701134],[23.474991,101.701286],[23.47427,101.701363],[23.473539,101.701248],[23.47261,101.70092],[23.471729,101.700432],[23.470921,101.699806],[23.4702,101.699051],[23.469601,101.698143],[23.467279,101.693512],[23.4664,101.692177],[23.46524,101.690804],[23.46394,101.689568],[23.462299,101.688393],[23.45648,101.68544],[23.45483,101.684227],[23.451571,101.679291],[23.45013,101.677612],[23.44994,101.67746],[23.449751,101.677254],[23.44949,101.677063],[23.44916,101.676651],[23.44833,101.676033],[23.44721,101.675468],[23.446461,101.675232],[23.445459,101.675049],[23.444201,101.675041],[23.44323,101.675217],[23.43902,101.67688],[23.43664,101.677452],[23.432159,101.677811],[23.43161,101.677773],[23.431431,101.677727],[23.431009,101.677711],[23.43075,101.677757],[23.430719,101.677887],[23.43041,101.678017],[23.42782,101.678543],[23.42403,101.680153],[23.423691,101.680183],[23.42275,101.680458],[23.422331,101.68055],[23.42065,101.680603],[23.41925,101.680367],[23.41754,101.679703],[23.416361,101.679008],[23.41523,101.678017],[23.41408,101.67662],[23.409769,101.67025],[23.409281,101.66922],[23.408991,101.667892],[23.408939,101.666992],[23.40909,101.665619],[23.409439,101.664513],[23.410669,101.661987],[23.4111,101.660606],[23.41157,101.658386],[23.4119,101.657417],[23.41876,101.645554],[23.422489,101.637756],[23.4282,101.62957],[23.42873,101.628517],[23.429131,101.626556],[23.42959,101.622337],[23.42943,101.621048],[23.42898,101.619904],[23.42824,101.618896],[23.427191,101.618149],[23.42573,101.617706],[23.424709,101.617783],[23.42399,101.617973],[23.421801,101.619003],[23.42082,101.619186],[23.41987,101.61908],[23.4189,101.618713],[23.418091,101.617973],[23.417589,101.617203],[23.417191,101.615929],[23.41724,101.6147],[23.41798,101.611702],[23.41794,101.610687],[23.417459,101.60936],[23.417101,101.608871],[23.416019,101.608063],[23.41116,101.606781],[23.410561,101.606598],[23.409781,101.606407],[23.408819,101.605873],[23.40723,101.604347],[23.40661,101.603989],[23.40645,101.603943],[23.40589,101.603752],[23.40432,101.603638],[23.403259,101.603188],[23.40159,101.602028],[23.393909,101.58802],[23.392799,101.586533],[23.392191,101.585709],[23.391319,101.584778],[23.390221,101.583527],[23.38945,101.582977],[23.38868,101.582642],[23.383381,101.580978],[23.382919,101.580917],[23.376631,101.581413],[23.37141,101.58181],[23.370029,101.581902],[23.365709,101.581863],[23.364161,101.581528],[23.36342,101.580582],[23.36319,101.579971],[23.363119,101.57975],[23.36302,101.578888],[23.363171,101.577911],[23.36417,101.574783],[23.36421,101.57399],[23.36409,101.572906],[23.36302,101.568893],[23.362671,101.566399],[23.36252,101.565987],[23.36227,101.565643],[23.36195,101.565338],[23.360991,101.564751],[23.36055,101.564323],[23.36034,101.563942],[23.36025,101.563507],[23.360241,101.563011],[23.36146,101.555557],[23.361481,101.555077],[23.36145,101.554817],[23.3613,101.554359],[23.361059,101.553932],[23.35988,101.552742],[23.359739,101.552559],[23.359541,101.552139],[23.35944,101.551666],[23.359461,101.551193],[23.3596,101.550743],[23.35985,101.550331],[23.360359,101.549797],[23.3624,101.548019],[23.36273,101.547653],[23.363001,101.547234],[23.363171,101.546722],[23.36323,101.546188],[23.363171,101.545624],[23.362129,101.542778],[23.36191,101.542297],[23.361429,101.541649],[23.36083,101.54113],[23.356621,101.539139],[23.355459,101.538544],[23.35391,101.537888],[23.353291,101.53775],[23.35309,101.53775],[23.35268,101.537857],[23.35231,101.538101],[23.352011,101.538452],[23.35129,101.539688],[23.351,101.539993],[23.35067,101.540222],[23.350281,101.540352],[23.349859,101.540367],[23.349211,101.54026],[23.34816,101.539841],[23.347811,101.539619],[23.34753,101.53933],[23.34734,101.538963],[23.34724,101.538513],[23.347269,101.537819],[23.347429,101.53669],[23.34742,101.536232],[23.347321,101.535797],[23.346979,101.535103],[23.346121,101.533829],[23.34573,101.533813],[23.344851,101.533127],[23.344709,101.532967],[23.34454,101.532593],[23.344469,101.532181],[23.344481,101.531754],[23.344749,101.531113],[23.345341,101.530067],[23.34547,101.52964],[23.34549,101.529419],[23.34544,101.528961],[23.345369,101.528732],[23.34515,101.528313],[23.344681,101.527786],[23.343719,101.526917],[23.34347,101.526573],[23.343281,101.526154],[23.34318,101.525703],[23.34318,101.525223],[23.343321,101.52449],[23.343639,101.523193],[23.34362,101.522339],[23.34285,101.519333],[23.34116,101.5177],[23.34013,101.517014],[23.33942,101.516563],[23.33905,101.51619],[23.335939,101.511429],[23.335501,101.510902],[23.335039,101.510536],[23.333469,101.510399],[23.3328,101.510399],[23.332359,101.510406],[23.331421,101.510529],[23.33069,101.510742],[23.33045,101.510841],[23.32917,101.511803],[23.32873,101.512032],[23.328251,101.512169],[23.327749,101.51223],[23.327009,101.512154],[23.323721,101.511398],[23.32324,101.511223],[23.322809,101.510941],[23.322451,101.510597],[23.322161,101.510147],[23.320351,101.505699],[23.32012,101.505348],[23.319851,101.505074],[23.316191,101.503098],[23.316031,101.50293],[23.315781,101.502434],[23.315651,101.501892],[23.315639,101.501511],[23.31591,101.500183],[23.31591,101.499603],[23.31584,101.499207],[23.31547,101.498512],[23.31509,101.4981],[23.313749,101.497139],[23.313049,101.4963],[23.311449,101.493736],[23.310949,101.49324],[23.310511,101.49295],[23.309811,101.492706],[23.309259,101.49263],[23.308701,101.492653],[23.30798,101.492867],[23.307329,101.493263],[23.30624,101.494263],[23.30578,101.494499],[23.30526,101.494598],[23.30475,101.494522],[23.30443,101.494408],[23.304001,101.494133],[23.30332,101.493523],[23.302679,101.493134],[23.302151,101.492973],[23.300329,101.492828],[23.29982,101.492691],[23.29936,101.492416],[23.29896,101.492058],[23.298651,101.49157],[23.29851,101.491203],[23.29841,101.490593],[23.298441,101.489937],[23.29887,101.488731],[23.29994,101.486298],[23.30003,101.485863],[23.300039,101.485397],[23.299959,101.484947],[23.29982,101.484512],[23.29916,101.483093],[23.29899,101.48246],[23.298941,101.479362],[23.29888,101.478943],[23.29845,101.477783],[23.29397,101.471352],[23.293539,101.470367],[23.293381,101.469688],[23.29336,101.469353],[23.293779,101.464844],[23.2936,101.460899],[23.29335,101.459717],[23.29188,101.454727],[23.29196,101.453789],[23.292139,101.453323],[23.29254,101.452782],[23.293091,101.452377],[23.29735,101.450317],[23.29784,101.450218],[23.298019,101.450157],[23.29837,101.45005],[23.300659,101.448982],[23.301109,101.448647],[23.301611,101.448097],[23.30344,101.445053],[23.303631,101.44455],[23.30373,101.44381],[23.303711,101.443443],[23.302691,101.440353],[23.30262,101.439346],[23.303419,101.434143],[23.30341,101.433594],[23.30246,101.428864],[23.30212,101.426933],[23.30205,101.425301],[23.30209,101.423752],[23.30225,101.423042],[23.302509,101.422371],[23.30275,101.421272],[23.30324,101.419991],[23.30357,101.418121],[23.304411,101.41581],[23.30448,101.414879],[23.3043,101.414093],[23.303921,101.412971],[23.30341,101.411713],[23.303289,101.411186],[23.302959,101.410378],[23.302151,101.407608],[23.302019,101.403557],[23.30205,101.399788],[23.301559,101.398216],[23.299601,101.394699],[23.29941,101.394173],[23.298491,101.388153],[23.29851,101.387039],[23.299,101.381798],[23.299179,101.379967],[23.299601,101.375473],[23.29952,101.37381],[23.29854,101.368073],[23.298491,101.367287],[23.298559,101.366814],[23.29862,101.366577],[23.29883,101.366158],[23.298969,101.365967],[23.299129,101.365807],[23.29973,101.365448],[23.30014,101.365318],[23.300591,101.365318],[23.300791,101.365372],[23.301411,101.365631],[23.302679,101.366463],[23.30315,101.366669],[23.305269,101.367111],[23.308611,101.368553],[23.30908,101.368668],[23.309549,101.368683],[23.30978,101.368637],[23.310221,101.368462],[23.31061,101.368179],[23.310921,101.367813],[23.311159,101.367348],[23.311291,101.366852],[23.31131,101.3666],[23.31126,101.366089],[23.31119,101.365829],[23.310949,101.365372],[23.310631,101.36496],[23.31044,101.364777],[23.308399,101.363472],[23.30801,101.363098],[23.30773,101.362648],[23.307541,101.362137],[23.30748,101.361893],[23.30747,101.361351],[23.307541,101.360817],[23.30772,101.360313],[23.30801,101.359863],[23.30838,101.359489],[23.30883,101.3592],[23.309771,101.358704],[23.310181,101.358353],[23.31049,101.357941],[23.31069,101.357468],[23.31078,101.356972],[23.310459,101.352417],[23.31035,101.351883],[23.310141,101.351357],[23.30983,101.350891],[23.309111,101.350021],[23.308661,101.349297],[23.30788,101.347549],[23.3076,101.347076],[23.30723,101.346687],[23.305611,101.345879],[23.305229,101.345596],[23.304939,101.345253],[23.30475,101.344803],[23.304661,101.344322],[23.30468,101.343826],[23.304729,101.343597],[23.30492,101.343163],[23.305201,101.342789],[23.30537,101.342644],[23.306009,101.34227],[23.308861,101.341087],[23.309299,101.340843],[23.309669,101.3405],[23.309959,101.340073],[23.310141,101.3396],[23.31019,101.339104],[23.310141,101.338593],[23.30998,101.338097],[23.309719,101.337692],[23.309549,101.337517],[23.30913,101.337242],[23.308649,101.337067],[23.30817,101.337013],[23.30768,101.337082],[23.30719,101.337273],[23.305771,101.33799],[23.301991,101.340103],[23.30154,101.340286],[23.30106,101.340393],[23.30057,101.34037],[23.29932,101.340088],[23.29855,101.34005],[23.297001,101.340271],[23.29649,101.34024],[23.29598,101.340118],[23.293831,101.339027],[23.293381,101.338768],[23.29261,101.338577],[23.29154,101.338562],[23.288971,101.338783],[23.288191,101.338737],[23.287689,101.338608],[23.287201,101.338387],[23.28404,101.335876],[23.283569,101.335587],[23.283079,101.335388],[23.28257,101.335274],[23.282049,101.335251],[23.281521,101.33532],[23.28101,101.335487],[23.28054,101.335732],[23.27841,101.337212],[23.277769,101.337517],[23.277321,101.337593],[23.27689,101.337547],[23.27648,101.33741],[23.2761,101.337143],[23.27562,101.336594],[23.27515,101.335983],[23.27478,101.335617],[23.274361,101.335373],[23.274139,101.335289],[23.273899,101.335243],[23.273439,101.335251],[23.272051,101.335579],[23.27157,101.335564],[23.27112,101.335403],[23.27072,101.335167],[23.27021,101.334663],[23.26919,101.333076],[23.269051,101.332809],[23.26845,101.332222],[23.267771,101.331757],[23.267241,101.331573],[23.266479,101.33149],[23.265961,101.331558],[23.265221,101.331787],[23.263969,101.332336],[23.263201,101.332497],[23.261641,101.332603],[23.261129,101.332733],[23.260651,101.332947],[23.260201,101.333229],[23.26,101.333397],[23.259661,101.333832],[23.259109,101.334793],[23.259041,101.334999],[23.257879,101.336838],[23.25754,101.337242],[23.256929,101.337769],[23.25646,101.33802],[23.25596,101.338181],[23.255699,101.338219],[23.255159,101.338188],[23.25489,101.338142],[23.24906,101.335602],[23.248369,101.335197],[23.24132,101.329826],[23.24147,101.328873],[23.24135,101.32872],[23.24053,101.327087],[23.24011,101.326118],[23.2397,101.325417],[23.239361,101.325027],[23.23761,101.323486],[23.23728,101.323082],[23.23691,101.322357],[23.236731,101.321823],[23.236641,101.321274],[23.236641,101.320442],[23.23761,101.314987],[23.23786,101.314232],[23.238091,101.313751],[23.23838,101.313309],[23.238939,101.312729],[23.239361,101.312393],[23.240049,101.312019],[23.24082,101.311768],[23.241579,101.311661],[23.24288,101.311569],[23.24366,101.311401],[23.244169,101.311203],[23.24485,101.310791],[23.24724,101.308578],[23.249371,101.306458],[23.25046,101.305717],[23.2514,101.305183],[23.252029,101.304672],[23.25238,101.30426],[23.253401,101.302597],[23.25375,101.3022],[23.254169,101.301857],[23.25576,101.300957],[23.256809,101.300117],[23.25803,101.298683],[23.259621,101.296432],[23.26001,101.295692],[23.260309,101.294907],[23.260509,101.293823],[23.260599,101.28904],[23.260759,101.28791],[23.26182,101.283836],[23.26189,101.283279],[23.261841,101.282417],[23.26166,101.281563],[23.2612,101.280502],[23.25816,101.275703],[23.25787,101.27494],[23.25729,101.272781],[23.25692,101.271729],[23.256861,101.271446],[23.25684,101.270866],[23.25701,101.269768],[23.2575,101.267838],[23.257601,101.266983],[23.257561,101.265312],[23.25761,101.264763],[23.25774,101.264198],[23.25815,101.263153],[23.258499,101.261742],[23.259399,101.259422],[23.26021,101.255463],[23.2605,101.254677],[23.261391,101.253326],[23.26161,101.252808],[23.261709,101.252228],[23.26173,101.251953],[23.26165,101.251404],[23.26148,101.2509],[23.261221,101.25042],[23.257629,101.245293],[23.25453,101.24102],[23.25424,101.240463],[23.25411,101.240051],[23.25407,101.239372],[23.254141,101.238907],[23.25489,101.237106],[23.255079,101.236382],[23.255131,101.235603],[23.25507,101.234787],[23.25494,101.234009],[23.254641,101.232986],[23.253679,101.230522],[23.253099,101.228249],[23.25218,101.224899],[23.252119,101.224251],[23.252159,101.223793],[23.25227,101.223343],[23.25267,101.222473],[23.255369,101.21814],[23.25563,101.217392],[23.255819,101.216293],[23.255989,101.211189],[23.25593,101.210632],[23.255699,101.209801],[23.25515,101.208397],[23.255079,101.207947],[23.255119,101.207291],[23.25556,101.205559],[23.25559,101.204849],[23.255541,101.204369],[23.253651,101.197647],[23.25321,101.190193],[23.253139,101.189636],[23.252899,101.18885],[23.25223,101.187347],[23.252081,101.186821],[23.252029,101.186028],[23.252029,101.184959],[23.251909,101.184181],[23.251471,101.182693],[23.251419,101.182167],[23.251471,101.181671],[23.251711,101.180946],[23.25214,101.179993],[23.252359,101.179207],[23.25268,101.176117],[23.253679,101.172638],[23.253969,101.17189],[23.25404,101.171608],[23.25423,101.17112],[23.25482,101.170181],[23.255159,101.169746],[23.259211,101.165756],[23.259529,101.165337],[23.25967,101.165108],[23.2598,101.164597],[23.25979,101.164093],[23.258751,101.160049],[23.25845,101.159592],[23.258369,101.15921],[23.258289,101.158447],[23.258169,101.158096],[23.257179,101.156563],[23.25629,101.155159],[23.255951,101.154793],[23.255541,101.154503],[23.25308,101.15316],[23.24979,101.150223],[23.247089,101.148514],[23.246321,101.147751],[23.244961,101.146111],[23.244539,101.145798],[23.244101,101.145569],[23.243641,101.145447],[23.243139,101.145439],[23.237881,101.146713],[23.23527,101.146896],[23.23027,101.148399],[23.227171,101.148933],[23.226601,101.149139],[23.226101,101.149513],[23.225031,101.150719],[23.22471,101.150948],[23.22401,101.151237],[23.223459,101.151314],[23.2229,101.151283],[23.21833,101.149529],[23.217529,101.149437],[23.21492,101.150093],[23.214319,101.150146],[23.21393,101.150101],[23.213551,101.149986],[23.212259,101.149292],[23.211651,101.149101],[23.20582,101.149193],[23.20516,101.149101],[23.20451,101.148857],[23.20013,101.146408],[23.197161,101.144211],[23.196699,101.14399],[23.196171,101.143883],[23.19566,101.143867],[23.18998,101.145264],[23.18713,101.146263],[23.182751,101.14782],[23.18214,101.147957],[23.18144,101.147972],[23.17918,101.148079],[23.176701,101.148148],[23.176439,101.148087],[23.1756,101.147591],[23.173691,101.145157],[23.173109,101.144783],[23.17226,101.144508],[23.17214,101.144493],[23.171379,101.144051],[23.17091,101.143517],[23.17028,101.14193],[23.17,101.14164],[23.16972,101.141602],[23.169439,101.141708],[23.168489,101.142616],[23.168249,101.142776],[23.167931,101.142853],[23.16761,101.14283],[23.167219,101.142616],[23.166941,101.142342],[23.165541,101.140137],[23.165371,101.139969],[23.165131,101.139893],[23.1649,101.1399],[23.16469,101.140007],[23.164539,101.140213],[23.16445,101.14048],[23.16448,101.140793],[23.16538,101.143227],[23.16543,101.14357],[23.16539,101.143867],[23.165239,101.144112],[23.16502,101.14431],[23.16489,101.144363],[23.16461,101.144333],[23.16432,101.144157],[23.163019,101.142433],[23.16272,101.142174],[23.162319,101.142067],[23.16206,101.142113],[23.16169,101.142326],[23.16151,101.142563],[23.16139,101.143013],[23.161699,101.14537],[23.161659,101.145683],[23.161551,101.14595],[23.16135,101.146149],[23.16123,101.146217],[23.161091,101.14624],[23.16082,101.146202],[23.16057,101.146072],[23.160259,101.145714],[23.159731,101.144867],[23.159531,101.144707],[23.159149,101.144577],[23.157949,101.144608],[23.157829,101.144577],[23.15764,101.144417],[23.15748,101.144173],[23.15741,101.14389],[23.15745,101.143623],[23.157551,101.143349],[23.159639,101.140259],[23.159769,101.139923],[23.15979,101.139557],[23.159719,101.139076],[23.159531,101.138649],[23.15921,101.138329],[23.156639,101.137047],[23.156389,101.136993],[23.156059,101.137062],[23.1558,101.137283],[23.155689,101.137459],[23.1556,101.137772],[23.155609,101.138649],[23.155491,101.139977],[23.15535,101.140266],[23.15517,101.140411],[23.154699,101.140518],[23.153589,101.140503],[23.15336,101.140556],[23.153191,101.140694],[23.15309,101.140862],[23.152969,101.14135],[23.15296,101.141541],[23.152849,101.141853],[23.152651,101.142036],[23.15243,101.142143],[23.15204,101.142143],[23.15184,101.142113],[23.151449,101.142242],[23.1513,101.14238],[23.15011,101.145851],[23.149879,101.146141],[23.149561,101.146332],[23.149179,101.146339],[23.148781,101.146133],[23.14868,101.146019],[23.14852,101.145737],[23.148199,101.14447],[23.14818,101.144096],[23.148239,101.143761],[23.148491,101.14312],[23.148529,101.142517],[23.14846,101.142067],[23.147579,101.140503],[23.14716,101.139427],[23.146629,101.138603],[23.1465,101.13829],[23.146351,101.137589],[23.146191,101.137383],[23.1458,101.137131],[23.1457,101.137131],[23.14535,101.136864],[23.145149,101.136597],[23.14497,101.136078],[23.145,101.135048],[23.144831,101.134483],[23.144569,101.134003],[23.14341,101.13269],[23.14303,101.131958],[23.14296,101.131317],[23.142981,101.130791],[23.143021,101.13031],[23.14278,101.12957],[23.142031,101.128441],[23.14192,101.12812],[23.14188,101.127731],[23.14192,101.127457],[23.14204,101.12693],[23.141991,101.126511],[23.141701,101.125992],[23.140921,101.124786],[23.140791,101.124329],[23.140751,101.123627],[23.140591,101.123238],[23.13983,101.122459],[23.139219,101.122047],[23.13895,101.121941],[23.13866,101.12191],[23.137951,101.122078],[23.13674,101.122704],[23.135241,101.123283],[23.13401,101.123489],[23.133511,101.123459],[23.13283,101.123253],[23.13246,101.123253],[23.130779,101.123734],[23.130409,101.123901],[23.12991,101.124283],[23.12949,101.124657],[23.129351,101.124763],[23.128851,101.12487],[23.12851,101.124863],[23.126789,101.12442],[23.126419,101.124367],[23.12533,101.124573],[23.12499,101.124588],[23.12468,101.124496],[23.124411,101.124329],[23.124189,101.124077],[23.123911,101.123688],[23.123671,101.123543],[23.1227,101.12326],[23.12211,101.122917],[23.120399,101.121613],[23.119591,101.120728],[23.11902,101.120232],[23.117861,101.119186],[23.11676,101.118294],[23.11643,101.117828],[23.11591,101.116852],[23.115431,101.116112],[23.113951,101.11451],[23.113501,101.114166],[23.112789,101.11393],[23.112261,101.113762],[23.11195,101.113548],[23.111401,101.112953],[23.111071,101.112709],[23.110701,101.112541],[23.110331,101.112419],[23.11002,101.112228],[23.10965,101.111816],[23.10878,101.110573],[23.107849,101.109497],[23.107559,101.1091],[23.10708,101.108177],[23.10644,101.106758],[23.10614,101.105141],[23.106171,101.104942],[23.106541,101.103653],[23.10606,101.099571],[23.10594,101.099129],[23.105619,101.098534],[23.102871,101.095078],[23.102421,101.094269],[23.10216,101.093369],[23.10181,101.091087],[23.10194,101.087334],[23.101749,101.084717],[23.101681,101.084343],[23.10136,101.08358],[23.095289,101.071663],[23.092871,101.062553],[23.09272,101.062317],[23.092489,101.062149],[23.088921,101.061073],[23.08243,101.056297],[23.0809,101.055191],[23.080441,101.055038],[23.078341,101.055092],[23.07649,101.055237],[23.07522,101.055809],[23.074841,101.05587],[23.074341,101.055779],[23.073879,101.055496],[23.073151,101.054863],[23.07061,101.053688],[23.070391,101.053497],[23.07021,101.053238],[23.069651,101.050728],[23.069481,101.050293],[23.06922,101.050041],[23.06679,101.048531],[23.066,101.048271],[23.06559,101.048264],[23.065319,101.048363],[23.0651,101.048523],[23.06461,101.048958],[23.06423,101.049133],[23.063789,101.049156],[23.063459,101.049057],[23.062389,101.048508],[23.059759,101.048233],[23.058189,101.048424],[23.057249,101.048233],[23.05648,101.047813],[23.055799,101.047012],[23.05534,101.046501],[23.055099,101.046356],[23.05422,101.046242],[23.04863,101.048233],[23.04837,101.04837],[23.047871,101.048431],[23.02458,101.048302],[23.024071,101.048157],[23.02363,101.047836],[23.02182,101.045883],[23.01825,101.044289],[23.017651,101.044228],[23.010521,101.045853],[23.01018,101.045998],[23.009899,101.046257],[23.009689,101.0466],[23.00923,101.047546],[23.00905,101.047729],[23.008829,101.047852],[23.008591,101.047897],[23.008221,101.047829],[23.0072,101.047447],[23.00699,101.04744],[23.00671,101.047546],[23.00486,101.049133],[23.004459,101.049347],[23.004141,101.049469],[23.003429,101.049538],[23.002609,101.049538],[23.001209,101.0495],[22.99102,101.050056],[22.990601,101.050232],[22.988979,101.051308],[22.986931,101.052177],[22.983101,101.053596],[22.98258,101.053596],[22.98111,101.053093],[22.980881,101.052917],[22.98064,101.052544],[22.98027,101.051727],[22.980181,101.051598],[22.979851,101.051323],[22.977791,101.050697],[22.977329,101.050682],[22.97683,101.050743],[22.97641,101.05069],[22.976101,101.050507],[22.97517,101.049477],[22.975031,101.049393],[22.97488,101.049339],[22.97471,101.049347],[22.97455,101.049408],[22.974409,101.049507],[22.974291,101.049789],[22.974131,101.051559],[22.973989,101.051819],[22.9736,101.052063],[22.97324,101.052071],[22.97154,101.051743],[22.97117,101.05188],[22.97064,101.052979],[22.9704,101.053261],[22.9699,101.053467],[22.969589,101.053482],[22.96904,101.053253],[22.967541,101.051788],[22.96735,101.051491],[22.967199,101.050926],[22.96707,101.050056],[22.966869,101.04985],[22.96673,101.049789],[22.966591,101.049767],[22.966249,101.049873],[22.96386,101.051697],[22.9636,101.05175],[22.963301,101.051643],[22.959089,101.045609],[22.956141,101.043243],[22.95582,101.042763],[22.95554,101.041786],[22.955561,101.041611],[22.955469,101.041199],[22.95533,101.040993],[22.955111,101.040871],[22.95499,101.04084],[22.95459,101.040916],[22.95439,101.041054],[22.95409,101.041618],[22.95377,101.042618],[22.953621,101.0429],[22.9533,101.043198],[22.95293,101.043343],[22.952551,101.043373],[22.95105,101.043114],[22.94944,101.042679],[22.94734,101.042618],[22.945259,101.041969],[22.943899,101.041206],[22.9433,101.0411],[22.94108,101.041023],[22.940371,101.040817],[22.93914,101.040337],[22.938881,101.040291],[22.937981,101.040459],[22.937111,101.040733],[22.936819,101.040688],[22.93659,101.040581],[22.9363,101.040291],[22.935471,101.038452],[22.934389,101.037483],[22.93408,101.036903],[22.933861,101.03627],[22.93358,101.035828],[22.930759,101.033897],[22.928329,101.0327],[22.92807,101.032654],[22.92779,101.032707],[22.925079,101.034653],[22.923201,101.035942],[22.92071,101.03714],[22.91906,101.038437],[22.918779,101.038589],[22.91832,101.038673],[22.913601,101.038834],[22.90958,101.038292],[22.909451,101.0383],[22.907591,101.039146],[22.90667,101.039864],[22.906139,101.040077],[22.903391,101.040199],[22.9011,101.039917],[22.899839,101.04007],[22.898951,101.040367],[22.894341,101.042671],[22.892481,101.043266],[22.89069,101.044769],[22.890381,101.04493],[22.89023,101.044968],[22.89006,101.044968],[22.88994,101.044899],[22.88973,101.04493],[22.885571,101.044243],[22.885229,101.044144],[22.884729,101.044144],[22.883869,101.044243],[22.882971,101.044228],[22.88155,101.043968],[22.879829,101.044067],[22.87952,101.044228],[22.87929,101.044434],[22.879181,101.044807],[22.87919,101.045258],[22.87907,101.045502],[22.878929,101.045624],[22.878759,101.045647],[22.87855,101.045624],[22.87825,101.045418],[22.87788,101.044594],[22.877769,101.044441],[22.87748,101.044289],[22.87735,101.044273],[22.87706,101.044327],[22.87561,101.045067],[22.87435,101.045563],[22.874069,101.045738],[22.873659,101.046143],[22.87348,101.046463],[22.873461,101.046783],[22.87372,101.047661],[22.873671,101.048126],[22.873381,101.048607],[22.8731,101.049057],[22.87294,101.049553],[22.872959,101.049843],[22.87299,101.051071],[22.873091,101.051468],[22.87307,101.051727],[22.872841,101.052048],[22.87248,101.052231],[22.872129,101.052238],[22.871901,101.052139],[22.871731,101.05201],[22.87158,101.051781],[22.87137,101.051331],[22.870871,101.050537],[22.87031,101.050301],[22.87015,101.050247],[22.86977,101.050247],[22.868971,101.05014],[22.868629,101.050194],[22.86834,101.050377],[22.86783,101.051132],[22.867571,101.051727],[22.86725,101.052254],[22.86702,101.052406],[22.866871,101.052437],[22.86664,101.052406],[22.8664,101.052299],[22.86628,101.0522],[22.86537,101.051041],[22.864679,101.049889],[22.864491,101.049759],[22.86417,101.04966],[22.863911,101.049744],[22.863689,101.049896],[22.86302,101.050751],[22.862921,101.050842],[22.8627,101.050903],[22.862459,101.050858],[22.862341,101.050789],[22.862141,101.050583],[22.86179,101.049911],[22.86162,101.049759],[22.861549,101.049652],[22.861429,101.049568],[22.861179,101.04953],[22.860901,101.049637],[22.86054,101.050079],[22.860201,101.050247],[22.85998,101.050201],[22.859751,101.050087],[22.85951,101.049782],[22.85891,101.049133],[22.858801,101.048973],[22.85874,101.048752],[22.85858,101.04847],[22.85841,101.047997],[22.858,101.047462],[22.857731,101.047256],[22.85655,101.046967],[22.8563,101.046959],[22.855829,101.046768],[22.85537,101.04673],[22.854799,101.046623],[22.85006,101.045921],[22.845831,101.044746],[22.84557,101.044601],[22.84523,101.044167],[22.84511,101.043877],[22.845091,101.043388],[22.845209,101.042717],[22.84556,101.04084],[22.84547,101.039772],[22.84502,101.038681],[22.84433,101.037338],[22.844259,101.03698],[22.84441,101.03569],[22.84409,101.032707],[22.843941,101.032372],[22.84374,101.032219],[22.843361,101.032143],[22.84267,101.032249],[22.842449,101.032204],[22.84227,101.032082],[22.84207,101.03154],[22.84198,101.029114],[22.842051,101.028877],[22.842239,101.02861],[22.84289,101.028084],[22.843069,101.027802],[22.843121,101.027473],[22.842661,101.025063],[22.84259,101.023514],[22.8423,101.022087],[22.842039,101.021744],[22.841921,101.021637],[22.840469,101.021187],[22.83992,101.020882],[22.839251,101.020699],[22.83877,101.020607],[22.83643,101.020943],[22.83602,101.020882],[22.83543,101.020538],[22.835251,101.02018],[22.835159,101.019417],[22.835239,101.019051],[22.835609,101.018333],[22.835791,101.017487],[22.83559,101.016022],[22.835461,101.015701],[22.835409,101.015404],[22.83482,101.014267],[22.83457,101.014038],[22.83433,101.013992],[22.833139,101.014503],[22.83259,101.014458],[22.831869,101.014343],[22.83053,101.014374],[22.830259,101.014282],[22.83005,101.014122],[22.82991,101.013893],[22.82984,101.013634],[22.829969,101.011917],[22.829901,101.011574],[22.829679,101.011261],[22.82835,101.010513],[22.82818,101.01033],[22.82806,101.010017],[22.828091,101.009712],[22.82819,101.009499],[22.828621,101.008827],[22.82872,101.008507],[22.828699,101.008148],[22.828489,101.007767],[22.828329,101.007561],[22.828199,101.007271],[22.82818,101.006958],[22.828251,101.006508],[22.82892,101.004562],[22.828939,101.004387],[22.82892,101.004211],[22.82877,101.003937],[22.828609,101.00386],[22.82851,101.003838],[22.827129,101.004417],[22.82692,101.004593],[22.8267,101.004982],[22.82649,101.006523],[22.82633,101.00679],[22.82616,101.006943],[22.82592,101.007004],[22.825689,101.006958],[22.82403,101.006088],[22.823681,101.00605],[22.82346,101.006119],[22.82337,101.006187],[22.82324,101.006432],[22.823219,101.006813],[22.82399,101.008453],[22.82399,101.008774],[22.823879,101.008957],[22.823681,101.009087],[22.82329,101.009109],[22.822479,101.008789],[22.8221,101.00872],[22.82177,101.008583],[22.821529,101.008583],[22.820789,101.008713],[22.81996,101.008583],[22.81974,101.008629],[22.81953,101.008781],[22.81933,101.009148],[22.819201,101.009819],[22.818939,101.010223],[22.81875,101.01033],[22.81855,101.010323],[22.81834,101.010223],[22.81811,101.009933],[22.81785,101.008659],[22.817579,101.008057],[22.817181,101.007607],[22.81698,101.007149],[22.816971,101.006393],[22.817101,101.005531],[22.81698,101.004761],[22.81669,101.004066],[22.81662,101.003967],[22.816351,101.003433],[22.816111,101.00322],[22.8158,101.003128],[22.815439,101.003159],[22.81422,101.003883],[22.813881,101.003998],[22.81366,101.004013],[22.813259,101.003754],[22.81312,101.00354],[22.813089,101.003281],[22.813181,101.002853],[22.813629,101.002243],[22.81424,101.001587],[22.814421,101.00119],[22.81451,100.999588],[22.81435,100.99884],[22.813931,100.997803],[22.81389,100.997131],[22.8141,100.995453],[22.81406,100.995247],[22.813869,100.99498],[22.81354,100.994713],[22.812071,100.994713],[22.811621,100.994812],[22.811399,100.994797],[22.811131,100.994667],[22.811001,100.994537],[22.810301,100.993599],[22.810169,100.99321],[22.809681,100.992577],[22.808121,100.991653],[22.80743,100.990997],[22.80442,100.986687],[22.803289,100.985558],[22.800989,100.9842],[22.79668,100.982613],[22.79608,100.982559],[22.795641,100.98262],[22.79413,100.983139],[22.79402,100.983147],[22.78949,100.984673],[22.78833,100.984734],[22.78718,100.984337],[22.786381,100.98378],[22.785009,100.982468],[22.783701,100.981873],[22.78307,100.981773],[22.778049,100.982323],[22.775881,100.981888],[22.773491,100.98156],[22.77161,100.981628],[22.770651,100.981438],[22.76981,100.98101],[22.769211,100.980476],[22.76837,100.979477],[22.76026,100.960899],[22.757999,100.955803],[22.757441,100.955391],[22.75708,100.955048],[22.75721,100.954697],[22.757549,100.954514],[22.75704,100.954567],[22.755301,100.954819],[22.75485,100.955139],[22.7547,100.95517],[22.75456,100.955002],[22.75416,100.954086],[22.7537,100.952957],[22.75363,100.952232],[22.753639,100.951859],[22.753731,100.95031],[22.75379,100.949226],[22.75386,100.948143],[22.753901,100.947762],[22.754181,100.947342],[22.754499,100.947273],[22.75466,100.947357],[22.75481,100.947609],[22.754841,100.947906],[22.754721,100.948082],[22.75465,100.948151],[22.75444,100.948288],[22.75411,100.948311],[22.753559,100.948311],[22.751921,100.947998],[22.75135,100.947693],[22.74992,100.946747],[22.74894,100.945709],[22.74827,100.944641],[22.74794,100.943817],[22.747869,100.943604],[22.747629,100.942703],[22.74728,100.940529],[22.747,100.939323],[22.746799,100.938171],[22.74645,100.937271],[22.74609,100.936653],[22.74593,100.936523],[22.74559,100.936256],[22.745041,100.935921],[22.744431,100.935699],[22.743589,100.935547],[22.74295,100.935478],[22.742531,100.935432],[22.742319,100.93541],[22.74148,100.935318],[22.740669,100.935219],[22.73987,100.935173],[22.73967,100.935181],[22.738371,100.935532],[22.737089,100.935951],[22.737221,100.937561],[22.736879,100.938103],[22.736759,100.93824],[22.736469,100.938568],[22.735411,100.939491],[22.735109,100.939758],[22.73385,100.938789],[22.73255,100.937866],[22.73188,100.937424],[22.7313,100.937263],[22.73031,100.937019],[22.72901,100.936897],[22.72834,100.93692],[22.727659,100.936996],[22.726971,100.937157],[22.72587,100.937553],[22.725189,100.937759],[22.72473,100.937843],[22.72377,100.937927],[22.723061,100.937889],[22.72282,100.937859],[22.72212,100.937721],[22.721439,100.937607],[22.72052,100.937538],[22.71982,100.937569],[22.718861,100.937721],[22.71837,100.937798],[22.71788,100.937851],[22.71763,100.937859],[22.716881,100.937851],[22.716391,100.937813],[22.715691,100.937683],[22.714161,100.937149],[22.71335,100.936859],[22.70923,100.935532],[22.706129,100.935272],[22.7059,100.935303],[22.70228,100.935913],[22.698429,100.936508],[22.697969,100.936501],[22.695841,100.935799],[22.69434,100.934319],[22.693859,100.933487],[22.692881,100.931847],[22.692579,100.931488],[22.69058,100.929947],[22.688129,100.929352],[22.687429,100.929367],[22.686251,100.929581],[22.68441,100.93026],[22.684179,100.930351],[22.6835,100.930618],[22.68281,100.93087],[22.681641,100.931152],[22.680941,100.93116],[22.68004,100.930992],[22.678801,100.930367],[22.67804,100.92984],[22.677851,100.92971],[22.675659,100.928902],[22.67326,100.929527],[22.673059,100.929657],[22.672211,100.930489],[22.671471,100.931808],[22.67083,100.933502],[22.67029,100.934967],[22.66975,100.936409],[22.669571,100.936882],[22.668791,100.938911],[22.668209,100.940453],[22.667789,100.941566],[22.667259,100.942947],[22.666759,100.944099],[22.666229,100.944946],[22.66468,100.94651],[22.664499,100.946678],[22.663601,100.9478],[22.6632,100.94841],[22.66169,100.949921],[22.661079,100.950256],[22.65884,100.951897],[22.65867,100.952042],[22.65498,100.95533],[22.652889,100.957962],[22.650261,100.962303],[22.649429,100.963142],[22.646749,100.965019],[22.64267,100.968117],[22.637991,100.972588],[22.635099,100.975403],[22.634501,100.975807],[22.63336,100.976723],[22.632851,100.977272],[22.63204,100.97821],[22.630671,100.979149],[22.62907,100.979347],[22.626699,100.979889],[22.62571,100.98082],[22.625561,100.981003],[22.625271,100.981339],[22.624451,100.982117],[22.621981,100.983459],[22.621571,100.983727],[22.62063,100.984596],[22.62031,100.985008],[22.619671,100.986153],[22.619551,100.986382],[22.61792,100.989319],[22.617081,100.990868],[22.616619,100.99173],[22.615801,100.99321],[22.615339,100.994034],[22.613991,100.99749],[22.61388,100.99794],[22.613501,101.000053],[22.613371,101.000763],[22.612659,101.004387],[22.612049,101.00573],[22.611759,101.006104],[22.610201,101.00721],[22.609751,101.007362],[22.607679,101.007797],[22.606541,101.008034],[22.605619,101.008209],[22.604639,101.006989],[22.60265,101.008003],[22.602079,101.008499],[22.601891,101.008682],[22.600941,101.009567],[22.60054,101.009903],[22.599701,101.010483],[22.599489,101.010628],[22.598221,101.011467],[22.59697,101.012291],[22.595961,101.013023],[22.5944,101.014282],[22.5931,101.015518],[22.59235,101.016289],[22.591801,101.016899],[22.591261,101.017517],[22.590919,101.01796],[22.59057,101.018387],[22.59005,101.01902],[22.589531,101.019653],[22.58902,101.020264],[22.58886,101.020462],[22.58802,101.021461],[22.58716,101.0224],[22.5863,101.023323],[22.5856,101.024063],[22.58543,101.024239],[22.58489,101.024803],[22.583969,101.025703],[22.583059,101.026604],[22.582319,101.027351],[22.58213,101.027542],[22.58135,101.02832],[22.580959,101.028717],[22.58037,101.029327],[22.579769,101.02993],[22.579161,101.03051],[22.578529,101.031021],[22.577629,101.031601],[22.576929,101.031967],[22.57407,101.032806],[22.57268,101.033127],[22.569481,101.033974],[22.566851,101.035629],[22.564631,101.038254],[22.562571,101.04084],[22.561569,101.042],[22.56105,101.042549],[22.55653,101.046677],[22.551979,101.050056],[22.549089,101.051498],[22.54871,101.051857],[22.547211,101.054031],[22.545851,101.055611],[22.54336,101.057426],[22.538851,101.060677],[22.536671,101.062241],[22.535339,101.063202],[22.53406,101.064117],[22.53334,101.064636],[22.533159,101.064774],[22.532261,101.065422],[22.530951,101.066353],[22.53075,101.06649],[22.52914,101.067642],[22.527901,101.068542],[22.52706,101.069153],[22.525999,101.069908],[22.52557,101.070213],[22.524731,101.070824],[22.523899,101.071411],[22.523279,101.071854],[22.52087,101.073593],[22.519039,101.074821],[22.515511,101.076576],[22.51333,101.077263],[22.51284,101.077393],[22.507811,101.078346],[22.502991,101.079971],[22.4993,101.081062],[22.49831,101.081284],[22.497311,101.081467],[22.49608,101.081688],[22.4951,101.081871],[22.49365,101.082123],[22.49098,101.082588],[22.49074,101.082626],[22.48781,101.08316],[22.48311,101.084023],[22.479179,101.084732],[22.47846,101.084869],[22.47751,101.085037],[22.47727,101.085091],[22.474871,101.085403],[22.472151,101.084801],[22.47193,101.084686],[22.469971,101.083214],[22.46851,101.081123],[22.46838,101.080887],[22.46525,101.076134],[22.46405,101.075218],[22.46118,101.073936],[22.46097,101.07383],[22.46055,101.073578],[22.46015,101.073303],[22.45813,101.071114],[22.454941,101.066788],[22.45241,101.063629],[22.451441,101.062912],[22.450809,101.062576],[22.450399,101.062378],[22.449249,101.061684],[22.44907,101.061531],[22.448311,101.060661],[22.44747,101.058617],[22.44726,101.057877],[22.447041,101.057114],[22.446621,101.055618],[22.44656,101.055382],[22.44626,101.054199],[22.446159,101.053268],[22.44618,101.052567],[22.446199,101.052338],[22.44644,101.051201],[22.44669,101.050537],[22.446791,101.050323],[22.44743,101.049301],[22.44944,101.047501],[22.45256,101.045052],[22.45421,101.043716],[22.45508,101.042671],[22.455469,101.041603],[22.45558,101.040413],[22.455441,101.039482],[22.455299,101.039047],[22.454571,101.037857],[22.453421,101.036743],[22.452419,101.035797],[22.451059,101.034531],[22.44902,101.032204],[22.448139,101.03109],[22.448,101.030907],[22.447321,101.030052],[22.446791,101.029404],[22.446239,101.028793],[22.445601,101.028267],[22.445089,101.027977],[22.44455,101.027733],[22.44379,101.027473],[22.442869,101.027039],[22.44202,101.026077],[22.441919,101.025887],[22.440689,101.022301],[22.439899,101.018692],[22.43993,101.01844],[22.44076,101.016403],[22.441521,101.014671],[22.441589,101.013519],[22.441429,101.012611],[22.441191,101.011757],[22.440969,101.010933],[22.44091,101.010727],[22.440741,101.010117],[22.44063,101.009697],[22.44046,101.009087],[22.440399,101.008888],[22.44026,101.008293],[22.43997,101.007103],[22.43926,101.005013],[22.438971,101.004204],[22.43878,101.003777],[22.43825,101.003036],[22.43762,101.002419],[22.437071,101.002037],[22.435881,101.001503],[22.43569,101.001411],[22.43453,101.000877],[22.432699,101.00032],[22.431379,100.999817],[22.429871,100.999237],[22.429649,100.999161],[22.42835,100.998688],[22.42729,100.998253],[22.425751,100.997887],[22.425079,100.997864],[22.424191,100.99781],[22.422859,100.997726],[22.42264,100.997711],[22.42198,100.997673],[22.42152,100.996429],[22.421169,100.995857],[22.420839,100.995033],[22.420691,100.994614],[22.420389,100.993767],[22.42004,100.992973],[22.41968,100.992416],[22.41955,100.992264],[22.41909,100.991814],[22.418539,100.991493],[22.41814,100.991341],[22.417721,100.991249],[22.416821,100.99128],[22.41659,100.991333],[22.414579,100.991943],[22.413879,100.992104],[22.41272,100.992363],[22.412491,100.992409],[22.412029,100.992523],[22.411489,100.99173],[22.410629,100.991402],[22.409349,100.990982],[22.408449,100.990921],[22.40686,100.991699],[22.406151,100.992973],[22.406,100.993713],[22.40591,100.994217],[22.40572,100.995506],[22.405109,100.997917],[22.40416,100.998901],[22.403561,100.999229],[22.40292,100.999512],[22.40205,100.999962],[22.40163,101.000214],[22.401421,101.000351],[22.400829,101.000778],[22.40065,101.000923],[22.399929,101.001457],[22.398781,101.001991],[22.39797,101.001999],[22.39777,101.001953],[22.39657,101.001633],[22.396379,101.001579],[22.39558,101.001373],[22.39538,101.001312],[22.39526,100.999611],[22.394581,100.999031],[22.39352,100.99868],[22.39287,100.998627],[22.39201,100.998672],[22.391159,100.998779],[22.390329,100.998871],[22.389509,100.99894],[22.38932,100.998947],[22.38833,100.999069],[22.38817,100.999077],[22.38769,100.999107],[22.386909,100.999184],[22.386049,100.999191],[22.385309,100.99913],[22.38492,100.999077],[22.384109,100.998894],[22.38331,100.998627],[22.38269,100.998428],[22.382271,100.998299],[22.38162,100.9981],[22.381399,100.998016],[22.379789,100.997589],[22.37746,100.997719],[22.37701,100.997803],[22.37565,100.99794],[22.374069,100.997757],[22.371149,100.996773],[22.36879,100.996872],[22.36677,100.998077],[22.36544,100.998917],[22.363939,100.999222],[22.36371,100.999207],[22.361771,100.998497],[22.361561,100.998383],[22.36068,100.997917],[22.35667,100.996277],[22.355659,100.996132],[22.35545,100.996094],[22.3552,100.996048],[22.35351,100.995506],[22.352989,100.995354],[22.35206,100.994911],[22.351191,100.9944],[22.350361,100.99382],[22.349239,100.992828],[22.3489,100.992477],[22.347679,100.990936],[22.34753,100.990723],[22.347231,100.990303],[22.3466,100.989418],[22.346451,100.989197],[22.345881,100.988319],[22.3456,100.987877],[22.344879,100.987053],[22.34469,100.986832],[22.3444,100.986397],[22.343929,100.985764],[22.34325,100.984917],[22.342899,100.98452],[22.34236,100.983963],[22.341551,100.983261],[22.341339,100.983093],[22.340931,100.982758],[22.340309,100.982277],[22.33968,100.98185],[22.33882,100.981354],[22.337931,100.980911],[22.337259,100.980621],[22.33658,100.980331],[22.335899,100.980011],[22.335011,100.979507],[22.334351,100.979088],[22.333929,100.978783],[22.333309,100.978302],[22.33271,100.977814],[22.332319,100.97747],[22.33115,100.976021],[22.33066,100.975357],[22.33033,100.974922],[22.32984,100.974281],[22.32935,100.97364],[22.328871,100.973007],[22.328541,100.972603],[22.328211,100.972168],[22.327511,100.971367],[22.32696,100.970787],[22.32638,100.970261],[22.325781,100.969727],[22.32449,100.968719],[22.323839,100.968231],[22.322981,100.967537],[22.32235,100.966988],[22.32173,100.966423],[22.32111,100.965813],[22.320511,100.965157],[22.31974,100.964256],[22.319361,100.963791],[22.319,100.963318],[22.31883,100.963081],[22.318489,100.962601],[22.318001,100.961853],[22.317539,100.961113],[22.31683,100.959846],[22.3167,100.959587],[22.316441,100.959053],[22.31583,100.95768],[22.315411,100.956596],[22.31521,100.956093],[22.314989,100.955597],[22.314751,100.955116],[22.31435,100.954437],[22.31389,100.953796],[22.31356,100.953377],[22.3132,100.953003],[22.313021,100.952812],[22.312639,100.952461],[22.312241,100.952141],[22.31143,100.951508],[22.310619,100.950844],[22.309799,100.950172],[22.30938,100.949837],[22.30875,100.949333],[22.30834,100.948967],[22.30776,100.948433],[22.307011,100.947678],[22.30665,100.947304],[22.30629,100.94693],[22.305771,100.946358],[22.30448,100.944847],[22.302361,100.942863],[22.30135,100.942192],[22.300039,100.941544],[22.29891,100.941139],[22.298679,100.941078],[22.29401,100.939636],[22.29364,100.939407],[22.29315,100.939018],[22.292601,100.938454],[22.292191,100.937828],[22.291941,100.937363],[22.29166,100.936699],[22.29142,100.936028],[22.291241,100.935516],[22.291,100.934837],[22.290689,100.933968],[22.29043,100.933243],[22.290171,100.932518],[22.289909,100.931793],[22.28965,100.931053],[22.28944,100.930489],[22.289181,100.929733],[22.288919,100.92897],[22.288719,100.928398],[22.288429,100.927658],[22.288191,100.927109],[22.28772,100.926224],[22.28751,100.925888],[22.28701,100.925056],[22.286711,100.924561],[22.286501,100.924217],[22.2857,100.922897],[22.283091,100.922768],[22.2829,100.922638],[22.282551,100.92234],[22.282061,100.921547],[22.28171,100.920723],[22.281401,100.919838],[22.28109,100.919243],[22.280649,100.918709],[22.280479,100.918556],[22.279711,100.918083],[22.27906,100.917793],[22.27845,100.917397],[22.27788,100.916908],[22.27706,100.91597],[22.276711,100.915627],[22.27635,100.915314],[22.275961,100.915047],[22.275339,100.914749],[22.274691,100.91449],[22.27426,100.914291],[22.273479,100.913727],[22.27298,100.913193],[22.27249,100.912582],[22.271811,100.911751],[22.271299,100.911133],[22.2708,100.9105],[22.270121,100.909691],[22.269621,100.909081],[22.26911,100.908478],[22.2686,100.907867],[22.267941,100.907059],[22.26745,100.906471],[22.26729,100.906281],[22.266529,100.905327],[22.26638,100.905159],[22.266109,100.904793],[22.265181,100.903084],[22.26512,100.902878],[22.26486,100.901817],[22.264759,100.901176],[22.264681,100.900543],[22.26461,100.900162],[22.264441,100.899437],[22.264219,100.898758],[22.264151,100.89859],[22.263769,100.897781],[22.262951,100.896568],[22.26133,100.89476],[22.25939,100.892632],[22.257799,100.890877],[22.25618,100.889526],[22.254049,100.888847],[22.252899,100.888924],[22.249889,100.889832],[22.24725,100.890663],[22.24247,100.892181],[22.24225,100.89225],[22.241619,100.892464],[22.240801,100.892723],[22.240601,100.892776],[22.239651,100.893082],[22.23909,100.89325],[22.237379,100.893532],[22.23546,100.892883],[22.233191,100.891357],[22.23279,100.891243],[22.229931,100.891037],[22.227671,100.891037],[22.22744,100.891037],[22.22624,100.890999],[22.226,100.890961],[22.22529,100.890846],[22.224819,100.890739],[22.222071,100.889473],[22.221689,100.889198],[22.220579,100.88842],[22.217211,100.886803],[22.216749,100.886673],[22.21537,100.886177],[22.215151,100.88607],[22.213539,100.884918],[22.21335,100.884743],[22.21269,100.883972],[22.211559,100.88224],[22.21076,100.881287],[22.209181,100.880188],[22.20785,100.879623],[22.20566,100.878441],[22.20363,100.876953],[22.20343,100.876793],[22.20179,100.875679],[22.20072,100.875061],[22.199169,100.874298],[22.19618,100.873253],[22.19453,100.872864],[22.192659,100.872551],[22.191271,100.872337],[22.189659,100.872108],[22.18873,100.872002],[22.18466,100.871529],[22.184441,100.871552],[22.18379,100.871658],[22.18276,100.872009],[22.18195,100.872292],[22.181749,100.872353],[22.18115,100.872498],[22.18075,100.872551],[22.17971,100.872528],[22.1782,100.872253],[22.17522,100.871643],[22.17458,100.871513],[22.1733,100.871239],[22.172661,100.871101],[22.17029,100.87149],[22.168579,100.872566],[22.16478,100.875488],[22.164101,100.877136],[22.164101,100.878738],[22.16431,100.880547],[22.163891,100.882553],[22.162741,100.884567],[22.16111,100.888344],[22.15967,100.889977],[22.15947,100.890106],[22.15798,100.8908],[22.156429,100.891068],[22.154831,100.890587],[22.15423,100.890297],[22.15365,100.889992],[22.15346,100.889893],[22.15308,100.889687],[22.1521,100.889374],[22.1511,100.889267],[22.1509,100.889297],[22.15032,100.889381],[22.149731,100.889503],[22.1486,100.889763],[22.147829,100.889931],[22.146811,100.890137],[22.146601,100.890182],[22.1453,100.890213],[22.1434,100.889481],[22.141661,100.88871],[22.14024,100.888573],[22.13888,100.88858],[22.13842,100.888573],[22.136339,100.888329],[22.13586,100.888229],[22.13463,100.888077],[22.133619,100.88813],[22.133141,100.88826],[22.132429,100.888542],[22.13179,100.888947],[22.13122,100.889442],[22.13084,100.889793],[22.130289,100.890343],[22.13011,100.890518],[22.129749,100.890877],[22.12937,100.891243],[22.12919,100.891434],[22.128811,100.891777],[22.128059,100.892509],[22.12748,100.893066],[22.127279,100.893272],[22.12668,100.893837],[22.125839,100.894562],[22.125389,100.894897],[22.124491,100.895523],[22.12426,100.895668],[22.123569,100.896049],[22.12311,100.896271],[22.122881,100.896378],[22.121969,100.896767],[22.12151,100.896927],[22.121059,100.897087],[22.120359,100.897293],[22.1199,100.8974],[22.119209,100.897537],[22.118031,100.897697],[22.117319,100.897758],[22.117081,100.897774],[22.116381,100.897797],[22.115919,100.897781],[22.115219,100.897751],[22.114771,100.897697],[22.11454,100.897667],[22.113411,100.897438],[22.113171,100.897377],[22.112221,100.897087],[22.1113,100.896767],[22.109541,100.896072],[22.109329,100.896004],[22.108931,100.895844],[22.107821,100.895363],[22.10671,100.894867],[22.1063,100.894707],[22.105659,100.894447],[22.104509,100.894028],[22.10401,100.893913],[22.102751,100.893784],[22.102249,100.893806],[22.10034,100.894386],[22.09577,100.896683],[22.09535,100.896889],[22.09514,100.897003],[22.091,100.899063],[22.09016,100.899467],[22.08934,100.899872],[22.0875,100.90078],[22.086281,100.901398],[22.086069,100.901497],[22.084459,100.90229],[22.082359,100.903587],[22.08218,100.90374],[22.080879,100.904747],[22.08029,100.905144],[22.079691,100.905487],[22.07802,100.906349],[22.076559,100.907097],[22.074671,100.908073],[22.074459,100.90818],[22.07284,100.909088],[22.072651,100.909233],[22.071779,100.910347],[22.07155,100.911049],[22.07114,100.91275],[22.07007,100.914352],[22.06971,100.914612],[22.06798,100.915222],[22.06732,100.915314],[22.06707,100.915398],[22.067011,100.915398],[22.066839,100.915367],[22.06671,100.915428],[22.06671,100.915428],[22.066191,100.915527],[22.065809,100.915627],[22.065701,100.915657],[22.0648,100.915863],[22.064171,100.915993],[22.06389,100.916054],[22.063181,100.916206],[22.06303,100.916252],[22.06241,100.916389],[22.06175,100.916527],[22.061239,100.916649],[22.059919,100.916832],[22.05904,100.916962],[22.05825,100.916946],[22.05735,100.916603],[22.05529,100.916061],[22.052691,100.91539],[22.043591,100.899223],[22.04199,100.896301],[22.040911,100.894302],[22.04068,100.893753],[22.04048,100.893158],[22.040251,100.892387],[22.04018,100.892197],[22.03977,100.891548],[22.039471,100.891258],[22.03857,100.890778],[22.03838,100.890678],[22.037889,100.890312],[22.037439,100.889587],[22.037371,100.889359],[22.03727,100.888687],[22.03849,100.887321],[22.038231,100.886932],[22.03797,100.886543],[22.03784,100.886353],[22.037319,100.885567],[22.03694,100.884987],[22.0368,100.884804],[22.03665,100.884613],[22.03618,100.885109],[22.035931,100.885269],[22.03573,100.885452],[22.035629,100.886169],[22.035851,100.886627],[22.036329,100.887131],[22.03694,100.887589],[22.037371,100.887947],[22.037769,100.888542],[22.038059,100.889397],[22.038601,100.890022],[22.038759,100.890091],[22.03908,100.890213],[22.039551,100.890381],[22.039709,100.890427],[22.040171,100.890617],[22.04055,100.890907],[22.04085,100.891487],[22.04088,100.891983],[22.040859,100.892303],[22.041019,100.893082],[22.04133,100.893448],[22.04187,100.893829],[22.042009,100.893929],[22.04236,100.894287],[22.042669,100.894897],[22.042761,100.895416],[22.04281,100.89608],[22.04302,100.896843],[22.043171,100.8974],[22.043329,100.897919],[22.04336,100.898033],[22.04343,100.898308],[22.043329,100.898941],[22.043221,100.899231],[22.04311,100.89959],[22.04307,100.899696],[22.042959,100.900017],[22.042801,100.900459],[22.04266,100.901329],[22.04273,100.901848],[22.042891,100.902496],[22.043011,100.903023],[22.04307,100.90329],[22.0431,100.903831],[22.04306,100.904114],[22.04298,100.904373],[22.042709,100.904846],[22.0425,100.905212],[22.042471,100.90583],[22.042601,100.906067],[22.042801,100.906258],[22.043329,100.906708],[22.04343,100.906807],[22.0436,100.907654],[22.04347,100.907928],[22.0432,100.908363],[22.042931,100.908813],[22.042509,100.909538],[22.042471,100.910461],[22.0427,100.910889],[22.042801,100.911018],[22.04372,100.911949],[22.043859,100.912079],[22.044359,100.912582],[22.04472,100.913528],[22.04451,100.913986],[22.04413,100.91433],[22.043119,100.915154],[22.04287,100.915573],[22.04269,100.916199],[22.04266,100.916359],[22.042521,100.917137],[22.04232,100.917717],[22.042139,100.918114],[22.04208,100.918228],[22.041771,100.919312],[22.041821,100.920036],[22.041901,100.920273],[22.04212,100.920998],[22.041929,100.921722],[22.041439,100.922592],[22.04129,100.924171],[22.04126,100.92466],[22.04137,100.925926],[22.041439,100.926308],[22.0415,100.928253],[22.041519,100.929138],[22.04121,100.929947],[22.0408,100.930191],[22.038839,100.931381],[22.03824,100.932617],[22.03816,100.932838],[22.03783,100.933723],[22.0376,100.93438],[22.03727,100.935242],[22.037001,100.935867],[22.03648,100.936867],[22.035589,100.938187],[22.03503,100.938904],[22.03474,100.939247],[22.03359,100.940689],[22.03301,100.941406],[22.032301,100.942299],[22.031099,100.943787],[22.03026,100.94487],[22.029539,100.945839],[22.029261,100.946281],[22.029091,100.946602],[22.02861,100.94767],[22.028391,100.948227],[22.02833,100.948433],[22.02803,100.949387],[22.02774,100.950394],[22.027679,100.950592],[22.02737,100.95163],[22.027,100.952888],[22.026939,100.953102],[22.0266,100.954163],[22.026011,100.955406],[22.02549,100.956146],[22.02519,100.956497],[22.02504,100.956673],[22.02302,100.958931],[22.02248,100.959717],[22.02177,100.960983],[22.021351,100.961884],[22.021231,100.962097],[22.020651,100.963203],[22.019051,100.965302],[22.01857,100.965767],[22.017229,100.967117],[22.016939,100.967453],[22.01679,100.967613],[22.016109,100.968483],[22.01552,100.96946],[22.015409,100.969658],[22.015011,100.970444],[22.01482,100.970802],[22.014271,100.971931],[22.014071,100.972328],[22.013821,100.972816],[22.013639,100.97316],[22.01335,100.973732],[22.01317,100.974136],[22.01281,100.974823],[22.011311,100.976913],[22.011169,100.977074],[22.010731,100.977562],[22.01045,100.97789],[22.010059,100.978409],[22.00983,100.978767],[22.00942,100.979523],[22.00905,100.980263],[22.0086,100.981056],[22.008369,100.981331],[22.00786,100.981812],[22.007601,100.982002],[22.007469,100.982094],[22.00699,100.982437],[22.006559,100.982841],[22.00647,100.982948],[22.005951,100.983681],[22.005751,100.9841],[22.005449,100.985153],[22.005381,100.985611],[22.00523,100.986397],[22.0049,100.987267],[22.00474,100.987556],[22.00428,100.98819],[22.00396,100.988487],[22.003151,100.989082],[22.00243,100.989517],[22.001011,100.990921],[22.000919,100.991051],[22.000191,100.992073],[21.99983,100.992554],[21.99975,100.992683],[21.999149,100.993523],[21.99906,100.993629],[21.998871,100.993843],[21.99811,100.994507],[21.99707,100.995071],[21.99651,100.995293],[21.995951,100.995506],[21.995399,100.995743],[21.99486,100.995956],[21.99436,100.996239],[21.992809,100.99765],[21.992701,100.99781],[21.99198,100.998779],[21.99185,100.998947],[21.99131,100.999641],[21.99102,100.999992],[21.990459,101.000717],[21.9888,101.00293],[21.98838,101.003487],[21.98786,101.003998],[21.987049,101.004883],[21.98671,101.005211],[21.986349,101.005539],[21.986179,101.005699],[21.98562,101.006172],[21.98525,101.006493],[21.984249,101.007271],[21.983841,101.007568],[21.98321,101.008003],[21.98258,101.008438],[21.98197,101.008873],[21.98177,101.009018],[21.98078,101.009811],[21.97967,101.010818],[21.976709,101.013283],[21.97607,101.013962],[21.975679,101.014252],[21.97489,101.014801],[21.97427,101.015198],[21.973869,101.015503],[21.973471,101.015793],[21.973101,101.016113],[21.97262,101.016701],[21.97249,101.016899],[21.97216,101.017563],[21.972071,101.017776],[21.971621,101.01918],[21.97146,101.019653],[21.971149,101.020576],[21.970921,101.021278],[21.97084,101.021507],[21.9706,101.022209],[21.97053,101.022453],[21.970289,101.02314],[21.970209,101.023376],[21.96982,101.024544],[21.969509,101.025467],[21.96785,101.026176],[21.967251,101.026573],[21.96661,101.026871],[21.966169,101.027061],[21.965309,101.027412],[21.96509,101.027496],[21.96422,101.027847],[21.964001,101.027946],[21.96335,101.028214],[21.9627,101.028503],[21.96207,101.028816],[21.961081,101.02951],[21.959749,101.030479],[21.95956,101.030617],[21.95937,101.031616],[21.95859,101.033081],[21.95812,101.034248],[21.95792,101.034698],[21.957279,101.035843],[21.956381,101.037048],[21.95595,101.037666],[21.95558,101.038307],[21.955469,101.038544],[21.955259,101.038979],[21.95509,101.039436],[21.954941,101.039902],[21.954729,101.040619],[21.95439,101.041817],[21.95418,101.042542],[21.95396,101.043243],[21.953409,101.044312],[21.953291,101.04451],[21.95188,101.046097],[21.95171,101.046272],[21.950581,101.047478],[21.95042,101.047653],[21.94935,101.048798],[21.94685,101.05146],[21.946529,101.051804],[21.94636,101.051964],[21.94483,101.053726],[21.94429,101.054443],[21.943529,101.055481],[21.943279,101.055817],[21.942329,101.057137],[21.942209,101.057312],[21.941851,101.0578],[21.941481,101.058273],[21.94095,101.058861],[21.940399,101.059402],[21.940269,101.05954],[21.939581,101.060219],[21.93902,101.060753],[21.93784,101.061127],[21.936701,101.061577],[21.93651,101.061684],[21.935301,101.062218],[21.933491,101.063057],[21.933109,101.063278],[21.930639,101.065109],[21.929501,101.066231],[21.92934,101.066391],[21.92901,101.066727],[21.92783,101.067917],[21.926649,101.069092],[21.925051,101.07045],[21.923241,101.071693],[21.921989,101.072533],[21.92062,101.073593],[21.92009,101.074112],[21.919189,101.075279],[21.917681,101.078453],[21.91642,101.081444],[21.916321,101.081673],[21.91571,101.083008],[21.915051,101.084587],[21.914379,101.087097],[21.914391,101.08876],[21.91444,101.089287],[21.914471,101.089722],[21.91452,101.090286],[21.914539,101.090439],[21.914579,101.091003],[21.914721,101.092216],[21.91493,101.095016],[21.91506,101.097748],[21.915051,101.103523],[21.914909,101.107643],[21.9149,101.107872],[21.914909,101.109596],[21.91526,101.113564],[21.91547,101.115044],[21.915751,101.11705],[21.915939,101.118347],[21.915991,101.118874],[21.916019,101.119141],[21.916071,101.119949],[21.91601,101.121269],[21.9158,101.122299],[21.915449,101.123268],[21.91511,101.123947],[21.914339,101.125504],[21.913811,101.127823],[21.91431,101.129951],[21.9146,101.13063],[21.91634,101.134247],[21.91654,101.134712],[21.91663,101.134933],[21.91839,101.139374],[21.918449,101.139603],[21.918631,101.140579],[21.91876,101.14238],[21.918859,101.14476],[21.9189,101.145813],[21.91894,101.146584],[21.918949,101.147102],[21.91897,101.147614],[21.91897,101.147873],[21.918949,101.148628],[21.91885,101.149399],[21.91869,101.150139],[21.918539,101.150879],[21.918449,101.151123],[21.91787,101.151672],[21.91713,101.152397],[21.914841,101.154327],[21.914499,101.154694],[21.914339,101.154877],[21.91366,101.155952],[21.913231,101.156891],[21.912741,101.158127],[21.91255,101.158638],[21.912081,101.159897],[21.911791,101.160652],[21.911501,101.1614],[21.911221,101.16214],[21.910749,101.163353],[21.910561,101.163811],[21.91011,101.164993],[21.909559,101.166382],[21.90947,101.166618],[21.90922,101.167343],[21.908661,101.170502],[21.908001,101.175049],[21.90786,101.175529],[21.907351,101.177269],[21.9072,101.177757],[21.90691,101.178757],[21.90649,101.180817],[21.906509,101.182121],[21.906549,101.182381],[21.90708,101.184097],[21.90826,101.186363],[21.90966,101.189034],[21.909769,101.189247],[21.911289,101.191254],[21.91147,101.191406],[21.912081,101.191833],[21.91445,101.193123],[21.91466,101.193253],[21.91526,101.193687],[21.916121,101.194618],[21.91687,101.195992],[21.91704,101.196457],[21.91711,101.196709],[21.91733,101.197769],[21.9175,101.198914],[21.917601,101.199783],[21.91777,101.200951],[21.91785,101.201508],[21.917971,101.202339],[21.918619,101.205002],[21.918949,101.20575],[21.92004,101.207611],[21.92045,101.208313],[21.920891,101.209213],[21.92137,101.210838],[21.92153,101.212631],[21.92156,101.213158],[21.921659,101.215263],[21.922371,101.219688],[21.922689,101.220886],[21.922979,101.221992],[21.92321,101.222763],[21.92333,101.223259],[21.923441,101.223701],[21.92392,101.226082],[21.92395,101.22644],[21.923969,101.226624],[21.923981,101.227013],[21.923981,101.227837],[21.923941,101.228706],[21.92392,101.228943],[21.9238,101.23037],[21.92371,101.231903],[21.923519,101.233963],[21.92304,101.239906],[21.92206,101.242363],[21.920389,101.244179],[21.920219,101.24437],[21.91906,101.246536],[21.918921,101.247253],[21.918831,101.249329],[21.918831,101.250221],[21.91881,101.250877],[21.91881,101.251099],[21.91873,101.252403],[21.918659,101.252838],[21.917749,101.255157],[21.91548,101.257736],[21.9149,101.258217],[21.9147,101.258377],[21.913401,101.259087],[21.912701,101.259354],[21.91222,101.259483],[21.910749,101.259811],[21.909769,101.26001],[21.90855,101.260277],[21.904751,101.261467],[21.904381,101.261726],[21.90402,101.262016],[21.902321,101.264214],[21.90143,101.265541],[21.90106,101.26609],[21.90019,101.267357],[21.89957,101.26825],[21.899309,101.26857],[21.898569,101.269302],[21.897261,101.269974],[21.89506,101.26992],[21.89484,101.269852],[21.89373,101.269432],[21.89328,101.269257],[21.89189,101.268799],[21.889059,101.268402],[21.88468,101.268173],[21.88446,101.26815],[21.880329,101.268433],[21.87883,101.269524],[21.87771,101.271393],[21.87731,101.273888],[21.87648,101.276787],[21.874929,101.278214],[21.8743,101.278458],[21.87303,101.278679],[21.872,101.278687],[21.871189,101.278717],[21.870171,101.278763],[21.868931,101.278839],[21.868509,101.278893],[21.86767,101.279099],[21.86746,101.279167],[21.86684,101.279404],[21.866631,101.279488],[21.864929,101.280167],[21.86426,101.280296],[21.86335,101.280312],[21.86289,101.280228],[21.86204,101.279892],[21.861469,101.279503],[21.860571,101.278488],[21.85997,101.277496],[21.85952,101.276718],[21.859289,101.276337],[21.85895,101.275749],[21.858391,101.274803],[21.85804,101.274223],[21.857809,101.273827],[21.857309,101.273087],[21.85689,101.272568],[21.856409,101.272102],[21.855659,101.271606],[21.855261,101.271423],[21.85461,101.271233],[21.854389,101.271179],[21.853291,101.271133],[21.852421,101.27121],[21.851561,101.271378],[21.851351,101.271423],[21.85051,101.271637],[21.849689,101.27195],[21.84889,101.272293],[21.8487,101.272392],[21.848129,101.272713],[21.847771,101.272957],[21.847429,101.273247],[21.84683,101.273911],[21.84646,101.274467],[21.846029,101.275543],[21.84589,101.276451],[21.845881,101.276939],[21.845921,101.277412],[21.84621,101.278847],[21.84626,101.279083],[21.846439,101.280022],[21.846581,101.280724],[21.84668,101.281174],[21.846979,101.282547],[21.847031,101.282784],[21.84713,101.283241],[21.847349,101.284653],[21.847349,101.285362],[21.8473,101.285828],[21.847019,101.286682],[21.84655,101.287537],[21.846081,101.288116],[21.84572,101.288437],[21.844709,101.288986],[21.844259,101.28907],[21.84314,101.2892],[21.842449,101.289177],[21.84178,101.289192],[21.840891,101.289299],[21.840441,101.289413],[21.83959,101.289742],[21.838961,101.290031],[21.838329,101.290314],[21.83728,101.290787],[21.83707,101.290894],[21.836439,101.291168],[21.83539,101.291641],[21.83518,101.291733],[21.837179,101.294617],[21.83725,101.295601],[21.837299,101.296066],[21.837339,101.296532],[21.83736,101.296997],[21.837311,101.297943],[21.83708,101.298828],[21.836729,101.299622],[21.836349,101.300133],[21.835699,101.300697],[21.83474,101.301224],[21.833679,101.301613],[21.832809,101.301918],[21.832371,101.302078],[21.83148,101.302383],[21.83082,101.302612],[21.829941,101.302917],[21.82951,101.303078],[21.82864,101.303383],[21.82777,101.303688],[21.827339,101.303841],[21.827129,101.303917],[21.82626,101.304222],[21.825411,101.304497],[21.82457,101.304688],[21.82436,101.304718],[21.823521,101.304771],[21.822651,101.304733],[21.822201,101.30468],[21.821079,101.304573],[21.82085,101.304527],[21.819771,101.304443],[21.81955,101.304428],[21.81811,101.304497],[21.81752,101.30468],[21.816549,101.305153],[21.81568,101.305801],[21.815121,101.306473],[21.81469,101.307243],[21.81444,101.307861],[21.81424,101.308502],[21.81418,101.308723],[21.81395,101.309578],[21.8139,101.309792],[21.81373,101.310448],[21.81356,101.311096],[21.81325,101.31218],[21.81319,101.312401],[21.81284,101.313881],[21.81263,101.31456],[21.8123,101.315376],[21.81167,101.316238],[21.81151,101.316383],[21.81098,101.31675],[21.810591,101.316917],[21.80978,101.317047],[21.808729,101.316933],[21.808331,101.316833],[21.80751,101.316612],[21.80731,101.316551],[21.806709,101.316383],[21.806101,101.316223],[21.8053,101.316002],[21.804489,101.315781],[21.804079,101.315666],[21.80308,101.315407],[21.802679,101.315308],[21.80188,101.315117],[21.801279,101.31498],[21.80068,101.314873],[21.79945,101.314781],[21.79841,101.314857],[21.798201,101.314888],[21.797569,101.315033],[21.795139,101.316109],[21.793831,101.316849],[21.792339,101.317703],[21.79178,101.318008],[21.789539,101.319283],[21.78265,101.342934],[21.78219,101.344131],[21.781931,101.34478],[21.781851,101.344978],[21.781731,101.345337],[21.781601,101.345802],[21.781321,101.347321],[21.781321,101.348717],[21.78134,101.348991],[21.78142,101.349808],[21.781549,101.350937],[21.78159,101.351227],[21.781731,101.352409],[21.78182,101.353279],[21.781839,101.353569],[21.781839,101.354141],[21.781771,101.35498],[21.78137,101.356293],[21.78125,101.356529],[21.780661,101.357407],[21.780331,101.357803],[21.780149,101.357986],[21.779631,101.35849],[21.77928,101.35881],[21.778761,101.359261],[21.778431,101.359573],[21.77767,101.360451],[21.77689,101.361717],[21.77639,101.362892],[21.776091,101.363632],[21.7756,101.364861],[21.77527,101.365578],[21.77515,101.365807],[21.774731,101.366463],[21.77421,101.367027],[21.77383,101.36734],[21.773621,101.36747],[21.77272,101.367897],[21.77083,101.368332],[21.770361,101.368439],[21.768511,101.368843],[21.76614,101.369759],[21.765829,101.370018],[21.765699,101.370163],[21.7647,101.371513],[21.764299,101.372093],[21.763041,101.37394],[21.76263,101.374557],[21.762211,101.375183],[21.76193,101.375603],[21.7612,101.375648],[21.75919,101.376251],[21.757509,101.376091],[21.7568,101.375893],[21.75511,101.375412],[21.754869,101.375359],[21.75362,101.375191],[21.752081,101.375168],[21.75131,101.375191],[21.750299,101.375198],[21.749281,101.375198],[21.748529,101.375168],[21.74777,101.37513],[21.74675,101.375053],[21.745741,101.374924],[21.745489,101.374878],[21.744989,101.374809],[21.74449,101.374741],[21.74399,101.37468],[21.74349,101.374619],[21.74324,101.374588],[21.74173,101.374428],[21.74098,101.374313],[21.73995,101.374153],[21.738661,101.373993],[21.73815,101.373947],[21.737619,101.373917],[21.736851,101.373947],[21.73633,101.374008],[21.735069,101.374283],[21.73406,101.37468],[21.73381,101.374786],[21.73307,101.375107],[21.73283,101.375229],[21.73185,101.375648],[21.7311,101.375923],[21.730591,101.376083],[21.7293,101.376266],[21.728769,101.376282],[21.727711,101.376221],[21.72718,101.37619],[21.72665,101.376152],[21.72613,101.376167],[21.725349,101.376213],[21.724819,101.376312],[21.72456,101.376373],[21.72378,101.376556],[21.723,101.376747],[21.72221,101.3769],[21.720619,101.37709],[21.71957,101.377083],[21.718781,101.377083],[21.718,101.37706],[21.71748,101.377029],[21.71697,101.377022],[21.715139,101.376961],[21.71434,101.37693],[21.713289,101.376907],[21.712761,101.376877],[21.712231,101.376862],[21.71196,101.376839],[21.71143,101.376793],[21.71064,101.376678],[21.710131,101.376579],[21.709869,101.376511],[21.708151,101.375938],[21.707439,101.375671],[21.70673,101.375397],[21.70648,101.375298],[21.705759,101.375038],[21.70479,101.374771],[21.70454,101.374733],[21.703791,101.374649],[21.703541,101.374641],[21.70084,101.374786],[21.699369,101.374687],[21.696461,101.374207],[21.69548,101.374046],[21.694759,101.373917],[21.69404,101.373779],[21.692101,101.373558],[21.68832,101.373627],[21.68716,101.373703],[21.68671,101.373718],[21.68626,101.373734],[21.68581,101.373756],[21.684259,101.373848],[21.68294,101.373917],[21.68227,101.373962],[21.68181,101.373993],[21.677691,101.374207],[21.6772,101.374252],[21.67627,101.37429],[21.67564,101.374329],[21.675261,101.374352],[21.674931,101.374367],[21.674431,101.374397],[21.674231,101.374382],[21.67403,101.374367],[21.673719,101.374367],[21.67363,101.374397],[21.67362,101.374397],[21.673281,101.374443],[21.672291,101.374519],[21.672041,101.374527],[21.669769,101.374817],[21.668909,101.374962],[21.66818,101.375053],[21.667589,101.375069],[21.66655,101.374992],[21.66567,101.37484],[21.66522,101.374733],[21.66452,101.374573],[21.66358,101.374336],[21.662609,101.374107],[21.660681,101.37365],[21.66044,101.373596],[21.65901,101.37326],[21.658279,101.373192],[21.65803,101.373199],[21.65778,101.37323],[21.65707,101.373413],[21.656429,101.373741],[21.65411,101.375397],[21.65262,101.376442],[21.651871,101.376961],[21.651131,101.37748],[21.649639,101.378517],[21.64854,101.379333],[21.648359,101.379478],[21.647209,101.38092],[21.64658,101.382469],[21.646481,101.382919],[21.646391,101.383598],[21.64636,101.384529],[21.64633,101.385681],[21.646311,101.386139],[21.646299,101.386581],[21.64628,101.387253],[21.64625,101.388138],[21.64624,101.38858],[21.646231,101.389023],[21.646259,101.389893],[21.646299,101.390961],[21.64636,101.391586],[21.646391,101.392227],[21.64641,101.392662],[21.646429,101.392883],[21.646481,101.394188],[21.646429,101.395058],[21.646339,101.395477],[21.646061,101.396561],[21.645821,101.3974],[21.64576,101.397614],[21.645651,101.398033],[21.64547,101.398666],[21.64535,101.399094],[21.64529,101.3993],[21.645109,101.399933],[21.64506,101.400139],[21.643129,101.399544],[21.64254,101.399788],[21.6415,101.400208],[21.640881,101.400436],[21.639811,101.400787],[21.639601,101.400864],[21.639179,101.400993],[21.638599,101.401253],[21.63805,101.401588],[21.637421,101.402153],[21.63689,101.402802],[21.636669,101.403191],[21.63641,101.40377],[21.63624,101.404167],[21.63607,101.404556],[21.63582,101.405159],[21.635731,101.405357],[21.635389,101.406151],[21.635139,101.406754],[21.6348,101.407539],[21.63463,101.407944],[21.63438,101.408531],[21.634041,101.409317],[21.633869,101.409721],[21.638929,101.41069],[21.6392,101.411049],[21.63945,101.411423],[21.639811,101.411957],[21.64032,101.412682],[21.64068,101.413223],[21.641041,101.41375],[21.641399,101.414284],[21.641649,101.414627],[21.641899,101.414993],[21.64266,101.416107],[21.643089,101.416939],[21.64325,101.417381],[21.643419,101.418068],[21.643499,101.418533],[21.6436,101.419006],[21.64378,101.41996],[21.64397,101.420914],[21.64411,101.421623],[21.644251,101.42234],[21.64114,101.423126],[21.640671,101.423347],[21.64003,101.423569],[21.63954,101.423698],[21.63903,101.423843],[21.6387,101.423912],[21.638,101.424049],[21.6373,101.424187],[21.63678,101.424309],[21.63625,101.424438],[21.634991,101.424744],[21.63446,101.424873],[21.63378,101.425079],[21.63345,101.425209],[21.632799,101.425537],[21.632339,101.42585],[21.631901,101.426201],[21.63147,101.426613],[21.631081,101.42704],[21.630831,101.427322],[21.630569,101.427612],[21.63015,101.427834],[21.62956,101.42836],[21.62854,101.429283],[21.628099,101.42968],[21.62752,101.430206],[21.62678,101.430862],[21.618349,101.454582],[21.618311,101.454857],[21.61771,101.456886],[21.616671,101.45816],[21.61628,101.458443],[21.615459,101.458977],[21.61483,101.459373],[21.613991,101.459908],[21.61311,101.46048],[21.61268,101.460747],[21.61224,101.460999],[21.61179,101.461197],[21.610849,101.461502],[21.6096,101.461723],[21.60911,101.4618],[21.60862,101.461884],[21.60788,101.462013],[21.606421,101.462273],[21.6057,101.462334],[21.60523,101.462303],[21.60499,101.46225],[21.604521,101.46212],[21.60429,101.462029],[21.603821,101.461838],[21.60358,101.461731],[21.6031,101.461517],[21.60235,101.461327],[21.601851,101.461273],[21.601089,101.461357],[21.599911,101.461807],[21.59948,101.462097],[21.598249,101.463051],[21.597851,101.463371],[21.597231,101.463837],[21.597031,101.463997],[21.596621,101.46431],[21.59622,101.464577],[21.595289,101.465027],[21.594259,101.465149],[21.593731,101.465141],[21.592951,101.46508],[21.59244,101.465012],[21.59144,101.464943],[21.59119,101.464928],[21.5907,101.464928],[21.59045,101.464943],[21.588699,101.465279],[21.58823,101.465553],[21.58778,101.465813],[21.586901,101.466393],[21.585779,101.467117],[21.5851,101.467484],[21.58486,101.46759],[21.58313,101.467796],[21.581961,101.467537],[21.58009,101.467323],[21.57918,101.467537],[21.57896,101.467628],[21.578751,101.467743],[21.57708,101.469528],[21.57564,101.471237],[21.573721,101.47213],[21.57185,101.47226],[21.571609,101.472267],[21.570921,101.47242],[21.5707,101.472504],[21.56967,101.473106],[21.56683,101.474373],[21.56468,101.474983],[21.564091,101.475304],[21.563181,101.47596],[21.562389,101.476761],[21.56115,101.478378],[21.561001,101.478561],[21.55938,101.480637],[21.559231,101.480827],[21.55831,101.481956],[21.5578,101.482483],[21.55722,101.48291],[21.556589,101.483231],[21.556141,101.483383],[21.554979,101.483566],[21.55451,101.483582],[21.554279,101.483589],[21.552191,101.48365],[21.551279,101.483681],[21.55061,101.483704],[21.548849,101.483757],[21.547979,101.483788],[21.54689,101.483841],[21.546671,101.483856],[21.546049,101.483971],[21.54414,101.484978],[21.54397,101.48513],[21.54348,101.485657],[21.542891,101.48642],[21.54274,101.48661],[21.542,101.487556],[21.541861,101.487747],[21.540859,101.489021],[21.54043,101.48954],[21.540291,101.489708],[21.539841,101.490173],[21.5392,101.4907],[21.53886,101.490921],[21.538691,101.49102],[21.538151,101.491287],[21.537781,101.491432],[21.537041,101.491669],[21.536671,101.491783],[21.5347,101.492409],[21.53422,101.492554],[21.533739,101.492706],[21.533421,101.492813],[21.53117,101.493507],[21.52005,101.497276],[21.51823,101.497932],[21.516729,101.498421],[21.516121,101.498749],[21.515369,101.499313],[21.51487,101.499863],[21.5142,101.500954],[21.51395,101.501404],[21.51309,101.502617],[21.512489,101.50341],[21.5119,101.504204],[21.51145,101.504799],[21.51115,101.505203],[21.509859,101.505867],[21.50952,101.506233],[21.508989,101.506767],[21.508471,101.507317],[21.508301,101.5075],[21.50812,101.507683],[21.50765,101.508568],[21.50758,101.508743],[21.50746,101.509407],[21.507481,101.510117],[21.507641,101.511124],[21.50786,101.512627],[21.507959,101.513397],[21.507151,101.514633],[21.50692,101.515289],[21.506491,101.516243],[21.5063,101.516731],[21.506149,101.517258],[21.506001,101.518044],[21.50596,101.518547],[21.50596,101.518784],[21.50597,101.518982],[21.505989,101.519333],[21.506029,101.519653],[21.506069,101.519997],[21.50596,101.522263],[21.50559,101.523567],[21.50539,101.524117],[21.505199,101.524643],[21.50493,101.525421],[21.504669,101.526169],[21.504499,101.526657],[21.50436,101.527168],[21.50421,101.527679],[21.50399,101.528442],[21.503691,101.529457],[21.50388,101.531113],[21.503839,101.531891],[21.50375,101.532417],[21.503469,101.53344],[21.503189,101.534187],[21.502741,101.535393],[21.502649,101.535629],[21.50247,101.536118],[21.50219,101.53685],[21.502001,101.537354],[21.50169,101.538101],[21.50135,101.539108],[21.50128,101.540138],[21.50182,101.541763],[21.502119,101.54213],[21.502279,101.542297],[21.502819,101.542686],[21.50433,101.543671],[21.505131,101.544182],[21.50856,101.546333],[21.50975,101.547249],[21.51009,101.547607],[21.51037,101.548019],[21.510691,101.548714],[21.51091,101.549713],[21.51087,101.550743],[21.510019,101.552643],[21.50943,101.553497],[21.507971,101.555656],[21.507099,101.556976],[21.50695,101.55722],[21.506689,101.557663],[21.50597,101.558723],[21.5054,101.55957],[21.50499,101.560188],[21.504021,101.561607],[21.50321,101.562866],[21.501711,101.565132],[21.500299,101.567253],[21.49931,101.568764],[21.498329,101.570236],[21.496941,101.572327],[21.49625,101.573372],[21.49472,101.575684],[21.491819,101.579353],[21.48933,101.58075],[21.48888,101.580887],[21.486139,101.581078],[21.48407,101.580566],[21.481621,101.579582],[21.481171,101.579399],[21.480721,101.579224],[21.47644,101.57753],[21.474199,101.57666],[21.47193,101.57579],[21.467951,101.574188],[21.46373,101.572517],[21.46306,101.572258],[21.46283,101.572166],[21.461531,101.571663],[21.45727,101.570129],[21.45557,101.56974],[21.450569,101.568871],[21.450121,101.568939],[21.449129,101.569443],[21.448389,101.570358],[21.447821,101.571732],[21.44714,101.573059],[21.447001,101.573257],[21.44635,101.573936],[21.44599,101.574226],[21.44524,101.574738],[21.44451,101.575249],[21.44367,101.576317],[21.443371,101.57695],[21.44311,101.577583],[21.44302,101.577797],[21.44268,101.578644],[21.442419,101.579277],[21.442169,101.579933],[21.442089,101.580139],[21.441589,101.581169],[21.441469,101.581367],[21.439939,101.583168],[21.43919,101.583748],[21.43844,101.584328],[21.43825,101.584473],[21.43788,101.584763],[21.437309,101.58519],[21.43712,101.585327],[21.43615,101.584167],[21.43479,101.583832],[21.4333,101.582962],[21.43273,101.582451],[21.432541,101.582253],[21.431669,101.581284],[21.430969,101.580513],[21.430269,101.57975],[21.43008,101.579567],[21.429501,101.579071],[21.428391,101.578491],[21.427919,101.578346],[21.427429,101.578247],[21.425461,101.578407],[21.424049,101.579048],[21.420389,101.581108],[21.419979,101.581337],[21.41571,101.583321],[21.41457,101.583511],[21.41366,101.583542],[21.41206,101.583427],[21.408621,101.583557],[21.40716,101.584686],[21.4049,101.588074],[21.403959,101.589478],[21.40303,101.590919],[21.402679,101.592781],[21.403009,101.593674],[21.40378,101.594841],[21.40402,101.595253],[21.40432,101.595886],[21.404461,101.596336],[21.404591,101.597549],[21.40451,101.598282],[21.40427,101.599258],[21.404169,101.599762],[21.40451,101.601669],[21.406111,101.604439],[21.40613,101.605873],[21.4058,101.606552],[21.404699,101.607536],[21.404261,101.607697],[21.403339,101.607971],[21.402929,101.608177],[21.402559,101.608459],[21.401739,101.610237],[21.401871,101.611267],[21.40221,101.612251],[21.402809,101.613823],[21.40299,101.614487],[21.40303,101.614967],[21.40284,101.616112],[21.401939,101.618828],[21.40192,101.619072],[21.40217,101.620598],[21.40247,101.621201],[21.40373,101.623901],[21.40465,101.626793],[21.40407,101.628906],[21.40324,101.63076],[21.403139,101.630989],[21.40155,101.634537],[21.40093,101.636017],[21.40012,101.637909],[21.399981,101.638763],[21.400181,101.639793],[21.400709,101.640717],[21.40102,101.641144],[21.401131,101.641296],[21.40196,101.642464],[21.402081,101.642639],[21.402981,101.643921],[21.404921,101.645638],[21.40534,101.645882],[21.406879,101.646599],[21.407089,101.646721],[21.40806,101.647476],[21.40929,101.649406],[21.40995,101.651413],[21.410191,101.652168],[21.412201,101.65831],[21.412661,101.659714],[21.413031,101.660873],[21.41342,101.661987],[21.413731,101.66288],[21.414021,101.663788],[21.4142,101.664726],[21.4142,101.665672],[21.414061,101.666344],[21.41399,101.66655],[21.41383,101.666992],[21.413389,101.66777],[21.41296,101.668297],[21.41247,101.668762],[21.411989,101.669197],[21.411329,101.669762],[21.410851,101.670174],[21.409861,101.671089],[21.409519,101.671387],[21.40654,101.674118],[21.40633,101.674179],[21.405331,101.675163],[21.40472,101.675667],[21.403,101.676773],[21.402309,101.677094],[21.402069,101.677193],[21.401581,101.677368],[21.40037,101.677727],[21.39938,101.678017],[21.397619,101.678543],[21.39686,101.678772],[21.39661,101.678848],[21.39558,101.679153],[21.393749,101.679703],[21.39349,101.679787],[21.39068,101.680634],[21.3897,101.680923],[21.388531,101.681267],[21.3883,101.681343],[21.38497,101.681824],[21.38472,101.681793],[21.38423,101.681709],[21.383301,101.681473],[21.38283,101.681328],[21.381849,101.681137],[21.3811,101.681099],[21.37989,101.681252],[21.374399,101.682503],[21.371639,101.683113],[21.37097,101.683243],[21.370119,101.683434],[21.369711,101.683517],[21.36779,101.683937],[21.366369,101.684273],[21.363689,101.684883],[21.358419,101.68605],[21.355499,101.686691],[21.35397,101.687172],[21.351471,101.688713],[21.34923,101.689758],[21.34716,101.689621],[21.346491,101.689499],[21.34627,101.689461],[21.3445,101.68914],[21.34428,101.68911],[21.34269,101.688812],[21.340111,101.68895],[21.33828,101.689888],[21.337641,101.690331],[21.334961,101.692108],[21.332781,101.692627],[21.3321,101.692612],[21.331181,101.692581],[21.330429,101.692551],[21.330179,101.692528],[21.326281,101.692917],[21.324341,101.693268],[21.324089,101.693314],[21.32147,101.693352],[21.31986,101.693321],[21.317921,101.694153],[21.317711,101.69426],[21.31728,101.694427],[21.316139,101.69445],[21.314119,101.693893],[21.3139,101.693832],[21.31188,101.693459],[21.30991,101.693947],[21.308069,101.69548],[21.30736,101.696136],[21.306259,101.697166],[21.30348,101.699059],[21.30176,101.699493],[21.29907,101.699257],[21.293909,101.698067],[21.292749,101.697807],[21.289789,101.697159],[21.289129,101.697006],[21.28742,101.696632],[21.286369,101.696388],[21.28471,101.696053],[21.28323,101.696136],[21.281811,101.696793],[21.28023,101.698433],[21.27973,101.699074],[21.279221,101.699722],[21.27784,101.701424],[21.27766,101.70163],[21.276819,101.70269],[21.276661,101.702904],[21.275181,101.70472],[21.27319,101.706131],[21.271839,101.706734],[21.271469,101.707047],[21.270941,101.70787],[21.26981,101.711739],[21.26972,101.711983],[21.2689,101.713188],[21.2665,101.715477],[21.26597,101.715958],[21.265369,101.716316],[21.26404,101.716522],[21.263161,101.716293],[21.260771,101.714844],[21.25922,101.713852],[21.257099,101.712517],[21.25647,101.712128],[21.256081,101.711884],[21.255791,101.711723],[21.25561,101.711571],[21.25526,101.711327],[21.25515,101.711273],[21.2542,101.710693],[21.253139,101.710037],[21.253019,101.709969],[21.252831,101.709846],[21.251011,101.708702],[21.250351,101.708321],[21.249781,101.70813],[21.24929,101.707947],[21.24873,101.70787],[21.24799,101.707802],[21.246639,101.707718],[21.24645,101.707703],[21.24424,101.707573],[21.24391,101.707512],[21.24243,101.707199],[21.23983,101.706123],[21.237459,101.705139],[21.232361,101.703072],[21.232071,101.702988],[21.229389,101.702309],[21.229059,101.702217],[21.22883,101.702263],[21.22781,101.702744],[21.227631,101.702858],[21.226589,101.703712],[21.22473,101.704857],[21.22368,101.705063],[21.221531,101.704613],[21.22003,101.704063],[21.217899,101.703362],[21.21722,101.703201],[21.21579,101.703049],[21.21278,101.70285],[21.209311,101.702278],[21.207649,101.701683],[21.20392,101.700203],[21.202351,101.699127],[21.200911,101.696533],[21.1991,101.693657],[21.19673,101.692017],[21.194309,101.690483],[21.19376,101.690102],[21.193081,101.689651],[21.1917,101.688637],[21.190769,101.687233],[21.19038,101.68663],[21.190069,101.686272],[21.189859,101.686096],[21.18948,101.685799],[21.188499,101.68512],[21.18718,101.684097],[21.18701,101.683723],[21.186689,101.683517],[21.186279,101.683693],[21.18615,101.683632],[21.185841,101.683296],[21.18573,101.682793],[21.18601,101.681519],[21.18609,101.680992],[21.18647,101.680603],[21.186871,101.680237],[21.187,101.679932],[21.18693,101.678787],[21.18714,101.678131],[21.187559,101.677711],[21.18775,101.677139],[21.18775,101.676033],[21.187361,101.675491],[21.18634,101.67466],[21.186001,101.674156],[21.185749,101.673912],[21.18507,101.673508],[21.184771,101.673378],[21.184389,101.673187],[21.18375,101.672913],[21.182159,101.67215],[21.180889,101.671158],[21.179991,101.670067],[21.17861,101.669197],[21.17667,101.668991],[21.17417,101.668457],[21.173349,101.668541],[21.17028,101.669739],[21.16925,101.670959],[21.1682,101.672523],[21.16785,101.672813],[21.166189,101.673027],[21.16534,101.672256],[21.16515,101.671768],[21.16436,101.671318],[21.164221,101.671341],[21.162239,101.671417],[21.15913,101.672249],[21.158449,101.672173],[21.157101,101.671822],[21.156509,101.671494],[21.15626,101.671288],[21.155239,101.671181],[21.15383,101.6716],[21.153191,101.672234],[21.15299,101.67263],[21.152439,101.67305],[21.151421,101.673592],[21.150631,101.67337],[21.15029,101.672989],[21.15037,101.672081],[21.150669,101.671257],[21.150391,101.670158],[21.15033,101.670067],[21.14954,101.669273],[21.14859,101.668411],[21.14756,101.668449],[21.14698,101.668678],[21.145809,101.668266],[21.14555,101.667824],[21.14522,101.666992],[21.14439,101.666809],[21.14426,101.666893],[21.14325,101.666779],[21.141621,101.665131],[21.140881,101.664749],[21.139521,101.664429],[21.138849,101.664528],[21.13736,101.665062],[21.1367,101.665047],[21.133381,101.664391],[21.13324,101.66433],[21.132509,101.663429],[21.13204,101.662064],[21.13155,101.661484],[21.12817,101.657883],[21.12644,101.656097],[21.124781,101.654663],[21.123831,101.654449],[21.122801,101.654503],[21.121611,101.653748],[21.12063,101.65239],[21.119909,101.652184],[21.119591,101.652199],[21.118719,101.651787],[21.116011,101.64978],[21.114189,101.648827],[21.11272,101.647827],[21.11216,101.647171],[21.11198,101.646858],[21.110399,101.645432],[21.10799,101.643784],[21.1066,101.642517],[21.105141,101.642128],[21.10467,101.642021],[21.10405,101.641533],[21.10235,101.639343],[21.10084,101.638039],[21.10059,101.637817],[21.099581,101.637688],[21.098789,101.637917],[21.097651,101.637497],[21.09745,101.636864],[21.097389,101.636368],[21.0968,101.635696],[21.09623,101.635429],[21.095579,101.635422],[21.094721,101.635567],[21.093611,101.635033],[21.0937,101.634087],[21.093571,101.633324],[21.093201,101.633339],[21.09173,101.633362],[21.091311,101.634033],[21.091339,101.634407],[21.090811,101.634972],[21.090679,101.634956],[21.090429,101.634933],[21.09004,101.63427],[21.090031,101.633827],[21.08955,101.633232],[21.08824,101.63266],[21.08761,101.631882],[21.08699,101.629753],[21.086281,101.629288],[21.085979,101.629883],[21.085951,101.630363],[21.085409,101.631233],[21.08371,101.633232],[21.08346,101.633499],[21.08213,101.634163],[21.081591,101.634033],[21.08135,101.633919],[21.08079,101.63427],[21.08078,101.634552],[21.080839,101.635437],[21.08036,101.63588],[21.08003,101.635902],[21.07967,101.636673],[21.079691,101.638252],[21.079399,101.639343],[21.078541,101.639977],[21.077511,101.640182],[21.07645,101.639679],[21.076229,101.639442],[21.075251,101.639282],[21.0749,101.639587],[21.074249,101.640633],[21.0742,101.641724],[21.074301,101.642326],[21.073811,101.642967],[21.07135,101.643784],[21.06925,101.644409],[21.06815,101.643997],[21.06529,101.641731],[21.06399,101.64122],[21.063589,101.640419],[21.06303,101.6399],[21.062799,101.640053],[21.06217,101.640602],[21.061819,101.641602],[21.061831,101.641678],[21.061939,101.64257],[21.061939,101.643494],[21.06189,101.64373],[21.06179,101.644058],[21.061331,101.644096],[21.060949,101.644112],[21.060551,101.64415],[21.058901,101.644211],[21.05814,101.644142],[21.057421,101.643707],[21.0557,101.641777],[21.054649,101.639397],[21.054371,101.637123],[21.05472,101.636192],[21.05496,101.635902],[21.055201,101.634933],[21.05521,101.633789],[21.05562,101.633133],[21.056,101.632858],[21.056259,101.632507],[21.056231,101.631889],[21.056009,101.631126],[21.056009,101.63031],[21.055611,101.629601],[21.05542,101.629463],[21.055229,101.629066],[21.05549,101.628708],[21.055759,101.628609],[21.056959,101.628326],[21.05728,101.628036],[21.057211,101.627663],[21.05706,101.627472],[21.056881,101.627289],[21.056749,101.626503],[21.056881,101.625992],[21.056391,101.625427],[21.056259,101.62542],[21.055861,101.625381],[21.055531,101.624649],[21.05567,101.624107],[21.05521,101.623482],[21.055071,101.623451],[21.054529,101.623337],[21.053841,101.623421],[21.05345,101.623573],[21.05257,101.623238],[21.052481,101.623108],[21.05212,101.622597],[21.05159,101.622292],[21.05098,101.622124],[21.05027,101.621071],[21.04999,101.617973],[21.050171,101.617203],[21.0518,101.614067],[21.053329,101.611893],[21.05361,101.610832],[21.054119,101.609283],[21.05393,101.608627],[21.05303,101.606812],[21.05307,101.605743],[21.053431,101.604851],[21.05352,101.60408],[21.05327,101.602287],[21.05216,101.599876],[21.052219,101.598587],[21.052691,101.596916],[21.052589,101.596092],[21.051649,101.59243],[21.05213,101.591179],[21.054859,101.588188],[21.055071,101.586418],[21.055019,101.58622],[21.053671,101.583351],[21.053471,101.583023],[21.05316,101.581673],[21.05213,101.580551],[21.05195,101.580467],[21.048651,101.579102],[21.047661,101.577583],[21.047159,101.575447],[21.04752,101.574654],[21.047939,101.574249],[21.047831,101.573502],[21.04771,101.573387],[21.045891,101.571762],[21.04542,101.57132],[21.044941,101.570572],[21.043739,101.569817],[21.043119,101.569893],[21.040911,101.57045],[21.039921,101.570267],[21.03924,101.569939],[21.038771,101.569153],[21.038679,101.568779],[21.03887,101.567871],[21.03911,101.56739],[21.038759,101.56649],[21.03618,101.56472],[21.034491,101.564079],[21.03421,101.563957],[21.033649,101.563393],[21.033291,101.562782],[21.03249,101.562347],[21.03064,101.561867],[21.02869,101.56057],[21.027941,101.558998],[21.028431,101.557823],[21.02883,101.557358],[21.0292,101.556396],[21.02948,101.554993],[21.03001,101.553947],[21.030121,101.553062],[21.03009,101.55275],[21.02957,101.552261],[21.0285,101.551842],[21.02776,101.551918],[21.02747,101.551987],[21.02669,101.551743],[21.025669,101.550957],[21.02426,101.549026],[21.024151,101.548843],[21.02359,101.546783],[21.022961,101.546013],[21.022449,101.545723],[21.02191,101.545181],[21.02103,101.544579],[21.01865,101.544144],[21.01754,101.543259],[21.017481,101.543068],[21.01631,101.540771],[21.01417,101.53756],[21.01343,101.536171],[21.01198,101.534866],[21.01107,101.533409],[21.01088,101.532593],[21.01087,101.53167],[21.01041,101.530777],[21.00898,101.529266],[21.00782,101.526787],[21.00745,101.525253],[21.00626,101.522858],[21.00585,101.522148],[21.005159,101.521637],[21.0049,101.521523],[21.004641,101.520668],[21.00502,101.518944],[21.00486,101.518288],[21.004499,101.517731],[21.003889,101.517303],[21.003651,101.517212],[21.003281,101.516609],[21.00312,101.515732],[21.002621,101.515251],[21.001989,101.514832],[21.00145,101.514183],[21.000019,101.513237],[20.99921,101.513107],[20.99798,101.513229],[20.997299,101.513573],[20.995371,101.514557],[20.99423,101.514267],[20.99411,101.514107],[20.993151,101.51326],[20.99276,101.512451],[20.99169,101.509193],[20.99136,101.508392],[20.99144,101.507004],[20.99139,101.506577],[20.99114,101.505531],[20.990749,101.504936],[20.990391,101.50457],[20.9893,101.504051],[20.988171,101.503937],[20.987301,101.503036],[20.986629,101.502098],[20.986059,101.501862],[20.98563,101.501823],[20.985189,101.501129],[20.98535,101.5009],[20.98554,101.500671],[20.985479,101.499657],[20.985201,101.499428],[20.984381,101.498848],[20.9841,101.4981],[20.98411,101.497597],[20.983919,101.496964],[20.982651,101.493713],[20.982571,101.49353],[20.98209,101.492943],[20.98139,101.492027],[20.98027,101.491493],[20.979931,101.491463],[20.97905,101.490608],[20.978979,101.490211],[20.97872,101.486893],[20.97826,101.484161],[20.977501,101.481491],[20.977671,101.480797],[20.97838,101.479523],[20.978571,101.478737],[20.97826,101.477966],[20.97625,101.475441],[20.975889,101.474953],[20.97571,101.474243],[20.97571,101.473801],[20.975189,101.473083],[20.974569,101.472763],[20.971781,101.472397],[20.971319,101.472343],[20.97085,101.471573],[20.9708,101.470627],[20.970989,101.469879],[20.97171,101.468323],[20.9718,101.46756],[20.97176,101.466614],[20.97085,101.464706],[20.96999,101.464142],[20.96937,101.463982],[20.968889,101.463127],[20.969021,101.462761],[20.96921,101.462219],[20.969311,101.459877],[20.96875,101.458588],[20.96818,101.458328],[20.967899,101.458344],[20.96715,101.457619],[20.966829,101.456596],[20.96603,101.456177],[20.964979,101.456093],[20.964399,101.455673],[20.96394,101.455139],[20.96306,101.454193],[20.96171,101.452744],[20.96068,101.451591],[20.956091,101.446877],[20.95311,101.443123],[20.94928,101.435982],[20.947901,101.432739],[20.947109,101.430893],[20.944679,101.423531],[20.94459,101.423302],[20.94437,101.422813],[20.94393,101.422318],[20.94335,101.421989],[20.940571,101.421303],[20.937679,101.420601],[20.93697,101.42028],[20.934799,101.41803],[20.934759,101.417976],[20.933929,101.41713],[20.931311,101.414238],[20.930401,101.411774],[20.928591,101.406677],[20.92713,101.402611],[20.926319,101.400558],[20.9261,101.400032],[20.92557,101.399147],[20.924749,101.397987],[20.92362,101.397202],[20.92201,101.396652],[20.919701,101.396263],[20.916941,101.396027],[20.91567,101.396103],[20.91518,101.396057],[20.91395,101.395683],[20.912701,101.395607],[20.912001,101.395248],[20.91086,101.393898],[20.91008,101.392738],[20.90941,101.39241],[20.908859,101.392418],[20.908319,101.392258],[20.907619,101.391838],[20.90641,101.391373],[20.90514,101.390343],[20.90481,101.390007],[20.90452,101.389236],[20.904369,101.387253],[20.90424,101.386543],[20.90419,101.385681],[20.904249,101.385193],[20.903959,101.384361],[20.902889,101.383614],[20.902361,101.382896],[20.901699,101.381378],[20.901421,101.38102],[20.90081,101.380478],[20.900419,101.379936],[20.89982,101.378464],[20.89942,101.377693],[20.89913,101.376877],[20.898861,101.375717],[20.89913,101.374657],[20.899389,101.373901],[20.899771,101.373192],[20.900129,101.372658],[20.900181,101.371742],[20.89929,101.370667],[20.899111,101.369743],[20.89933,101.36908],[20.89933,101.368187],[20.89893,101.366798],[20.898621,101.365959],[20.897791,101.364807],[20.89596,101.363327],[20.89566,101.363159],[20.894501,101.362846],[20.893221,101.362282],[20.89233,101.362289],[20.891911,101.362503],[20.89109,101.362419],[20.890869,101.361862],[20.890989,101.361412],[20.891991,101.359993],[20.892191,101.359543],[20.892321,101.359039],[20.892361,101.357803],[20.891979,101.356918],[20.89134,101.356422],[20.89098,101.355713],[20.89085,101.354797],[20.890739,101.354477],[20.890169,101.353882],[20.88908,101.35334],[20.887831,101.352203],[20.887449,101.351532],[20.887051,101.350227],[20.886459,101.347748],[20.88616,101.345627],[20.885771,101.344566],[20.885139,101.343468],[20.88505,101.342644],[20.885099,101.342339],[20.884859,101.341637],[20.88353,101.339973],[20.882351,101.338768],[20.880859,101.3377],[20.87953,101.335678],[20.878099,101.334183],[20.87734,101.333168],[20.876961,101.332138],[20.87657,101.331589],[20.87565,101.330719],[20.875271,101.329689],[20.875191,101.328537],[20.874901,101.327873],[20.87468,101.327583],[20.874399,101.326897],[20.87429,101.325577],[20.87417,101.325081],[20.87361,101.324387],[20.87336,101.323647],[20.87372,101.323196],[20.8745,101.322937],[20.87533,101.322411],[20.876341,101.321587],[20.87653,101.320892],[20.876419,101.320633],[20.87587,101.319832],[20.8755,101.319199],[20.874941,101.31871],[20.8743,101.318604],[20.87339,101.318153],[20.87311,101.317917],[20.872601,101.317039],[20.87215,101.316429],[20.87092,101.316002],[20.87092,101.315643],[20.87122,101.314941],[20.871281,101.314583],[20.871241,101.314484],[20.87109,101.314323],[20.870701,101.314133],[20.87014,101.313477],[20.869671,101.313187],[20.869301,101.312759],[20.86846,101.312218],[20.86771,101.311951],[20.8671,101.311447],[20.86688,101.311409],[20.866301,101.3116],[20.86607,101.311523],[20.865959,101.311409],[20.865801,101.310837],[20.86561,101.31041],[20.865049,101.309357],[20.86484,101.309067],[20.86454,101.308907],[20.86376,101.309387],[20.86334,101.309227],[20.86293,101.308487],[20.862379,101.308144],[20.86187,101.308067],[20.86134,101.307678],[20.86109,101.307343],[20.86058,101.307114],[20.859579,101.306999],[20.859261,101.307022],[20.858521,101.306557],[20.85837,101.306557],[20.85812,101.306839],[20.857849,101.307281],[20.85762,101.307373],[20.85746,101.307266],[20.85737,101.306808],[20.85758,101.304932],[20.85774,101.304482],[20.857809,101.303909],[20.85762,101.303467],[20.857031,101.302849],[20.85684,101.302551],[20.856741,101.301697],[20.85685,101.301376],[20.857031,101.301117],[20.857401,101.300873],[20.8578,101.300407],[20.857809,101.299911],[20.85775,101.299751],[20.85659,101.298553],[20.85626,101.298347],[20.85582,101.297791],[20.8554,101.297028],[20.8552,101.296783],[20.85458,101.296593],[20.854441,101.296631],[20.85359,101.296577],[20.85334,101.296173],[20.853201,101.295738],[20.852631,101.295326],[20.85215,101.295288],[20.85099,101.294746],[20.849661,101.293571],[20.84874,101.292473],[20.84767,101.291672],[20.845869,101.291008],[20.845289,101.290916],[20.84473,101.290749],[20.8437,101.289886],[20.84339,101.289398],[20.842211,101.288437],[20.842039,101.288353],[20.84111,101.288147],[20.839911,101.287758],[20.839411,101.287682],[20.837811,101.286537],[20.836929,101.2864],[20.83576,101.286842],[20.83511,101.28685],[20.834379,101.286758],[20.83363,101.286812],[20.83313,101.286972],[20.832451,101.28698],[20.83209,101.286903],[20.83136,101.286858],[20.8307,101.286659],[20.82987,101.286171],[20.827419,101.284218],[20.82687,101.283821],[20.826639,101.2836],[20.826469,101.282822],[20.827129,101.280853],[20.827259,101.280098],[20.827181,101.279358],[20.827009,101.278397],[20.82641,101.276901],[20.82559,101.276009],[20.823879,101.273521],[20.823151,101.272568],[20.82159,101.269386],[20.82069,101.2687],[20.81974,101.268578],[20.81888,101.268013],[20.818501,101.26712],[20.818159,101.266602],[20.81764,101.265961],[20.8174,101.265213],[20.817101,101.263397],[20.81666,101.26268],[20.81521,101.260689],[20.81455,101.2593],[20.81427,101.257919],[20.813629,101.256981],[20.812321,101.256058],[20.81144,101.255783],[20.81056,101.255829],[20.80987,101.255524],[20.809561,101.254936],[20.809259,101.254532],[20.808781,101.25428],[20.80657,101.253616],[20.8057,101.252892],[20.805111,101.25174],[20.804529,101.251251],[20.804199,101.25116],[20.80361,101.250793],[20.803249,101.25042],[20.802361,101.250076],[20.80204,101.250076],[20.80131,101.249603],[20.801081,101.248833],[20.800421,101.248154],[20.799601,101.24794],[20.79903,101.247581],[20.79871,101.247009],[20.79841,101.246651],[20.798059,101.246368],[20.797729,101.245918],[20.79738,101.245552],[20.796869,101.245453],[20.796061,101.245071],[20.795691,101.244034],[20.79571,101.24337],[20.79591,101.242928],[20.79604,101.242363],[20.79582,101.242012],[20.79541,101.241859],[20.79455,101.241829],[20.79377,101.241577],[20.79318,101.241508],[20.792471,101.241676],[20.791559,101.241417],[20.79118,101.241043],[20.79059,101.240044],[20.79001,101.239571],[20.78912,101.239166],[20.788349,101.238457],[20.78746,101.23822],[20.787109,101.238312],[20.7859,101.238449],[20.78516,101.238167],[20.784611,101.237091],[20.78401,101.236816],[20.783689,101.236809],[20.78311,101.236382],[20.782841,101.235779],[20.78194,101.234947],[20.78125,101.234741],[20.780479,101.234016],[20.780319,101.233017],[20.7799,101.232117],[20.77844,101.230377],[20.778259,101.229301],[20.778521,101.22863],[20.778641,101.228104],[20.77836,101.227226],[20.77755,101.225906],[20.77619,101.222702],[20.775499,101.221542],[20.775351,101.220627],[20.775431,101.219948],[20.775299,101.21936],[20.774981,101.219063],[20.774429,101.218277],[20.77429,101.217552],[20.774059,101.21685],[20.77401,101.21595],[20.7736,101.214958],[20.77289,101.214157],[20.772711,101.213707],[20.77206,101.213028],[20.77157,101.212852],[20.77067,101.212082],[20.769079,101.211403],[20.76856,101.210831],[20.7684,101.210358],[20.76782,101.209717],[20.766581,101.208923],[20.766041,101.208389],[20.76475,101.206596],[20.7642,101.20533],[20.763359,101.204628],[20.76206,101.204338],[20.76133,101.203827],[20.760889,101.203232],[20.76026,101.202133],[20.75979,101.201714],[20.75909,101.201591],[20.758789,101.201103],[20.758659,101.200577],[20.758289,101.199913],[20.756969,101.198578],[20.75625,101.197777],[20.75568,101.197388],[20.754919,101.196739],[20.754379,101.196007],[20.753799,101.194603],[20.753019,101.193871],[20.752131,101.193619],[20.75107,101.192886],[20.75004,101.191017],[20.749201,101.190369],[20.74798,101.190247],[20.747049,101.189789],[20.746679,101.189377],[20.74592,101.18782],[20.744631,101.186089],[20.744249,101.185173],[20.743811,101.18457],[20.742531,101.18351],[20.74172,101.181969],[20.740219,101.179893],[20.739519,101.178558],[20.73938,101.178192],[20.73859,101.177406],[20.73609,101.17572],[20.735571,101.175194],[20.735161,101.174278],[20.734949,101.173271],[20.73436,101.171417],[20.73366,101.16983],[20.733391,101.168877],[20.73332,101.167488],[20.73292,101.166161],[20.732599,101.165382],[20.7318,101.164146],[20.730471,101.162468],[20.729731,101.161346],[20.728519,101.158813],[20.727631,101.157448],[20.727249,101.156227],[20.72673,101.155281],[20.72649,101.154922],[20.72521,101.153793],[20.72459,101.152687],[20.724159,101.150543],[20.723579,101.148811],[20.722309,101.14669],[20.721519,101.145203],[20.72089,101.142311],[20.72014,101.139526],[20.719931,101.138321],[20.71986,101.13755],[20.71986,101.135567],[20.71977,101.135147],[20.71953,101.134521],[20.719139,101.133034],[20.719021,101.131973],[20.71859,101.131027],[20.716841,101.128883],[20.715891,101.127151],[20.71361,101.123306],[20.713131,101.122078],[20.71228,101.120903],[20.71139,101.119331],[20.71073,101.116898],[20.71067,101.116501],[20.71023,101.115593],[20.70933,101.11425],[20.70879,101.112427],[20.70808,101.111382],[20.70723,101.10994],[20.70668,101.108551],[20.706181,101.106972],[20.70561,101.10614],[20.70388,101.104538],[20.70244,101.102783],[20.70118,101.09993],[20.70072,101.09906],[20.6994,101.097847],[20.69784,101.095589],[20.69607,101.093971],[20.69558,101.093132],[20.69499,101.0914],[20.69352,101.089119],[20.689859,101.084457],[20.68833,101.082237],[20.68816,101.081863],[20.68788,101.079727],[20.68796,101.077667],[20.688219,101.076057],[20.688129,101.075287],[20.68651,101.071457],[20.686211,101.070671],[20.68609,101.069862],[20.68597,101.068253],[20.685909,101.066559],[20.68614,101.0644],[20.686119,101.062973],[20.686029,101.062637],[20.685539,101.061783],[20.68491,101.061203],[20.68383,101.060493],[20.68259,101.059792],[20.68153,101.059624],[20.68082,101.059608],[20.67993,101.059982],[20.67845,101.061462],[20.67696,101.063042],[20.676001,101.063911],[20.67528,101.064041],[20.67485,101.063957],[20.674549,101.06398],[20.67375,101.06414],[20.672791,101.063828],[20.67153,101.063164],[20.67119,101.063087],[20.670349,101.06321],[20.66991,101.063431],[20.669331,101.063477],[20.66877,101.063271],[20.66786,101.063087],[20.667271,101.062637],[20.66712,101.06237],[20.666519,101.061897],[20.666201,101.061867],[20.664379,101.061996],[20.663731,101.062233],[20.6633,101.0625],[20.66238,101.0625],[20.662001,101.061981],[20.661909,101.061668],[20.661579,101.061172],[20.66132,101.061043],[20.660379,101.060806],[20.659349,101.060799],[20.658239,101.06041],[20.657511,101.060318],[20.656771,101.060303],[20.656139,101.060768],[20.65538,101.064034],[20.654011,101.066132],[20.653879,101.06678],[20.65395,101.067062],[20.653839,101.067787],[20.65346,101.068527],[20.65251,101.069458],[20.65188,101.069992],[20.65143,101.070847],[20.651449,101.073021],[20.65098,101.073807],[20.650551,101.073967],[20.647909,101.074493],[20.647511,101.07473],[20.647209,101.075127],[20.647039,101.076431],[20.64661,101.077271],[20.646231,101.07766],[20.645269,101.078148],[20.64476,101.078644],[20.644279,101.07943],[20.64299,101.080406],[20.64089,101.081017],[20.640221,101.081093],[20.639441,101.081612],[20.638889,101.082474],[20.63821,101.082863],[20.63739,101.082977],[20.63587,101.08374],[20.63508,101.083847],[20.633369,101.083763],[20.63271,101.083946],[20.632099,101.084244],[20.631451,101.084351],[20.629339,101.083977],[20.628559,101.083351],[20.628071,101.082176],[20.62792,101.081711],[20.627359,101.080887],[20.626101,101.079613],[20.62479,101.078598],[20.622829,101.077782],[20.62022,101.076309],[20.61867,101.07502],[20.617029,101.073868],[20.616859,101.073776],[20.615549,101.073547],[20.614929,101.073242],[20.61466,101.072731],[20.61433,101.071564],[20.61392,101.070877],[20.61338,101.069649],[20.612909,101.069092],[20.611031,101.068062],[20.6094,101.067436],[20.608749,101.067139],[20.607571,101.066399],[20.60638,101.065758],[20.605659,101.065567],[20.604589,101.065857],[20.60412,101.066147],[20.6033,101.0662],[20.602989,101.066032],[20.60177,101.064842],[20.601231,101.064377],[20.60047,101.063942],[20.59808,101.063057],[20.597231,101.062599],[20.596189,101.06221],[20.59548,101.061638],[20.59498,101.060852],[20.59428,101.060387],[20.59376,101.060303],[20.593109,101.059952],[20.591631,101.058723],[20.59132,101.058113],[20.590731,101.055931],[20.589729,101.053772],[20.58914,101.051903],[20.588221,101.050682],[20.586269,101.048897],[20.585609,101.048561],[20.584181,101.048302],[20.58263,101.048203],[20.58144,101.047684],[20.579809,101.047829],[20.578791,101.046982],[20.578609,101.046478],[20.578621,101.045578],[20.578329,101.045082],[20.57781,101.04483],[20.576771,101.043968],[20.575359,101.04261],[20.57526,101.042007],[20.57534,101.041771],[20.5756,101.041321],[20.57601,101.040932],[20.57641,101.04068],[20.57692,101.040031],[20.57786,101.038063],[20.57855,101.037613],[20.57943,101.037949],[20.579651,101.0382],[20.580391,101.039436],[20.58083,101.039673],[20.58103,101.039307],[20.58106,101.03894],[20.58148,101.0383],[20.581739,101.038254],[20.582291,101.037956],[20.58223,101.037659],[20.582001,101.03701],[20.582211,101.036247],[20.582529,101.036034],[20.58309,101.035378],[20.583151,101.034973],[20.58288,101.034416],[20.582211,101.03434],[20.581659,101.03476],[20.58082,101.034737],[20.58021,101.033791],[20.58004,101.033241],[20.58007,101.032333],[20.579781,101.031731],[20.577749,101.029953],[20.57756,101.029602],[20.577141,101.029343],[20.57696,101.029427],[20.57642,101.029877],[20.57612,101.02993],[20.575781,101.0299],[20.57556,101.029831],[20.57505,101.028816],[20.574751,101.028816],[20.57456,101.028908],[20.57383,101.028847],[20.572729,101.028511],[20.57069,101.028091],[20.5688,101.027817],[20.56827,101.027237],[20.568291,101.026779],[20.568439,101.026031],[20.56822,101.025513],[20.567841,101.025352],[20.567329,101.02552],[20.566971,101.025757],[20.56641,101.025757],[20.564489,101.024986],[20.564039,101.02459],[20.56389,101.024231],[20.563801,101.02388],[20.563551,101.023453],[20.563129,101.023178],[20.562531,101.023003],[20.562229,101.022728],[20.56225,101.02198],[20.56193,101.021362],[20.561541,101.021072],[20.56139,101.020493],[20.561449,101.020393],[20.56163,101.019592],[20.561159,101.019112],[20.560499,101.018959],[20.55938,101.019341],[20.558701,101.01915],[20.55862,101.019051],[20.55801,101.018784],[20.5574,101.01857],[20.55698,101.01754],[20.556499,101.01696],[20.55608,101.016747],[20.555599,101.016113],[20.55518,101.014618],[20.554899,101.013847],[20.55479,101.012917],[20.555,101.012421],[20.555349,101.011757],[20.555389,101.011497],[20.55579,101.011002],[20.55604,101.01088],[20.55661,101.01004],[20.556971,101.008743],[20.557289,101.008118],[20.557541,101.007347],[20.55731,101.006798],[20.55694,101.006767],[20.556709,101.006798],[20.55617,101.006683],[20.555639,101.006241],[20.55555,101.005898],[20.555599,101.005508],[20.555901,101.004578],[20.555861,101.00415],[20.555599,101.003983],[20.55525,101.003532],[20.555149,101.003014],[20.55477,101.002808],[20.554411,101.002403],[20.554399,101.002052],[20.55467,101.000832],[20.55497,101.000343],[20.555241,101.000122],[20.5555,100.999748],[20.555519,100.99926],[20.555429,100.996834],[20.554729,100.995697],[20.55479,100.995163],[20.55497,100.994797],[20.55489,100.994133],[20.55426,100.993599],[20.55397,100.993568],[20.55353,100.993156],[20.55308,100.992416],[20.552521,100.992332],[20.55209,100.992523],[20.551741,100.99231],[20.551531,100.991898],[20.55085,100.990868],[20.55032,100.990334],[20.549789,100.990082],[20.549299,100.989761],[20.54896,100.989288],[20.54842,100.988937],[20.547911,100.989052],[20.547541,100.989052],[20.54726,100.988808],[20.547199,100.988564],[20.547291,100.988129],[20.54792,100.987732],[20.548281,100.987221],[20.54855,100.986969],[20.54892,100.98597],[20.549141,100.985703],[20.54917,100.985458],[20.549219,100.984077],[20.548691,100.982964],[20.54842,100.981506],[20.548479,100.980377],[20.5481,100.978722],[20.54752,100.978149],[20.54685,100.977989],[20.54624,100.97744],[20.5457,100.976273],[20.5452,100.975906],[20.544399,100.975807],[20.54377,100.975662],[20.542471,100.975243],[20.54208,100.974892],[20.54159,100.974548],[20.539921,100.973717],[20.53916,100.973557],[20.538691,100.973351],[20.538179,100.973351],[20.5369,100.974091],[20.536739,100.974319],[20.536341,100.974571],[20.535971,100.974487],[20.535299,100.974068],[20.53492,100.973717],[20.534109,100.973328],[20.53293,100.973343],[20.531759,100.97274],[20.53125,100.972107],[20.53051,100.970657],[20.53039,100.969528],[20.5303,100.969162],[20.53018,100.968811],[20.5298,100.968231],[20.52944,100.967308],[20.529369,100.966843],[20.528959,100.966469],[20.528351,100.966072],[20.528219,100.965103],[20.527941,100.963737],[20.527439,100.963303],[20.526911,100.962936],[20.526951,100.962593],[20.526859,100.962067],[20.526461,100.961693],[20.526291,100.961227],[20.526251,100.960648],[20.525999,100.960114],[20.525721,100.959808],[20.525379,100.959648],[20.52515,100.95961],[20.52487,100.959358],[20.524879,100.959],[20.52479,100.958633],[20.524349,100.957977],[20.52438,100.957527],[20.52458,100.956757],[20.524401,100.956306],[20.523899,100.955887],[20.52313,100.955688],[20.521749,100.955513],[20.52129,100.955353],[20.520531,100.955307],[20.519991,100.955101],[20.51984,100.954948],[20.51955,100.954887],[20.51899,100.954674],[20.51889,100.954483],[20.518459,100.954193],[20.517891,100.954369],[20.51753,100.954918],[20.517229,100.955589],[20.516911,100.955673],[20.516781,100.955406],[20.51675,100.955177],[20.516399,100.95488],[20.516001,100.955002],[20.51556,100.954964],[20.515129,100.955009],[20.51465,100.954941],[20.514441,100.954613],[20.514151,100.954613],[20.513359,100.954933],[20.512911,100.955147],[20.512659,100.955383],[20.512381,100.955353],[20.512211,100.955177],[20.511669,100.954857],[20.510799,100.954773],[20.51033,100.95462],[20.509859,100.95462],[20.509159,100.954979],[20.508619,100.95491],[20.508591,100.954819],[20.50824,100.954483],[20.507959,100.954536],[20.50754,100.954376],[20.50742,100.953873],[20.5072,100.953484],[20.506941,100.953117],[20.506491,100.952904],[20.50629,100.95295],[20.50569,100.952927],[20.505541,100.952667],[20.505461,100.95208],[20.505541,100.951523],[20.50552,100.951027],[20.50514,100.95005],[20.504801,100.949707],[20.5047,100.949722],[20.504009,100.949532],[20.50391,100.949249],[20.50391,100.948463],[20.504061,100.94799],[20.50411,100.947418],[20.50355,100.946037],[20.503401,100.945763],[20.503059,100.945679],[20.502661,100.945686],[20.50226,100.945457],[20.501881,100.945129],[20.50157,100.945236],[20.501011,100.945084],[20.500731,100.944633],[20.500641,100.944183],[20.49922,100.941566],[20.499359,100.940933],[20.499519,100.94046],[20.499371,100.940048],[20.499241,100.93988],[20.498859,100.93972],[20.498159,100.939621],[20.4972,100.939293],[20.496759,100.939034],[20.495871,100.938087],[20.49571,100.937851],[20.49563,100.937263],[20.495661,100.93663],[20.495871,100.936119],[20.49629,100.935638],[20.496309,100.935127],[20.496031,100.934868],[20.49571,100.934036],[20.49589,100.933388],[20.495741,100.932892],[20.49498,100.932777],[20.49445,100.932426],[20.49431,100.931923],[20.494341,100.931267],[20.49431,100.931099],[20.494011,100.930893],[20.49321,100.930763],[20.492571,100.930313],[20.49185,100.928413],[20.491751,100.927803],[20.49176,100.927254],[20.49139,100.92659],[20.49098,100.926178],[20.490841,100.925911],[20.490829,100.925552],[20.491171,100.924057],[20.49114,100.923424],[20.49077,100.92276],[20.489731,100.921677],[20.48945,100.921021],[20.489349,100.920464],[20.489,100.919884],[20.4884,100.919647],[20.48777,100.919579],[20.487341,100.919411],[20.487,100.918861],[20.486811,100.918312],[20.485781,100.918266],[20.48568,100.918182],[20.485201,100.917587],[20.48465,100.916412],[20.484159,100.91584],[20.482771,100.914902],[20.4821,100.914253],[20.48135,100.912987],[20.480671,100.912178],[20.480471,100.911392],[20.480471,100.91098],[20.480089,100.910461],[20.479731,100.910301],[20.479071,100.90979],[20.47794,100.909103],[20.477369,100.908531],[20.476601,100.906883],[20.47571,100.90554],[20.474541,100.904732],[20.473881,100.904083],[20.472811,100.903282],[20.47242,100.903183],[20.472,100.903503],[20.471279,100.904449],[20.470301,100.904877],[20.469681,100.904831],[20.46957,100.904793],[20.46909,100.904823],[20.46899,100.9049],[20.468519,100.905083],[20.468321,100.904953],[20.467649,100.904373],[20.46719,100.904243],[20.466841,100.904373],[20.46665,100.904541],[20.4662,100.90477],[20.466,100.904678],[20.46546,100.903999],[20.465309,100.903397],[20.465151,100.902946],[20.464861,100.902763],[20.464399,100.902634],[20.464001,100.902367],[20.463751,100.901993],[20.463631,100.901466],[20.46343,100.901207],[20.463039,100.901466],[20.46282,100.90168],[20.462469,100.901588],[20.46212,100.900787],[20.46162,100.900551],[20.46133,100.900681],[20.46069,100.900719],[20.45845,100.899513],[20.457861,100.899582],[20.45747,100.899841],[20.456659,100.900284],[20.456261,100.900414],[20.455641,100.900398],[20.455151,100.900307],[20.455021,100.900269],[20.454729,100.900047],[20.45451,100.899963],[20.45429,100.899986],[20.45396,100.900497],[20.45385,100.901176],[20.453739,100.90139],[20.453609,100.901497],[20.452829,100.901802],[20.452379,100.902184],[20.452061,100.902313],[20.451651,100.902046],[20.451401,100.902023],[20.451059,100.902046],[20.450279,100.902458],[20.45005,100.902367],[20.449881,100.902206],[20.44982,100.902008],[20.4499,100.901688],[20.45009,100.90136],[20.45014,100.900932],[20.449961,100.900688],[20.449631,100.900429],[20.44912,100.900352],[20.448231,100.900642],[20.447929,100.900574],[20.44776,100.900124],[20.447121,100.899727],[20.446989,100.89901],[20.446911,100.898842],[20.44643,100.898232],[20.44639,100.897873],[20.446119,100.897621],[20.445709,100.897324],[20.44548,100.897087],[20.44516,100.896988],[20.44486,100.896957],[20.44445,100.896759],[20.443979,100.896339],[20.44319,100.89537],[20.44272,100.895103],[20.44248,100.894997],[20.44202,100.894943],[20.441351,100.894531],[20.441059,100.893669],[20.44046,100.892189],[20.43977,100.890793],[20.43943,100.890282],[20.438919,100.889763],[20.43788,100.889023],[20.43775,100.888542],[20.437759,100.888077],[20.43762,100.887833],[20.43714,100.887604],[20.43623,100.887047],[20.43495,100.886482],[20.43429,100.886368],[20.433781,100.886124],[20.433281,100.885551],[20.432489,100.884438],[20.43186,100.883698],[20.431721,100.883377],[20.43148,100.882393],[20.43161,100.881477],[20.431881,100.880569],[20.432011,100.879272],[20.432039,100.878532],[20.4324,100.877853],[20.43273,100.877502],[20.432911,100.877068],[20.43289,100.876793],[20.4321,100.875381],[20.43191,100.874802],[20.43194,100.87458],[20.432581,100.872719],[20.432581,100.872276],[20.43252,100.872063],[20.43162,100.870483],[20.431311,100.870262],[20.430981,100.870163],[20.43005,100.869987],[20.429199,100.869553],[20.428631,100.869164],[20.42746,100.868912],[20.42679,100.868423],[20.425791,100.865967],[20.425171,100.865547],[20.42388,100.865791],[20.42346,100.865646],[20.422541,100.865097],[20.42201,100.865021],[20.42149,100.86512],[20.421021,100.865021],[20.42034,100.864563],[20.41993,100.86441],[20.418819,100.864616],[20.4179,100.864693],[20.417549,100.864601],[20.417191,100.864342],[20.416691,100.863647],[20.41651,100.863052],[20.416361,100.862183],[20.41654,100.86145],[20.417061,100.861153],[20.417681,100.86113],[20.418091,100.860687],[20.41827,100.859192],[20.418051,100.858353],[20.41744,100.857529],[20.41696,100.856644],[20.41647,100.855377],[20.416161,100.854729],[20.41585,100.853371],[20.41531,100.852493],[20.414829,100.851921],[20.41411,100.851807],[20.413851,100.851913],[20.41334,100.851891],[20.41227,100.851173],[20.411011,100.850693],[20.41024,100.850456],[20.409161,100.850647],[20.4083,100.851181],[20.40797,100.851501],[20.407829,100.85173],[20.407471,100.851898],[20.40719,100.851692],[20.406799,100.851608],[20.406441,100.85186],[20.40589,100.851952],[20.405939,100.851692],[20.40617,100.851547],[20.406401,100.851303],[20.406481,100.850723],[20.4063,100.850304],[20.4062,100.849747],[20.406031,100.849426],[20.40575,100.84903],[20.405689,100.848663],[20.405701,100.848289],[20.4056,100.848053],[20.405199,100.847672],[20.404961,100.847282],[20.4039,100.844551],[20.40336,100.84343],[20.40317,100.84256],[20.402519,100.841721],[20.40229,100.841179],[20.402269,100.840698],[20.40242,100.840233],[20.40267,100.839737],[20.402769,100.838913],[20.40255,100.838364],[20.402349,100.838127],[20.401461,100.837593],[20.401011,100.837212],[20.40053,100.836159],[20.400261,100.835037],[20.39954,100.833992],[20.399269,100.83374],[20.398939,100.83287],[20.398991,100.832283],[20.39875,100.83165],[20.398331,100.83136],[20.3974,100.83091],[20.39673,100.83007],[20.396311,100.829826],[20.3958,100.829758],[20.395069,100.82946],[20.39382,100.828629],[20.39279,100.828011],[20.392191,100.827499],[20.391821,100.826736],[20.391741,100.825974],[20.39159,100.8255],[20.391411,100.825127],[20.38825,100.819542],[20.38793,100.819183],[20.387569,100.818626],[20.387489,100.818451],[20.387341,100.817963],[20.38714,100.816818],[20.386801,100.815941],[20.386749,100.815369],[20.38707,100.81385],[20.387199,100.813408],[20.387409,100.813042],[20.387449,100.81279],[20.38743,100.812622],[20.387119,100.812263],[20.386539,100.81205],[20.386061,100.811661],[20.385509,100.811409],[20.38489,100.811539],[20.3846,100.811523],[20.38423,100.811234],[20.383739,100.810417],[20.38348,100.810173],[20.38299,100.809921],[20.382561,100.809387],[20.38196,100.807297],[20.38113,100.805763],[20.380911,100.804916],[20.38061,100.804077],[20.38055,100.803352],[20.38064,100.802711],[20.3804,100.801903],[20.379869,100.801193],[20.3792,100.8004],[20.378929,100.799477],[20.378759,100.798393],[20.37841,100.797707],[20.377251,100.796219],[20.376989,100.795158],[20.376949,100.793961],[20.37689,100.793716],[20.375931,100.79213],[20.37571,100.791107],[20.375681,100.789543],[20.375401,100.788361],[20.374701,100.786774],[20.374371,100.785843],[20.372959,100.782387],[20.372789,100.781883],[20.3727,100.781303],[20.37212,100.780533],[20.37154,100.779892],[20.371189,100.779694],[20.37081,100.779663],[20.37048,100.7798],[20.36981,100.780281],[20.368521,100.780807],[20.368019,100.780952],[20.367649,100.780861],[20.367491,100.780609],[20.367319,100.780083],[20.367041,100.779579],[20.36451,100.776817],[20.364189,100.776627],[20.363819,100.776787],[20.363609,100.777168],[20.3634,100.777367],[20.362921,100.777603],[20.3626,100.777847],[20.36236,100.777977],[20.362089,100.77774],[20.362089,100.777489],[20.362631,100.776283],[20.36305,100.774963],[20.363199,100.7743],[20.36344,100.773872],[20.363831,100.773392],[20.363911,100.77298],[20.363729,100.772507],[20.363569,100.772301],[20.36347,100.771698],[20.363581,100.771027],[20.36319,100.770531],[20.36265,100.769958],[20.36215,100.769112],[20.36161,100.768837],[20.36137,100.768867],[20.36116,100.768822],[20.36088,100.768646],[20.360689,100.768097],[20.360809,100.767242],[20.360649,100.766617],[20.36017,100.765137],[20.36006,100.764549],[20.360109,100.763947],[20.360519,100.763573],[20.36062,100.763557],[20.36084,100.76339],[20.360979,100.762657],[20.361469,100.762306],[20.36165,100.762062],[20.361641,100.761658],[20.361,100.760948],[20.36079,100.760422],[20.36071,100.76001],[20.3608,100.759506],[20.360941,100.759323],[20.361179,100.759109],[20.36128,100.758728],[20.361179,100.758553],[20.36101,100.757988],[20.361059,100.757187],[20.361031,100.756912],[20.36109,100.756393],[20.360991,100.75592],[20.360701,100.755699],[20.360519,100.755363],[20.3605,100.755219],[20.360491,100.754608],[20.3606,100.754219],[20.36092,100.753792],[20.36104,100.752907],[20.360901,100.752434],[20.36084,100.750587],[20.36058,100.749977],[20.360451,100.749313],[20.3603,100.748833],[20.360041,100.748421],[20.359171,100.747307],[20.35895,100.746758],[20.358841,100.745842],[20.358509,100.744392],[20.358709,100.743652],[20.35891,100.743362],[20.35898,100.742538],[20.3589,100.742188],[20.35845,100.741653],[20.357941,100.741547],[20.35754,100.741432],[20.356831,100.740913],[20.356331,100.740807],[20.35593,100.740837],[20.35537,100.740517],[20.355209,100.740196],[20.354429,100.738113],[20.35376,100.736107],[20.353001,100.734627],[20.352421,100.733772],[20.352209,100.733543],[20.351999,100.733192],[20.351879,100.73275],[20.351839,100.732262],[20.351891,100.731537],[20.35169,100.730789],[20.351521,100.730362],[20.35149,100.729736],[20.35153,100.729507],[20.35186,100.729012],[20.353081,100.727547],[20.355471,100.725609],[20.355841,100.724991],[20.35594,100.724503],[20.35598,100.721733],[20.355761,100.721252],[20.354799,100.7202],[20.354271,100.719833],[20.35388,100.719398],[20.35384,100.718674],[20.35331,100.717789],[20.35264,100.717194],[20.35252,100.71669],[20.35284,100.715897],[20.35318,100.715599],[20.353701,100.715561],[20.35397,100.715111],[20.35391,100.714462],[20.354231,100.713768],[20.35479,100.713478],[20.35507,100.71312],[20.355579,100.712921],[20.35626,100.713051],[20.357,100.71286],[20.35745,100.712578],[20.358089,100.711929],[20.35874,100.711441],[20.35887,100.711403],[20.35931,100.711357],[20.35961,100.711456],[20.36083,100.712143],[20.36128,100.71212],[20.36129,100.711639],[20.36125,100.71096],[20.36128,100.710663],[20.361561,100.710159],[20.36167,100.709839],[20.361679,100.709351],[20.36149,100.708809],[20.3615,100.70829],[20.36186,100.707458],[20.361879,100.706818],[20.36179,100.705933],[20.361799,100.704933],[20.361879,100.704659],[20.36215,100.704163],[20.36253,100.703773],[20.36327,100.703308],[20.36344,100.70314],[20.363621,100.702858],[20.363569,100.7024],[20.363199,100.701279],[20.36265,100.700531],[20.362511,100.700272],[20.3627,100.698997],[20.363359,100.69799],[20.363741,100.696861],[20.364189,100.695938],[20.365049,100.694862],[20.36602,100.693771],[20.367121,100.692047],[20.367201,100.691879],[20.36727,100.690613],[20.36672,100.689194],[20.366659,100.688438],[20.366449,100.687683],[20.366079,100.687073],[20.365471,100.686607],[20.36454,100.686203],[20.364031,100.685371],[20.364111,100.684464],[20.36484,100.682533],[20.36484,100.682167],[20.364559,100.680946],[20.364309,100.680222],[20.364389,100.679558],[20.36446,100.679359],[20.364479,100.678917],[20.364429,100.678467],[20.364491,100.678032],[20.364611,100.677727],[20.364639,100.677147],[20.36442,100.676842],[20.36405,100.676666],[20.3631,100.676376],[20.36293,100.676277],[20.362341,100.675774],[20.36183,100.675163],[20.36145,100.674423],[20.361349,100.674026],[20.361389,100.672523],[20.36096,100.670631],[20.36039,100.66877],[20.36035,100.667908],[20.3601,100.667038],[20.359289,100.665192],[20.358999,100.664146],[20.35878,100.663017],[20.35887,100.662514],[20.358971,100.662277],[20.35936,100.661819],[20.359591,100.661163],[20.359501,100.660599],[20.359249,100.659683],[20.35911,100.657623],[20.358919,100.657127],[20.35828,100.656113],[20.358061,100.655678],[20.358009,100.654892],[20.3578,100.65432],[20.356991,100.653603],[20.356319,100.652359],[20.35602,100.651573],[20.355881,100.650909],[20.355579,100.648392],[20.355459,100.647987],[20.355089,100.647163],[20.355061,100.646568],[20.35541,100.646088],[20.3556,100.6455],[20.35557,100.644867],[20.355499,100.644569],[20.35507,100.643646],[20.35486,100.642967],[20.35471,100.642616],[20.354441,100.642212],[20.354469,100.641777],[20.355169,100.641617],[20.35548,100.641289],[20.355471,100.641037],[20.35537,100.640633],[20.35556,100.640099],[20.35564,100.639603],[20.35552,100.639214],[20.35527,100.638763],[20.35511,100.637718],[20.35515,100.637253],[20.355499,100.636238],[20.355551,100.635612],[20.35533,100.634941],[20.355101,100.634422],[20.355089,100.633911],[20.35535,100.633087],[20.355749,100.632797],[20.356001,100.632721],[20.35652,100.632339],[20.35663,100.632118],[20.357059,100.631897],[20.357349,100.632187],[20.35779,100.633057],[20.35833,100.633522],[20.359249,100.633881],[20.35972,100.633789],[20.3606,100.633453],[20.36109,100.63372],[20.36145,100.633698],[20.36198,100.633423],[20.36241,100.6325],[20.36285,100.631653],[20.36348,100.631264],[20.36356,100.630981],[20.36334,100.629883],[20.363649,100.629463],[20.363951,100.629417],[20.364241,100.629646],[20.36475,100.630089],[20.366261,100.630089],[20.36676,100.630257],[20.36722,100.630241],[20.367359,100.630096],[20.367661,100.62915],[20.36801,100.628601],[20.36879,100.628143],[20.369249,100.627342],[20.36919,100.6269],[20.368679,100.626373],[20.36817,100.624977],[20.36775,100.62352],[20.36764,100.622238],[20.36821,100.621208],[20.368561,100.620399],[20.36894,100.617233],[20.36931,100.615646],[20.369789,100.614014],[20.370131,100.613327],[20.37133,100.612297],[20.371679,100.611603],[20.37171,100.611191],[20.371889,100.610779],[20.37208,100.610573],[20.372219,100.610008],[20.371969,100.609047],[20.372511,100.607971],[20.374069,100.606483],[20.374969,100.605927],[20.376051,100.606056],[20.38036,100.602577],[20.38096,100.601677],[20.381519,100.600143],[20.38242,100.598907],[20.382891,100.596527],[20.383659,100.594353],[20.385059,100.59182],[20.38669,100.590233],[20.387131,100.587471],[20.387171,100.586563],[20.38603,100.583878],[20.380939,100.576797],[20.380171,100.575996],[20.36994,100.571991],[20.36841,100.570488],[20.3664,100.568863],[20.36528,100.567017],[20.364679,100.564987],[20.360701,100.554718],[20.358471,100.553917],[20.35429,100.54924],[20.35074,100.543022],[20.349541,100.541199],[20.348101,100.539291],[20.347191,100.538368],[20.342621,100.534698],[20.341419,100.533577],[20.340731,100.532547],[20.338511,100.530228],[20.337061,100.528732],[20.336281,100.528328],[20.33316,100.527657],[20.33197,100.526894],[20.33049,100.525299],[20.329559,100.524841],[20.32822,100.524857],[20.32708,100.524368],[20.32666,100.523468],[20.326349,100.5215],[20.325621,100.518784],[20.324909,100.518204],[20.324181,100.518158],[20.323641,100.518646],[20.321939,100.520767],[20.321239,100.521683],[20.320419,100.522118],[20.319901,100.522209],[20.318251,100.522148],[20.317381,100.522507],[20.316191,100.523354],[20.31547,100.523369],[20.31489,100.522926],[20.314529,100.52272],[20.313761,100.522552],[20.311609,100.520554],[20.310949,100.519928],[20.30965,100.518463],[20.30732,100.516968],[20.306,100.516747],[20.30275,100.517471],[20.300171,100.516441],[20.29899,100.51564],[20.29772,100.514442],[20.29727,100.512657],[20.297359,100.511261],[20.29715,100.510277],[20.296301,100.509506],[20.29497,100.509071],[20.29368,100.509033],[20.29195,100.506844],[20.2903,100.50457],[20.285521,100.502708],[20.283449,100.498299],[20.283251,100.496407],[20.280399,100.493027],[20.27717,100.491127],[20.27722,100.485771],[20.27581,100.479683],[20.274639,100.478523],[20.276501,100.473183],[20.27618,100.469414],[20.274891,100.467171],[20.273279,100.463387],[20.26845,100.46254],[20.26667,100.463539],[20.264891,100.464142],[20.263081,100.463921],[20.261669,100.464081],[20.26067,100.463333],[20.25362,100.451843],[20.251631,100.44397],[20.249929,100.44194],[20.24954,100.441002],[20.24959,100.439781],[20.249439,100.438667],[20.24979,100.437653],[20.250509,100.43676],[20.251249,100.436211],[20.251579,100.435791],[20.2516,100.434952],[20.25148,100.434082],[20.251381,100.433037],[20.25115,100.432297],[20.250879,100.431953],[20.25086,100.43148],[20.251381,100.430908],[20.25153,100.430489],[20.25128,100.430344],[20.25071,100.430359],[20.25016,100.430138],[20.25004,100.429741],[20.24996,100.428307],[20.25029,100.426987],[20.2505,100.426437],[20.25102,100.425758],[20.251671,100.425217],[20.252331,100.42408],[20.25292,100.42347],[20.25317,100.422729],[20.25334,100.422363],[20.254629,100.420921],[20.25526,100.420212],[20.25573,100.419533],[20.256161,100.418854],[20.2575,100.418037],[20.26022,100.416687],[20.26158,100.416077],[20.26276,100.415337],[20.263371,100.415131],[20.264509,100.415283],[20.26535,100.415337],[20.26556,100.415237],[20.26605,100.414757],[20.26685,100.414177],[20.267191,100.414017],[20.26763,100.413971],[20.26852,100.413879],[20.269581,100.413933],[20.270361,100.413727],[20.27227,100.413208],[20.27359,100.412773],[20.274349,100.412514],[20.27471,100.412376],[20.27606,100.411873],[20.276831,100.411552],[20.276409,100.410561],[20.276279,100.410294],[20.27615,100.409988],[20.27606,100.409683],[20.27594,100.409302],[20.275141,100.406822],[20.27511,100.40654],[20.275169,100.406197],[20.275311,100.406013],[20.275841,100.405251],[20.27589,100.404793],[20.275749,100.404839],[20.27441,100.405243],[20.27425,100.403351],[20.27413,100.402611],[20.27413,100.401932],[20.27434,100.401443],[20.274639,100.401062],[20.274851,100.400742],[20.274929,100.400337],[20.27487,100.399857],[20.27471,100.399567],[20.27459,100.399223],[20.274679,100.398827],[20.27494,100.398552],[20.27527,100.398163],[20.275551,100.397858],[20.275881,100.397522],[20.276079,100.397163],[20.276199,100.396843],[20.27632,100.396652],[20.27663,100.396622],[20.276911,100.396667],[20.27717,100.396584],[20.277411,100.396347],[20.27774,100.396149],[20.278099,100.39595],[20.27853,100.395973],[20.27895,100.396049],[20.279409,100.396217],[20.279831,100.396118],[20.280199,100.395813],[20.28047,100.3955],[20.280781,100.395203],[20.281601,100.394882],[20.282761,100.394447],[20.28368,100.394043],[20.28441,100.393593],[20.28524,100.393028],[20.28595,100.392647],[20.28698,100.391853],[20.28813,100.390877],[20.288759,100.390312],[20.289141,100.390083],[20.289619,100.389954],[20.289841,100.389992],[20.290581,100.390106],[20.291149,100.390129],[20.291599,100.390091],[20.29217,100.389877],[20.292589,100.389542],[20.292999,100.389359],[20.293369,100.389374],[20.293961,100.389542],[20.29447,100.389641],[20.294821,100.38961],[20.295271,100.38929],[20.295679,100.388977],[20.296261,100.388687],[20.296801,100.388641],[20.29731,100.388573],[20.29837,100.388542],[20.30019,100.388527],[20.30183,100.388512],[20.302429,100.388474],[20.30319,100.38829],[20.303801,100.388153],[20.3043,100.388008],[20.304621,100.387787],[20.304831,100.387444],[20.30509,100.386993],[20.30526,100.386574],[20.305479,100.386139],[20.30575,100.385818],[20.30608,100.385567],[20.306459,100.385223],[20.30687,100.38485],[20.307541,100.384323],[20.308189,100.383972],[20.30883,100.383537],[20.309139,100.383232],[20.309401,100.382782],[20.309681,100.382477],[20.31003,100.382294],[20.31057,100.382057],[20.31098,100.381866],[20.31156,100.381599],[20.31197,100.381378],[20.3123,100.381279],[20.312639,100.381027],[20.312889,100.380707],[20.313,100.380417],[20.313311,100.380112],[20.313641,100.379959],[20.31443,100.380043],[20.314791,100.380081],[20.315161,100.380127],[20.315491,100.379982],[20.31592,100.379784],[20.31637,100.379608],[20.31674,100.379433],[20.317169,100.379242],[20.3176,100.379158],[20.318119,100.379059],[20.31848,100.378937],[20.31889,100.37886],[20.319321,100.37886],[20.319889,100.37899],[20.3204,100.379143],[20.3209,100.379341],[20.321369,100.379547],[20.3218,100.379631],[20.322241,100.379623],[20.322611,100.379562],[20.32299,100.379532],[20.323339,100.379608],[20.323641,100.379692],[20.32411,100.379707],[20.32449,100.379662],[20.324921,100.379608],[20.32535,100.379517],[20.325729,100.379341],[20.326059,100.379143],[20.326441,100.379028],[20.32682,100.378967],[20.327221,100.37899],[20.32765,100.37886],[20.328011,100.378616],[20.32826,100.378326],[20.32863,100.377823],[20.328859,100.377487],[20.329109,100.377243],[20.32934,100.37706],[20.32963,100.376953],[20.329941,100.37664],[20.330299,100.376266],[20.330561,100.376167],[20.330811,100.376137],[20.331169,100.37616],[20.33145,100.376137],[20.331779,100.37606],[20.33213,100.375977],[20.332411,100.375961],[20.33263,100.376106],[20.332979,100.376221],[20.33329,100.376259],[20.33354,100.376228],[20.3339,100.37606],[20.3342,100.375877],[20.334539,100.375771],[20.334829,100.375763],[20.335251,100.37574],[20.335541,100.375763],[20.336029,100.375687],[20.33626,100.375671],[20.33643,100.375603],[20.3367,100.375473],[20.33703,100.37532],[20.337179,100.375252],[20.33742,100.375221],[20.337721,100.375191],[20.33802,100.375168],[20.338261,100.375038],[20.3384,100.37484],[20.33847,100.374542],[20.338579,100.374367],[20.33876,100.374283],[20.33905,100.374123],[20.339331,100.37397],[20.33963,100.373917],[20.33988,100.373917],[20.340219,100.37394],[20.34067,100.374039],[20.34096,100.374138],[20.34128,100.374191],[20.341631,100.374268],[20.34194,100.374222],[20.342171,100.374153],[20.34252,100.373993],[20.342779,100.373787],[20.342979,100.373619],[20.343149,100.37355],[20.343321,100.373573],[20.343439,100.373718],[20.343571,100.373993],[20.343639,100.374237],[20.343809,100.374451],[20.343969,100.374527],[20.3442,100.374588],[20.34449,100.374496],[20.34466,100.374367],[20.34499,100.374252],[20.345261,100.374168],[20.34564,100.373993],[20.3459,100.373756],[20.346201,100.373489],[20.346491,100.373222],[20.346901,100.372871],[20.34734,100.372421],[20.347401,100.372139],[20.347389,100.371803],[20.34742,100.371429],[20.34758,100.371147],[20.347691,100.370857],[20.347719,100.370499],[20.34775,100.370102],[20.34761,100.369751],[20.34746,100.369431],[20.347361,100.369164],[20.347429,100.368942],[20.34758,100.368767],[20.347799,100.368683],[20.348209,100.368736],[20.34856,100.368912],[20.34897,100.36911],[20.34931,100.369164],[20.349791,100.369118],[20.349871,100.368912],[20.34984,100.368584],[20.349751,100.368134],[20.34972,100.367828],[20.349819,100.367561],[20.35001,100.367409],[20.35022,100.367233],[20.3503,100.367058],[20.35021,100.366707],[20.34993,100.366386],[20.349001,100.365578],[20.34866,100.365158],[20.34852,100.364922],[20.34848,100.364563],[20.348579,100.364326],[20.34877,100.36412],[20.34897,100.363853],[20.348961,100.363533],[20.348801,100.363327],[20.348669,100.362938],[20.34873,100.362701],[20.348989,100.362427],[20.349251,100.362289],[20.34955,100.362137],[20.349911,100.362083],[20.35025,100.362068],[20.350719,100.361977],[20.351009,100.361893],[20.35121,100.361671],[20.35161,100.361397],[20.35191,100.361214],[20.35211,100.360901],[20.352079,100.360527],[20.35183,100.360138],[20.35158,100.359779],[20.35137,100.359253],[20.351299,100.358719],[20.351219,100.358002],[20.351151,100.357384],[20.35108,100.356857],[20.35088,100.356483],[20.3505,100.35611],[20.350109,100.355629],[20.349871,100.355217],[20.349701,100.354683],[20.349489,100.353912],[20.3491,100.352753],[20.348801,100.351936],[20.347561,100.350304],[20.346901,100.349297],[20.34656,100.348129],[20.34656,100.346901],[20.34639,100.345123],[20.34589,100.342987],[20.34516,100.339973],[20.344601,100.337914],[20.34466,100.335854],[20.344879,100.334167],[20.345329,100.333328],[20.34606,100.332893],[20.346901,100.333107],[20.34745,100.332718],[20.34734,100.3321],[20.34667,100.3321],[20.34568,100.33152],[20.34479,100.33123],[20.344589,100.330742],[20.34436,100.330368],[20.3437,100.330139],[20.34333,100.329803],[20.343019,100.32917],[20.342899,100.328369],[20.342899,100.32785],[20.343189,100.327393],[20.34322,100.326973],[20.34284,100.326714],[20.341669,100.326073],[20.341101,100.325531],[20.34067,100.325218],[20.339979,100.325218],[20.33952,100.325363],[20.338831,100.325241],[20.337999,100.324783],[20.33737,100.324211],[20.336769,100.323593],[20.335369,100.321274],[20.33522,100.320747],[20.334881,100.320259],[20.334339,100.319633],[20.334311,100.319199],[20.334391,100.318741],[20.33345,100.317093],[20.33288,100.317253],[20.332331,100.317337],[20.332081,100.317047],[20.33202,100.316566],[20.331619,100.316277],[20.32967,100.315422],[20.328091,100.314957],[20.32715,100.314362],[20.32658,100.313927],[20.326229,100.313393],[20.32612,100.312607],[20.32629,100.311546],[20.326151,100.310982],[20.325741,100.310516],[20.325371,100.310013],[20.325371,100.30941],[20.325689,100.307892],[20.32563,100.307426],[20.32514,100.306969],[20.324711,100.306427],[20.324051,100.305222],[20.323879,100.304573],[20.32357,100.303909],[20.32328,100.302879],[20.32291,100.301643],[20.322769,100.299751],[20.322571,100.298439],[20.32239,100.298073],[20.32202,100.297722],[20.32185,100.297348],[20.32165,100.296204],[20.321079,100.29483],[20.32073,100.293877],[20.32056,100.293022],[20.320789,100.290817],[20.320669,100.290329],[20.32053,100.289558],[20.31967,100.287437],[20.319361,100.287117],[20.31864,100.287163],[20.31818,100.28672],[20.31793,100.286179],[20.317381,100.284973],[20.31695,100.284317],[20.31624,100.283859],[20.31472,100.282997],[20.31423,100.2826],[20.313431,100.281357],[20.311621,100.277206],[20.31111,100.275887],[20.31082,100.275146],[20.30908,100.273827],[20.308451,100.273232],[20.307671,100.27137],[20.306641,100.269279],[20.306499,100.268623],[20.306499,100.265617],[20.306391,100.264183],[20.306129,100.263184],[20.305241,100.259972],[20.304871,100.258171],[20.304581,100.256622],[20.304291,100.253304],[20.30401,100.252586],[20.30341,100.252007],[20.302691,100.251839],[20.30192,100.251839],[20.301399,100.251747],[20.301121,100.251442],[20.300911,100.250214],[20.301001,100.247398],[20.30077,100.24614],[20.30043,100.245506],[20.29974,100.243019],[20.29954,100.240044],[20.29954,100.239563],[20.2992,100.239067],[20.29874,100.23864],[20.29825,100.238319],[20.29814,100.238037],[20.298161,100.234253],[20.29882,100.231483],[20.29908,100.229813],[20.299391,100.228607],[20.29949,100.227859],[20.299549,100.227211],[20.299721,100.226501],[20.299419,100.226082],[20.29817,100.224533],[20.29698,100.223846],[20.29533,100.22316],[20.29389,100.222473],[20.29315,100.222061],[20.292789,100.22155],[20.29199,100.221207],[20.29141,100.220932],[20.29093,100.220421],[20.29035,100.220078],[20.289249,100.219971],[20.288321,100.219727],[20.28706,100.219116],[20.28581,100.218048],[20.28484,100.217056],[20.283461,100.215637],[20.28233,100.214523],[20.280979,100.213013],[20.280149,100.211906],[20.27915,100.210457],[20.27844,100.209396],[20.278021,100.208717],[20.27783,100.207817],[20.27783,100.206902],[20.277571,100.205872],[20.27689,100.204773],[20.27615,100.203918],[20.27496,100.202103],[20.27429,100.200829],[20.27364,100.199516],[20.27281,100.19873],[20.271811,100.197639],[20.27062,100.196159],[20.27001,100.195267],[20.26927,100.194267],[20.26849,100.193413],[20.266081,100.191048],[20.265209,100.190262],[20.264339,100.189812],[20.26322,100.188988],[20.262699,100.188507],[20.26235,100.187859],[20.26174,100.186447],[20.260771,100.184647],[20.26021,100.182938],[20.26037,100.181908],[20.260679,100.180908],[20.2579,100.180527],[20.25491,100.17997],[20.253241,100.179314],[20.25135,100.179642],[20.249689,100.178421],[20.24847,100.17775],[20.247311,100.177437],[20.24621,100.177254],[20.2451,100.176331],[20.2435,100.174347],[20.242241,100.171883],[20.24194,100.171043],[20.24098,100.169128],[20.240601,100.167412],[20.24003,100.166458],[20.23889,100.165314],[20.238159,100.16391],[20.2374,100.161568],[20.237129,100.160439],[20.23694,100.157692],[20.23774,100.155632],[20.240351,100.150452],[20.24041,100.149551],[20.24004,100.149002],[20.238899,100.148613],[20.230089,100.145058],[20.227119,100.143799],[20.2234,100.144203],[20.22238,100.144028],[20.22163,100.14357],[20.22163,100.142311],[20.221689,100.136833],[20.22123,100.135452],[20.220779,100.134201],[20.2202,100.133003],[20.22032,100.132187],[20.220551,100.131569],[20.220949,100.130943],[20.22146,100.130539],[20.22238,100.130081],[20.2234,100.130028],[20.22426,100.130081],[20.225401,100.12957],[20.226839,100.128822],[20.228889,100.127907],[20.231239,100.126938],[20.232719,100.126312],[20.234501,100.125633],[20.235689,100.125282],[20.236549,100.125282],[20.23838,100.125557],[20.238951,100.125633],[20.239269,100.125359],[20.24003,100.124641],[20.24082,100.124222],[20.24209,100.123596],[20.24258,100.123177],[20.24321,100.122581],[20.24362,100.121933],[20.244169,100.120911],[20.244329,100.11969],[20.244141,100.114143],[20.244221,100.112823],[20.24461,100.111748],[20.24552,100.107658],[20.245569,100.105873],[20.246019,100.10495],[20.247499,100.102898],[20.248671,100.102791],[20.24914,100.102608],[20.25177,100.100777],[20.25688,100.097267],[20.258829,100.095711],[20.260731,100.093811],[20.259911,100.086281],[20.26025,100.084396],[20.261,100.082962],[20.262091,100.08181],[20.26926,100.076973],[20.26903,100.076843],[20.26845,100.076431],[20.26779,100.075684],[20.267691,100.075569],[20.2675,100.075333],[20.26725,100.074577],[20.267429,100.073776],[20.267599,100.073517],[20.267969,100.073036],[20.26873,100.072037],[20.268869,100.071808],[20.26894,100.071388],[20.268921,100.071098],[20.268801,100.069023],[20.26877,100.068626],[20.268709,100.067993],[20.26874,100.06781],[20.268801,100.067451],[20.269529,100.065788],[20.269621,100.065353],[20.26969,100.058792],[20.269739,100.057213],[20.269831,100.05687],[20.269979,100.056557],[20.27109,100.05513],[20.27137,100.054642],[20.27169,100.053932],[20.271879,100.053352],[20.2719,100.053291],[20.27212,100.051521],[20.27227,100.050903],[20.272511,100.050468],[20.272829,100.050049],[20.27322,100.049713],[20.27532,100.048187],[20.27696,100.046913],[20.278509,100.045799],[20.27902,100.04528],[20.279329,100.045052],[20.28196,100.043381],[20.28227,100.042969],[20.28232,100.042664],[20.28199,100.039772],[20.28216,100.037811],[20.28245,100.036713],[20.28249,100.03656],[20.283291,100.033943],[20.283461,100.032356],[20.28355,100.031937],[20.284889,100.027328],[20.28492,100.027069],[20.284889,100.026711],[20.284451,100.025642],[20.283649,100.02253],[20.282631,100.019608],[20.282459,100.019379],[20.2822,100.019218],[20.281549,100.018822],[20.281281,100.018517],[20.28104,100.017998],[20.28096,100.01783],[20.28046,100.016228],[20.280319,100.015823],[20.27994,100.014809],[20.27947,100.013863],[20.27894,100.012939],[20.278629,100.01239],[20.278191,100.011948],[20.277611,100.011673],[20.276871,100.011414],[20.276529,100.011253],[20.27626,100.010933],[20.2761,100.010567],[20.276011,100.009956],[20.276039,100.008537],[20.276131,100.008118],[20.276381,100.007423],[20.27643,100.007057],[20.27619,100.006447],[20.27611,100.005913],[20.276131,100.005661],[20.276541,100.004341],[20.27739,100.002243],[20.277519,100.001602],[20.27751,100.00135],[20.27717,100.000137],[20.27632,99.99839],[20.27622,99.997864],[20.27598,99.995117],[20.27578,99.994469],[20.2752,99.993393],[20.27483,99.992889],[20.274389,99.992393],[20.273899,99.991982],[20.2733,99.991608],[20.272711,99.991333],[20.27207,99.991112],[20.271151,99.990799],[20.26943,99.990196],[20.267929,99.989693],[20.26746,99.989517],[20.265051,99.98867],[20.260799,99.986908],[20.26021,99.986603],[20.25956,99.986122],[20.258579,99.98526],[20.25312,99.980637],[20.250441,99.978249],[20.249901,99.977707],[20.24902,99.976723],[20.24851,99.976128],[20.24799,99.975517],[20.243361,99.969711],[20.24229,99.968307],[20.23768,99.961952],[20.237089,99.961243],[20.23678,99.960907],[20.236469,99.960709],[20.23546,99.960403],[20.235189,99.960258],[20.235001,99.960167],[20.23457,99.959831],[20.23427,99.959534],[20.231171,99.955971],[20.23019,99.954781],[20.229759,99.954353],[20.22612,99.950317],[20.225361,99.949493],[20.223261,99.947304],[20.22253,99.946472],[20.22105,99.944946],[20.2173,99.940514],[20.21426,99.936852],[20.213909,99.936417],[20.210979,99.933022],[20.20336,99.924316],[20.20289,99.923752],[20.20256,99.923363],[20.20229,99.922813],[20.20085,99.919243],[20.200251,99.917732],[20.199671,99.916267],[20.199181,99.915077],[20.19784,99.911629],[20.19697,99.90963],[20.19672,99.908997],[20.196461,99.908287],[20.19632,99.907944],[20.19614,99.907539],[20.195181,99.905983],[20.19488,99.905342],[20.19462,99.904213],[20.19449,99.903137],[20.194229,99.901459],[20.19413,99.900963],[20.193979,99.90033],[20.19376,99.899719],[20.19334,99.898857],[20.192921,99.898331],[20.192261,99.897476],[20.1915,99.896606],[20.190639,99.895409],[20.187269,99.891022],[20.18634,99.889763],[20.185221,99.888191],[20.18457,99.887154],[20.18409,99.886269],[20.18368,99.885536],[20.18329,99.884857],[20.182751,99.883904],[20.18235,99.883186],[20.181841,99.882294],[20.181511,99.881844],[20.18092,99.881378],[20.18082,99.881287],[20.180349,99.880959],[20.179501,99.880363],[20.17819,99.879387],[20.176781,99.878387],[20.174061,99.87645],[20.17366,99.876106],[20.17345,99.875771],[20.1723,99.87352],[20.17215,99.873253],[20.17174,99.872673],[20.17095,99.872009],[20.169439,99.871193],[20.169069,99.87088],[20.16851,99.870308],[20.1668,99.869034],[20.16614,99.868408],[20.164459,99.866531],[20.163719,99.866043],[20.162889,99.865593],[20.160891,99.86451],[20.160801,99.864464],[20.16007,99.864059],[20.15867,99.863297],[20.157801,99.862694],[20.156269,99.861603],[20.156019,99.861389],[20.15589,99.861023],[20.15583,99.860527],[20.15589,99.860184],[20.155491,99.860199],[20.1551,99.860184],[20.1548,99.860092],[20.154181,99.859833],[20.154079,99.859734],[20.153299,99.8591],[20.152769,99.858704],[20.15164,99.858276],[20.147631,99.857521],[20.14694,99.857384],[20.14674,99.857361],[20.145821,99.857262],[20.14502,99.85717],[20.144711,99.85714],[20.143869,99.85704],[20.143379,99.856987],[20.142599,99.856903],[20.139759,99.856598],[20.13909,99.856613],[20.13855,99.856728],[20.137991,99.856918],[20.137341,99.85746],[20.13419,99.860947],[20.13195,99.862442],[20.13092,99.863426],[20.130289,99.863953],[20.12956,99.864464],[20.12685,99.867111],[20.12649,99.867317],[20.126051,99.867447],[20.12459,99.867813],[20.122669,99.868134],[20.12114,99.868584],[20.119909,99.869034],[20.119301,99.869392],[20.118059,99.87043],[20.11643,99.872063],[20.11577,99.87249],[20.11545,99.872627],[20.114981,99.872757],[20.09539,99.874527],[20.09425,99.874573],[20.090561,99.874893],[20.08865,99.874657],[20.08559,99.874527],[20.08499,99.87455],[20.080891,99.874908],[20.079241,99.875107],[20.07443,99.875717],[20.07328,99.875687],[20.06992,99.875542],[20.064859,99.875557],[20.06189,99.875443],[20.05637,99.875359],[20.05394,99.875443],[20.05282,99.875542],[20.049891,99.875992],[20.046709,99.876244],[20.0462,99.876266],[20.04603,99.876282],[20.045691,99.876312],[20.04425,99.876404],[20.04303,99.876297],[20.041679,99.876137],[20.04003,99.875839],[20.03854,99.875542],[20.03141,99.874046],[20.028919,99.873497],[20.026489,99.872787],[20.02272,99.87146],[20.01881,99.870377],[20.014919,99.86937],[20.01181,99.868759],[20.00489,99.867264],[20.004431,99.867188],[20.001101,99.866623],[19.99958,99.866287],[19.998461,99.865959],[19.994511,99.864754],[19.993469,99.864433],[19.991541,99.86377],[19.987789,99.862572],[19.983509,99.861198],[19.977421,99.859497],[19.9772,99.859444],[19.973289,99.858208],[19.969009,99.856873],[19.968769,99.856796],[19.967291,99.856339],[19.962219,99.854317],[19.96102,99.853737],[19.95957,99.853073],[19.956461,99.851562],[19.950371,99.848991],[19.95006,99.848846],[19.94776,99.848],[19.94174,99.8461],[19.941191,99.845947],[19.940399,99.845627],[19.939939,99.845512],[19.939461,99.845451],[19.93458,99.844978],[19.93329,99.844856],[19.9328,99.844833],[19.932329,99.844788],[19.93128,99.844658],[19.930479,99.844559],[19.92926,99.844452],[19.928101,99.844383],[19.927031,99.844254],[19.926519,99.844254],[19.9261,99.844322],[19.925659,99.844429],[19.924841,99.844704],[19.92466,99.844772],[19.92452,99.844833],[19.92285,99.84539],[19.91926,99.84671],[19.919029,99.846786],[19.9188,99.846863],[19.91856,99.846893],[19.918301,99.846916],[19.918011,99.846939],[19.9177,99.846916],[19.91733,99.846863],[19.91716,99.846832],[19.91688,99.846786],[19.91614,99.846657],[19.91597,99.846603],[19.915791,99.846542],[19.915649,99.846451],[19.9156,99.846413],[19.915449,99.846298],[19.91519,99.8461],[19.91506,99.845932],[19.914909,99.845734],[19.91482,99.845551],[19.9144,99.844727],[19.914,99.843964],[19.9137,99.843246],[19.913469,99.842857],[19.9133,99.842613],[19.913071,99.842331],[19.912821,99.842087],[19.91238,99.841667],[19.912121,99.841469],[19.911831,99.841248],[19.911221,99.840927],[19.9109,99.840782],[19.910589,99.840668],[19.910259,99.840652],[19.909861,99.840714],[19.90881,99.840759],[19.908581,99.840767],[19.90823,99.840813],[19.907591,99.840927],[19.907049,99.840973],[19.90662,99.840919],[19.906231,99.840958],[19.90579,99.840981],[19.90518,99.840973],[19.904579,99.840897],[19.903761,99.840767],[19.90309,99.840523],[19.9025,99.840378],[19.901751,99.840179],[19.901529,99.840134],[19.89817,99.839073],[19.896799,99.838638],[19.895309,99.838242],[19.89484,99.838097],[19.89209,99.837196],[19.89089,99.836861],[19.88945,99.836433],[19.879311,99.833359],[19.878031,99.832413],[19.87665,99.831192],[19.872709,99.827423],[19.862711,99.821381],[19.84935,99.809143],[19.836611,99.787727],[19.82707,99.775383],[19.824829,99.766403],[19.82202,99.763603],[19.80855,99.75489],[19.800699,99.753487],[19.78414,99.743393],[19.76815,99.736092],[19.7572,99.733566],[19.746201,99.726852],[19.74276,99.724037],[19.73921,99.722839],[19.72596,99.716492],[19.72014,99.716148],[19.716591,99.71666],[19.71174,99.720444],[19.708179,99.720268],[19.70447,99.719063],[19.688629,99.723358],[19.68475,99.727127],[19.679899,99.727821],[19.67149,99.731598],[19.6681,99.734169],[19.664539,99.734337],[19.65662,99.735718],[19.653709,99.736923],[19.64983,99.737259],[19.644501,99.738632],[19.637711,99.743103],[19.620081,99.743271],[19.61006,99.747726],[19.600519,99.749619],[19.595181,99.748589],[19.591459,99.746529],[19.582239,99.744987],[19.57626,99.746529],[19.57011,99.751678],[19.56736,99.752197],[19.550541,99.747391],[19.541479,99.742073],[19.51705,99.745667],[19.504271,99.746872],[19.50135,99.746696],[19.49699,99.748589],[19.48016,99.751678],[19.472389,99.753738],[19.469641,99.754082],[19.467211,99.755112],[19.462839,99.75563],[19.45928,99.755798],[19.453939,99.757172],[19.44973,99.758034],[19.44228,99.758202],[19.432249,99.761978],[19.42415,99.766098],[19.410549,99.770393],[19.37849,99.78756],[19.357759,99.799057],[19.339621,99.811943],[19.3218,99.838371],[19.310631,99.845917],[19.30415,99.852272],[19.29945,99.853127],[19.290051,99.855881],[19.275141,99.856392],[19.268181,99.857773],[19.255369,99.857422],[19.24938,99.858627],[19.240629,99.860863],[19.23674,99.862923],[19.229931,99.863426],[19.227011,99.863953],[19.20772,99.871498],[19.2001,99.872528],[19.19735,99.874763],[19.188431,99.889008],[19.178049,99.901016],[19.17128,99.906563],[19.16725,99.909927],[19.161579,99.914177],[19.158171,99.914436],[19.152809,99.912689],[19.141399,99.910896],[19.12985,99.910072],[19.115681,99.90567],[19.106331,99.908417],[19.095181,99.912193],[19.09145,99.913727],[19.082689,99.92231],[19.075069,99.927979],[19.069059,99.92746],[19.05657,99.932098],[19.05316,99.933472],[19.050079,99.935867],[19.04554,99.935532],[19.043261,99.934669],[19.04018,99.931236],[19.038719,99.931068],[19.03775,99.930382],[19.02947,99.927116],[19.02639,99.923523],[19.019899,99.920433],[19.019251,99.919052],[19.01503,99.911163],[19.00983,99.906013],[19.00659,99.902573],[19.005449,99.899307],[19.00334,99.898109],[19.00042,99.899483],[18.99782,99.901367],[18.994419,99.903259],[18.991011,99.904289],[18.988569,99.906174],[18.985979,99.906349],[18.98127,99.907204],[18.977051,99.91098],[18.976231,99.912872],[18.97364,99.914413],[18.9699,99.915283],[18.96796,99.918709],[18.96455,99.920937],[18.95822,99.920593],[18.95627,99.922829],[18.95075,99.923523],[18.93889,99.929008],[18.934999,99.931923],[18.93354,99.932793],[18.929319,99.931763],[18.924931,99.933983],[18.922171,99.935013],[18.91876,99.937424],[18.905769,99.943771],[18.902519,99.944633],[18.89814,99.946342],[18.893259,99.946693],[18.887251,99.944633],[18.88319,99.945312],[18.8741,99.947548],[18.867599,99.948402],[18.858829,99.948921],[18.851681,99.948059],[18.846161,99.947891],[18.834141,99.949432],[18.82406,99.949089],[18.821791,99.949608],[18.807159,99.958527],[18.804079,99.960587],[18.78701,99.964371],[18.78587,99.965233],[18.781969,99.969177],[18.776609,99.970032],[18.76491,99.97364],[18.76214,99.973457],[18.757429,99.970032],[18.753201,99.970032],[18.7428,99.975014],[18.74004,99.975357],[18.73597,99.973984],[18.733049,99.971237],[18.73012,99.971237],[18.72703,99.968491],[18.72541,99.968491],[18.72323,99.967339],[18.72118,99.966263],[18.719721,99.966263],[18.718901,99.964706],[18.71516,99.960938],[18.71386,99.958527],[18.71175,99.957161],[18.7085,99.958023],[18.706869,99.957497],[18.7059,99.956131],[18.70134,99.954758],[18.699551,99.952698],[18.69809,99.948753],[18.696951,99.947548],[18.68996,99.944283],[18.687691,99.944801],[18.68573,99.943604],[18.68037,99.934502],[18.674021,99.928673],[18.6724,99.927803],[18.66736,99.92643],[18.661659,99.924202],[18.65711,99.921967],[18.655649,99.92025],[18.65044,99.920433],[18.64784,99.920593],[18.645069,99.918709],[18.641821,99.91819],[18.635799,99.914589],[18.63434,99.911667],[18.626699,99.909103],[18.62442,99.90892],[18.618561,99.907722],[18.61824,99.906349],[18.614981,99.908234],[18.61091,99.907043],[18.6075,99.9048],[18.6049,99.904289],[18.60343,99.903603],[18.601971,99.902397],[18.598881,99.900681],[18.596109,99.898453],[18.592529,99.898621],[18.589769,99.896744],[18.588461,99.89502],[18.58684,99.89399],[18.58391,99.893471],[18.582609,99.89296],[18.58082,99.89193],[18.57691,99.886597],[18.575769,99.886093],[18.575121,99.886597],[18.57398,99.88575],[18.57333,99.88472],[18.572029,99.883858],[18.571541,99.882141],[18.56975,99.881287],[18.568291,99.879051],[18.5665,99.878883],[18.56373,99.875618],[18.56324,99.872871],[18.56275,99.87133],[18.56292,99.86927],[18.560801,99.866348],[18.55966,99.865997],[18.55966,99.864288],[18.558359,99.861198],[18.55673,99.859657],[18.555269,99.854507],[18.55348,99.853821],[18.5525,99.852448],[18.550871,99.851418],[18.54925,99.849182],[18.547291,99.848328],[18.543711,99.840767],[18.540131,99.839912],[18.53964,99.838707],[18.537849,99.838203],[18.53558,99.835617],[18.530531,99.832191],[18.529881,99.830299],[18.52581,99.828934],[18.51783,99.82412],[18.513769,99.820862],[18.5149,99.81897],[18.499439,99.812279],[18.47893,99.807472],[18.47648,99.806099],[18.47323,99.805237],[18.47225,99.80558],[18.466881,99.804207],[18.466709,99.802673],[18.463301,99.804382],[18.462971,99.803703],[18.459061,99.801292],[18.455641,99.797684],[18.45402,99.797173],[18.45385,99.795113],[18.451571,99.793404],[18.452061,99.790131],[18.45125,99.788589],[18.448311,99.786697],[18.448311,99.783607],[18.44245,99.776047],[18.44066,99.775017],[18.43952,99.772797],[18.43692,99.772453],[18.434799,99.769867],[18.42487,99.754601],[18.42519,99.752022],[18.42161,99.749107],[18.42128,99.747902],[18.4221,99.743103],[18.42112,99.741547],[18.420309,99.739487],[18.41995,99.737396],[18.42004,99.735573],[18.42008,99.733253],[18.41995,99.732552],[18.41889,99.730331],[18.41873,99.729698],[18.418711,99.72905],[18.418791,99.728363],[18.4195,99.727074],[18.419979,99.726349],[18.420231,99.726128],[18.421,99.7258],[18.424561,99.724602],[18.425671,99.724037],[18.426571,99.723328],[18.427401,99.722572],[18.428101,99.721451],[18.42823,99.720734],[18.42827,99.719788],[18.42893,99.718018],[18.429291,99.716713],[18.42931,99.715942],[18.429251,99.714172],[18.42909,99.71257],[18.42915,99.711746],[18.429159,99.710548],[18.42911,99.709961],[18.42881,99.709312],[18.42832,99.708794],[18.42795,99.708214],[18.427919,99.707649],[18.42795,99.706039],[18.42767,99.704086],[18.427589,99.702888],[18.427589,99.70208],[18.426929,99.700233],[18.426741,99.699043],[18.426781,99.698059],[18.42658,99.697319],[18.42609,99.696053],[18.42481,99.694153],[18.424101,99.693573],[18.423691,99.692886],[18.42347,99.69194],[18.423491,99.689323],[18.423241,99.688538],[18.423031,99.68734],[18.42272,99.686203],[18.422131,99.684937],[18.422041,99.684174],[18.42222,99.683647],[18.422501,99.683128],[18.422661,99.682358],[18.42264,99.680542],[18.422541,99.679131],[18.42197,99.675194],[18.42194,99.67244],[18.42174,99.671631],[18.421301,99.670486],[18.420971,99.669319],[18.42094,99.665627],[18.42099,99.663811],[18.42087,99.663017],[18.42053,99.66185],[18.417959,99.653954],[18.4172,99.651909],[18.41601,99.649818],[18.412809,99.644562],[18.406851,99.639587],[18.40027,99.634438],[18.392811,99.624962],[18.385281,99.615044],[18.37586,99.599113],[18.36557,99.581909],[18.355709,99.565353],[18.34586,99.548767],[18.33902,99.541557],[18.31636,99.528687],[18.310011,99.528687],[18.305771,99.527657],[18.285431,99.512939],[18.2847,99.512192],[18.284321,99.511879],[18.28384,99.511429],[18.283501,99.511009],[18.28231,99.50872],[18.282021,99.506973],[18.281969,99.506752],[18.281931,99.506447],[18.28183,99.504372],[18.281799,99.503326],[18.2817,99.501801],[18.28154,99.498703],[18.281389,99.496017],[18.28134,99.495178],[18.281179,99.492928],[18.28109,99.491997],[18.28097,99.491493],[18.280741,99.490639],[18.280491,99.490067],[18.280251,99.489571],[18.276279,99.484016],[18.275089,99.482361],[18.271931,99.477943],[18.26992,99.475143],[18.265791,99.469559],[18.264151,99.467949],[18.263901,99.467728],[18.259399,99.462921],[18.254829,99.457451],[18.25322,99.45546],[18.25285,99.455002],[18.252251,99.454407],[18.251181,99.453377],[18.248911,99.451523],[18.24684,99.449829],[18.246321,99.449249],[18.246229,99.449158],[18.24357,99.446136],[18.240339,99.442268],[18.240231,99.442131],[18.23794,99.439133],[18.237009,99.43779],[18.234949,99.434761],[18.234051,99.433434],[18.233271,99.432281],[18.232941,99.431862],[18.23254,99.431396],[18.231871,99.43087],[18.23115,99.430443],[18.23048,99.430099],[18.223049,99.426353],[18.219999,99.42485],[18.214729,99.422234],[18.2141,99.421783],[18.213449,99.421173],[18.21044,99.417763],[18.20784,99.414848],[18.206091,99.41288],[18.20507,99.411789],[18.2041,99.410851],[18.203369,99.410233],[18.202881,99.409859],[18.202271,99.409431],[18.20149,99.408997],[18.20116,99.408768],[18.20055,99.408447],[18.199909,99.408142],[18.198891,99.40773],[18.19791,99.407379],[18.19705,99.407158],[18.19627,99.40699],[18.195271,99.406807],[18.194441,99.406723],[18.193081,99.406639],[18.19174,99.406708],[18.190941,99.406807],[18.190041,99.406929],[18.18878,99.407204],[18.186609,99.407761],[18.184031,99.408447],[18.182199,99.408928],[18.18095,99.409187],[18.180309,99.409233],[18.17975,99.409233],[18.179211,99.409149],[18.17749,99.408699],[18.17017,99.406662],[18.166981,99.405777],[18.163481,99.404831],[18.15963,99.403793],[18.158501,99.403519],[18.157089,99.403229],[18.15344,99.402649],[18.150881,99.402184],[18.15004,99.402046],[18.149481,99.401962],[18.149,99.401863],[18.148581,99.401703],[18.147989,99.401352],[18.14753,99.400978],[18.14703,99.40033],[18.1467,99.399567],[18.14559,99.395081],[18.1453,99.394173],[18.144859,99.393402],[18.144341,99.3927],[18.14374,99.392097],[18.142941,99.391563],[18.14249,99.391312],[18.14209,99.391144],[18.141621,99.390961],[18.14101,99.390823],[18.14044,99.390778],[18.139891,99.390747],[18.13619,99.390709],[18.13114,99.390762],[18.128851,99.391121],[18.124069,99.392548],[18.10453,99.398163],[18.10178,99.398788],[18.099609,99.398727],[18.096781,99.398109],[18.094761,99.397583],[18.092661,99.397118],[18.091841,99.396919],[18.0884,99.396072],[18.085541,99.395348],[18.083891,99.394974],[18.075769,99.392998],[18.070539,99.391769],[18.066629,99.390846],[18.062481,99.390266],[18.05871,99.389839],[18.05596,99.389267],[18.054411,99.388397],[18.051821,99.386383],[18.050211,99.38546],[18.045561,99.383141],[18.043961,99.381851],[18.04265,99.380638],[18.041,99.379402],[18.036779,99.376457],[18.036421,99.376259],[18.034201,99.375107],[18.033239,99.374786],[18.032431,99.374603],[18.031601,99.374496],[18.030519,99.37442],[18.024441,99.373947],[18.0229,99.373329],[18.02154,99.37207],[18.012831,99.358124],[18.01133,99.357002],[18.009991,99.356583],[17.99893,99.355247],[17.98905,99.357224],[17.982321,99.356018],[17.979931,99.355743],[17.97489,99.356071],[17.973339,99.355614],[17.970539,99.353241],[17.969101,99.352692],[17.96756,99.352707],[17.962151,99.354393],[17.961781,99.354492],[17.96125,99.354637],[17.961029,99.35466],[17.96056,99.35466],[17.95981,99.354637],[17.959379,99.354561],[17.95863,99.354279],[17.95808,99.353981],[17.95723,99.353378],[17.95643,99.352737],[17.95587,99.352371],[17.955059,99.351822],[17.95433,99.351357],[17.95396,99.351189],[17.95359,99.351044],[17.953091,99.350883],[17.95245,99.350838],[17.951981,99.350853],[17.951429,99.350929],[17.95067,99.351082],[17.95013,99.351196],[17.94813,99.351593],[17.946581,99.351837],[17.946051,99.351921],[17.945681,99.351936],[17.945511,99.351929],[17.945129,99.351883],[17.944559,99.351707],[17.94421,99.351593],[17.943859,99.351433],[17.94348,99.351257],[17.94228,99.350517],[17.941111,99.349838],[17.93996,99.349243],[17.93936,99.348953],[17.93882,99.348679],[17.93819,99.348473],[17.9373,99.348289],[17.93652,99.348137],[17.934759,99.347778],[17.93421,99.347687],[17.932699,99.347427],[17.93189,99.347298],[17.92786,99.346573],[17.92705,99.346413],[17.92444,99.34594],[17.92285,99.345657],[17.92038,99.345207],[17.9198,99.345093],[17.91939,99.345001],[17.91836,99.344711],[17.91785,99.344589],[17.917351,99.344429],[17.917009,99.344269],[17.9163,99.343849],[17.915291,99.343246],[17.915051,99.343117],[17.91415,99.342613],[17.913731,99.342377],[17.913441,99.342216],[17.91333,99.342163],[17.913191,99.342133],[17.9125,99.342003],[17.91172,99.341957],[17.91118,99.341927],[17.910681,99.341873],[17.90926,99.341827],[17.908791,99.341797],[17.90661,99.341667],[17.904579,99.341522],[17.9039,99.341476],[17.903549,99.341469],[17.902691,99.341431],[17.902109,99.3414],[17.90139,99.341362],[17.900949,99.341331],[17.899851,99.341217],[17.899229,99.341133],[17.89868,99.341026],[17.898109,99.340927],[17.89765,99.340851],[17.89702,99.340736],[17.89642,99.340637],[17.895901,99.340553],[17.89366,99.340157],[17.89069,99.33963],[17.88946,99.339417],[17.888769,99.33931],[17.88637,99.338882],[17.88438,99.338531],[17.882891,99.33828],[17.881689,99.338081],[17.88026,99.337822],[17.87919,99.337646],[17.87808,99.337471],[17.87718,99.337318],[17.8766,99.337257],[17.87611,99.337181],[17.87467,99.337128],[17.874229,99.337143],[17.87361,99.337143],[17.871771,99.337196],[17.87114,99.337242],[17.870489,99.337273],[17.870131,99.337273],[17.86964,99.337196],[17.869011,99.337082],[17.8687,99.337013],[17.868401,99.336838],[17.86796,99.336563],[17.86767,99.336349],[17.86746,99.336197],[17.86726,99.336014],[17.86688,99.33551],[17.86599,99.334396],[17.865061,99.333237],[17.864401,99.332397],[17.863991,99.331802],[17.86343,99.331001],[17.86311,99.33049],[17.862749,99.32975],[17.86245,99.328903],[17.862289,99.328217],[17.86224,99.327454],[17.862181,99.326714],[17.862129,99.32605],[17.86191,99.322456],[17.861759,99.319107],[17.861549,99.315567],[17.86153,99.315292],[17.861521,99.31517],[17.861481,99.315033],[17.86117,99.313766],[17.8608,99.312477],[17.860331,99.310944],[17.86005,99.310051],[17.859909,99.309601],[17.859859,99.309486],[17.85973,99.309273],[17.85928,99.308662],[17.85885,99.308243],[17.858391,99.307747],[17.85741,99.306763],[17.85648,99.305923],[17.855591,99.305107],[17.85523,99.304764],[17.854839,99.304314],[17.854601,99.304031],[17.85445,99.303741],[17.85433,99.303513],[17.85412,99.303017],[17.85392,99.302223],[17.85384,99.30159],[17.85371,99.300491],[17.8533,99.296638],[17.853251,99.296318],[17.85321,99.296013],[17.853029,99.295303],[17.852871,99.2948],[17.852711,99.29451],[17.85252,99.294228],[17.852261,99.293854],[17.852079,99.293587],[17.85186,99.293404],[17.851761,99.293297],[17.85161,99.293198],[17.851259,99.292953],[17.850969,99.29277],[17.850731,99.292641],[17.85043,99.292542],[17.85,99.292397],[17.8496,99.29232],[17.84923,99.29229],[17.84869,99.29232],[17.84779,99.292458],[17.847481,99.292511],[17.844879,99.293228],[17.843941,99.293472],[17.843321,99.293587],[17.842369,99.293701],[17.841961,99.293739],[17.84166,99.293732],[17.84104,99.293709],[17.840599,99.293633],[17.840219,99.293533],[17.839899,99.293449],[17.83931,99.293243],[17.83873,99.292923],[17.83827,99.29261],[17.83799,99.292389],[17.836639,99.2911],[17.836531,99.291023],[17.836411,99.290932],[17.836281,99.290848],[17.835911,99.290672],[17.8354,99.290413],[17.83526,99.290337],[17.83514,99.290298],[17.834579,99.290268],[17.83226,99.290161],[17.831779,99.290154],[17.831591,99.290154],[17.831499,99.290138],[17.830999,99.289932],[17.83036,99.289597],[17.83024,99.28952],[17.83003,99.289322],[17.82963,99.288872],[17.82939,99.288643],[17.829281,99.28849],[17.82917,99.288239],[17.828871,99.287407],[17.82847,99.286018],[17.82832,99.285347],[17.828159,99.284813],[17.82811,99.284683],[17.82798,99.284462],[17.82766,99.284058],[17.82745,99.283836],[17.82724,99.2836],[17.827101,99.28347],[17.826941,99.283363],[17.826679,99.283234],[17.826389,99.283081],[17.82618,99.282997],[17.82585,99.282921],[17.825569,99.282867],[17.825081,99.282806],[17.824591,99.282799],[17.821569,99.28289],[17.82082,99.282898],[17.820551,99.282898],[17.81995,99.28286],[17.8197,99.282852],[17.819,99.282806],[17.818501,99.282753],[17.81819,99.282692],[17.8179,99.282547],[17.817579,99.282333],[17.817209,99.282066],[17.816971,99.281822],[17.816771,99.281609],[17.816601,99.281326],[17.81636,99.280884],[17.816179,99.280487],[17.816031,99.280083],[17.81386,99.273483],[17.81365,99.272911],[17.81352,99.272583],[17.813181,99.271957],[17.81295,99.271584],[17.8127,99.27124],[17.81225,99.270798],[17.81126,99.269852],[17.810381,99.269119],[17.80974,99.26857],[17.80872,99.267761],[17.80821,99.267357],[17.807859,99.267128],[17.80744,99.266907],[17.806999,99.266693],[17.80674,99.266617],[17.80644,99.266571],[17.80608,99.266533],[17.805759,99.266533],[17.805401,99.266533],[17.80504,99.266617],[17.80337,99.266998],[17.802469,99.267174],[17.802071,99.267227],[17.801889,99.267227],[17.801689,99.267227],[17.80142,99.267174],[17.8009,99.267036],[17.800541,99.266937],[17.80023,99.266861],[17.800051,99.266777],[17.798241,99.266006],[17.79715,99.265556],[17.79257,99.263641],[17.791861,99.263344],[17.78828,99.26181],[17.78756,99.261513],[17.78669,99.261124],[17.7859,99.260757],[17.78512,99.260429],[17.78488,99.260292],[17.784559,99.260033],[17.7843,99.259827],[17.783911,99.259506],[17.783489,99.259117],[17.78289,99.258347],[17.781799,99.257004],[17.78129,99.256287],[17.77948,99.254051],[17.7777,99.251877],[17.77697,99.251038],[17.77673,99.250763],[17.776421,99.250481],[17.77618,99.250313],[17.7756,99.250031],[17.775,99.249786],[17.773529,99.249382],[17.773161,99.249283],[17.770929,99.248657],[17.769039,99.248009],[17.768499,99.247833],[17.768101,99.247627],[17.7679,99.247437],[17.76725,99.246834],[17.76651,99.246017],[17.76532,99.244629],[17.76475,99.243988],[17.764339,99.243607],[17.763969,99.243401],[17.763491,99.243141],[17.76297,99.242897],[17.76252,99.242783],[17.761299,99.24247],[17.76108,99.242416],[17.76034,99.242218],[17.759871,99.242073],[17.759029,99.241737],[17.75853,99.241524],[17.758101,99.241241],[17.757481,99.240791],[17.756941,99.240318],[17.75658,99.239883],[17.754259,99.236938],[17.75318,99.235573],[17.752991,99.235367],[17.75267,99.235062],[17.752399,99.234879],[17.75209,99.234688],[17.751051,99.234238],[17.750351,99.234001],[17.7498,99.233772],[17.748859,99.233276],[17.748581,99.233093],[17.747829,99.232452],[17.746889,99.231583],[17.746691,99.231377],[17.74646,99.231194],[17.74609,99.230972],[17.74564,99.230827],[17.745159,99.230682],[17.744881,99.230637],[17.744419,99.230629],[17.743931,99.23069],[17.74349,99.230782],[17.743191,99.230873],[17.74276,99.231102],[17.74197,99.231628],[17.74017,99.232971],[17.73991,99.233147],[17.739531,99.233292],[17.73864,99.233566],[17.73842,99.233589],[17.73773,99.233589],[17.73707,99.233582],[17.736509,99.233513],[17.73584,99.233383],[17.73542,99.233292],[17.734819,99.233177],[17.73427,99.23304],[17.733521,99.232773],[17.732241,99.232307],[17.730801,99.231644],[17.730061,99.231293],[17.728479,99.230621],[17.727859,99.230362],[17.72703,99.230057],[17.726549,99.229881],[17.726231,99.229767],[17.725981,99.229721],[17.724819,99.229462],[17.72401,99.229309],[17.723749,99.229263],[17.723499,99.229233],[17.72278,99.229134],[17.72213,99.22905],[17.72184,99.229019],[17.72105,99.228928],[17.720671,99.228889],[17.720409,99.228859],[17.720261,99.228859],[17.720039,99.228882],[17.71792,99.229012],[17.71751,99.229027],[17.7131,99.229362],[17.71036,99.229683],[17.709999,99.229729],[17.709591,99.229782],[17.709379,99.229797],[17.70927,99.22982],[17.709061,99.229874],[17.708929,99.229912],[17.70859,99.230003],[17.703871,99.231422],[17.6992,99.232727],[17.69821,99.233017],[17.69763,99.233177],[17.697451,99.233223],[17.69726,99.233238],[17.696751,99.233276],[17.696369,99.233292],[17.69614,99.233307],[17.69598,99.233299],[17.69591,99.233292],[17.69561,99.233223],[17.69491,99.23304],[17.694389,99.23291],[17.694099,99.232841],[17.69388,99.232811],[17.69368,99.232803],[17.693279,99.23275],[17.692961,99.232727],[17.692671,99.232697],[17.69244,99.232697],[17.692301,99.232697],[17.692169,99.232727],[17.691891,99.232803],[17.69169,99.232857],[17.691191,99.233093],[17.691019,99.233177],[17.69067,99.233437],[17.690411,99.233658],[17.690121,99.233994],[17.689871,99.234283],[17.689671,99.234543],[17.689461,99.234879],[17.688641,99.236259],[17.68808,99.23719],[17.68734,99.238152],[17.68705,99.238503],[17.686781,99.238724],[17.6863,99.239014],[17.68573,99.239311],[17.68515,99.239563],[17.68358,99.24015],[17.679119,99.241768],[17.67421,99.243568],[17.670959,99.244667],[17.669821,99.24501],[17.66951,99.245102],[17.669319,99.245163],[17.669201,99.245171],[17.669081,99.245171],[17.66873,99.245163],[17.667709,99.245064],[17.66604,99.244743],[17.66552,99.244629],[17.66523,99.244583],[17.66506,99.24456],[17.664921,99.24456],[17.66469,99.244583],[17.6644,99.244614],[17.664009,99.244637],[17.663759,99.24469],[17.66358,99.244743],[17.663389,99.244812],[17.663219,99.244904],[17.662809,99.245117],[17.66263,99.245247],[17.662331,99.245453],[17.66197,99.245811],[17.660839,99.247223],[17.660061,99.248207],[17.659401,99.2491],[17.65922,99.249313],[17.659121,99.249413],[17.65889,99.249588],[17.658171,99.25016],[17.657921,99.250343],[17.657669,99.250473],[17.65728,99.250641],[17.656561,99.250893],[17.656309,99.250961],[17.655861,99.25103],[17.655359,99.251091],[17.654989,99.251106],[17.65469,99.251106],[17.654181,99.251038],[17.653561,99.25087],[17.653231,99.250763],[17.652941,99.250641],[17.652571,99.250427],[17.652439,99.250351],[17.652189,99.250183],[17.651711,99.249847],[17.65132,99.249489],[17.650909,99.249039],[17.650351,99.248322],[17.649651,99.247177],[17.64868,99.245667],[17.64819,99.244987],[17.647699,99.244331],[17.64736,99.243896],[17.647091,99.243652],[17.646799,99.243439],[17.646021,99.24292],[17.644899,99.242287],[17.643909,99.241737],[17.64311,99.24131],[17.641239,99.240349],[17.640791,99.240097],[17.640671,99.240044],[17.64039,99.239937],[17.640221,99.239883],[17.63924,99.239662],[17.639059,99.239616],[17.63826,99.239517],[17.63669,99.239388],[17.635361,99.23925],[17.63233,99.238876],[17.63176,99.238823],[17.631161,99.238739],[17.630199,99.238609],[17.63006,99.238586],[17.629971,99.238579],[17.62962,99.238541],[17.629141,99.238472],[17.62866,99.238403],[17.628309,99.23835],[17.627979,99.238281],[17.62742,99.238197],[17.62673,99.238037],[17.62583,99.237892],[17.625059,99.237633],[17.622801,99.236839],[17.621441,99.236008],[17.61692,99.232162],[17.61537,99.230904],[17.61335,99.229797],[17.60886,99.227928],[17.602249,99.22522],[17.597521,99.223282],[17.59412,99.222054],[17.587271,99.220108],[17.58593,99.219467],[17.584789,99.218277],[17.5783,99.208618],[17.57519,99.203941],[17.574329,99.203087],[17.573111,99.202309],[17.57239,99.202087],[17.57156,99.201981],[17.57074,99.202003],[17.564529,99.203102],[17.56094,99.203789],[17.559891,99.203529],[17.559389,99.203369],[17.55278,99.200447],[17.545259,99.197067],[17.537621,99.193703],[17.52972,99.190163],[17.522421,99.186867],[17.517151,99.184593],[17.511311,99.183838],[17.50985,99.183296],[17.508881,99.182648],[17.503361,99.178322],[17.499451,99.175423],[17.499241,99.175041],[17.48904,99.167084],[17.47415,99.162407],[17.469481,99.161247],[17.423571,99.157494],[17.41935,99.157249],[17.41753,99.156578],[17.411221,99.151299],[17.40942,99.150032],[17.40662,99.149208],[17.39879,99.149406],[17.39036,99.148537],[17.38191,99.147797],[17.377081,99.149017],[17.37434,99.149094],[17.36429,99.146599],[17.3626,99.146698],[17.354561,99.148918],[17.35183,99.149513],[17.34754,99.14946],[17.34433,99.149437],[17.34161,99.149643],[17.33868,99.151382],[17.335911,99.153374],[17.33367,99.154083],[17.33156,99.153992],[17.30291,99.147034],[17.295,99.142593],[17.28458,99.141388],[17.28159,99.140633],[17.25828,99.132843],[17.24894,99.128304],[17.23995,99.123833],[17.238461,99.122993],[17.237061,99.122704],[17.207069,99.123238],[17.20488,99.123596],[17.20418,99.123947],[17.2031,99.12455],[17.19191,99.130913],[17.179131,99.138077],[17.17695,99.138298],[17.17457,99.137848],[17.16736,99.135223],[17.15797,99.131851],[17.15015,99.129463],[17.147699,99.128029],[17.13851,99.112953],[17.13471,99.106644],[17.132629,99.104424],[17.126169,99.098793],[17.115339,99.091873],[17.113079,99.08847],[17.111059,99.084801],[17.109261,99.080406],[17.10791,99.077362],[17.105841,99.075607],[17.103371,99.074699],[17.089741,99.072487],[17.074369,99.06559],[17.07151,99.06543],[17.069031,99.066544],[17.06661,99.06781],[17.05814,99.072273],[17.047461,99.078308],[17.03545,99.087624],[17.023211,99.097221],[17.00762,99.108757],[16.997351,99.112717],[16.988581,99.117897],[16.980551,99.122093],[16.979561,99.122704],[16.978951,99.12368],[16.976191,99.128593],[16.97452,99.130058],[16.97257,99.130501],[16.968321,99.13092],[16.96356,99.131462],[16.96092,99.13134],[16.920919,99.115631],[16.919189,99.11586],[16.91795,99.11602],[16.91305,99.118767],[16.90901,99.121246],[16.9007,99.126984],[16.89715,99.128098],[16.893391,99.129143],[16.89175,99.129051],[16.885201,99.127052],[16.88372,99.126694],[16.881399,99.127083],[16.876499,99.130058],[16.87117,99.133377],[16.863501,99.13826],[16.85927,99.12957],[16.856239,99.123466],[16.855671,99.12233],[16.85342,99.117859],[16.85202,99.115067],[16.85084,99.113182],[16.84898,99.111923],[16.84684,99.111504],[16.84412,99.112358],[16.8416,99.11367],[16.84152,99.113724],[16.837959,99.115807],[16.835329,99.117531],[16.821699,99.130074],[16.801649,99.148598],[16.799669,99.150833],[16.798031,99.15358],[16.795401,99.157867],[16.79244,99.162163],[16.78866,99.166969],[16.76845,99.18911],[16.76483,99.192543],[16.7096,99.240257],[16.68836,99.258202],[16.679461,99.264771],[16.67762,99.266113],[16.677481,99.266212],[16.6754,99.267906],[16.67342,99.269623],[16.67309,99.270317],[16.67288,99.271057],[16.672859,99.271423],[16.67281,99.272797],[16.672779,99.273537],[16.672729,99.27478],[16.672661,99.275673],[16.672489,99.276649],[16.672251,99.277786],[16.67214,99.278313],[16.67173,99.280197],[16.671499,99.281181],[16.6712,99.283028],[16.671181,99.283287],[16.671249,99.285454],[16.671789,99.288597],[16.671829,99.288857],[16.672001,99.289909],[16.67218,99.290947],[16.672421,99.292236],[16.6726,99.293266],[16.67338,99.298218],[16.673161,99.300034],[16.672979,99.300537],[16.672041,99.302116],[16.66967,99.304527],[16.666189,99.308037],[16.665819,99.308411],[16.663031,99.31118],[16.66287,99.311348],[16.66259,99.31163],[16.6623,99.311943],[16.66151,99.312729],[16.6612,99.313026],[16.66095,99.313278],[16.66025,99.314003],[16.659611,99.314667],[16.659439,99.314842],[16.658159,99.316139],[16.65443,99.319923],[16.65276,99.321609],[16.652571,99.3218],[16.649229,99.325203],[16.647921,99.326508],[16.646601,99.32785],[16.64641,99.328041],[16.64311,99.331429],[16.64192,99.332878],[16.64097,99.334152],[16.64082,99.334373],[16.637951,99.338142],[16.63311,99.344543],[16.630091,99.348587],[16.629789,99.348991],[16.629169,99.349792],[16.628531,99.350601],[16.62711,99.352493],[16.62414,99.356438],[16.62381,99.35685],[16.62253,99.358543],[16.62108,99.360443],[16.618429,99.363991],[16.61496,99.368683],[16.61392,99.370857],[16.613609,99.37159],[16.61319,99.372566],[16.613079,99.37281],[16.61297,99.373062],[16.612749,99.373558],[16.611071,99.377563],[16.610439,99.379044],[16.60939,99.381523],[16.60792,99.384987],[16.60771,99.385483],[16.607599,99.385727],[16.607189,99.386703],[16.60689,99.387444],[16.606569,99.388168],[16.606159,99.389153],[16.605419,99.390877],[16.605009,99.391869],[16.603491,99.395462],[16.603121,99.396317],[16.60302,99.396568],[16.602591,99.397552],[16.600929,99.401466],[16.60062,99.402206],[16.600519,99.402458],[16.59807,99.408287],[16.596411,99.412201],[16.596001,99.41317],[16.595791,99.413658],[16.595591,99.414146],[16.594521,99.416603],[16.594311,99.417084],[16.594101,99.41758],[16.594,99.417831],[16.59269,99.420998],[16.591021,99.424927],[16.588301,99.431328],[16.586519,99.435532],[16.58543,99.437042],[16.584,99.438202],[16.58209,99.439056],[16.580641,99.439629],[16.580151,99.439812],[16.578939,99.440331],[16.57461,99.442101],[16.57412,99.442299],[16.57338,99.442596],[16.57313,99.442703],[16.571659,99.443283],[16.57023,99.443893],[16.567341,99.44503],[16.566139,99.445511],[16.563231,99.446663],[16.56251,99.446953],[16.55891,99.448486],[16.55868,99.448608],[16.558229,99.448868],[16.556589,99.45018],[16.554319,99.4524],[16.55036,99.456284],[16.548071,99.458511],[16.54731,99.459251],[16.544491,99.461937],[16.544331,99.462097],[16.543751,99.462677],[16.543159,99.463272],[16.54306,99.463379],[16.542561,99.463837],[16.5424,99.463989],[16.542191,99.464241],[16.542009,99.464417],[16.541679,99.464737],[16.541269,99.465134],[16.540661,99.465729],[16.540331,99.466057],[16.53981,99.466583],[16.539049,99.4673],[16.538851,99.467484],[16.53808,99.468224],[16.53751,99.468781],[16.536751,99.469521],[16.53598,99.470268],[16.53504,99.471191],[16.534849,99.471367],[16.53429,99.471931],[16.53392,99.472313],[16.533001,99.473228],[16.53264,99.473587],[16.530359,99.475601],[16.528509,99.47641],[16.52446,99.477753],[16.52404,99.47789],[16.52319,99.478142],[16.52297,99.47821],[16.522091,99.478523],[16.52186,99.478592],[16.521629,99.478683],[16.521151,99.478859],[16.51795,99.479942],[16.516251,99.480507],[16.51479,99.481003],[16.51083,99.482323],[16.50983,99.482658],[16.509581,99.482742],[16.508089,99.483253],[16.507589,99.483414],[16.507099,99.483589],[16.506849,99.483673],[16.50609,99.483887],[16.504271,99.484047],[16.502211,99.483627],[16.501431,99.483429],[16.50091,99.483299],[16.498619,99.482689],[16.497601,99.482422],[16.497089,99.482277],[16.49658,99.48214],[16.49402,99.481621],[16.492479,99.481903],[16.491171,99.482773],[16.48962,99.484154],[16.48595,99.487839],[16.485571,99.488213],[16.48538,99.488403],[16.483351,99.490791],[16.482929,99.491463],[16.48209,99.49276],[16.48167,99.493408],[16.481529,99.493629],[16.481239,99.494072],[16.481091,99.494301],[16.480101,99.495537],[16.479,99.496292],[16.47747,99.496696],[16.47649,99.496689],[16.476089,99.496658],[16.47576,99.496643],[16.475479,99.496613],[16.47537,99.496597],[16.47506,99.496567],[16.474609,99.496552],[16.472771,99.496483],[16.471889,99.496407],[16.471439,99.496384],[16.470751,99.496323],[16.470169,99.496246],[16.469761,99.496193],[16.468161,99.496147],[16.467911,99.496132],[16.46665,99.496063],[16.465639,99.495987],[16.464371,99.495918],[16.46105,99.495689],[16.460541,99.495644],[16.4568,99.495323],[16.455311,99.495621],[16.453951,99.496407],[16.45089,99.498993],[16.4485,99.500977],[16.447519,99.501823],[16.44635,99.5028],[16.445999,99.503113],[16.44545,99.503563],[16.44314,99.505539],[16.439569,99.508553],[16.438971,99.509071],[16.436991,99.51075],[16.43314,99.513939],[16.428801,99.517578],[16.424419,99.521103],[16.422661,99.521637],[16.421869,99.521713],[16.42108,99.521698],[16.4182,99.521629],[16.415039,99.521561],[16.414009,99.521538],[16.412491,99.5215],[16.411449,99.521492],[16.409679,99.521538],[16.409161,99.521561],[16.40608,99.521568],[16.405041,99.521561],[16.400579,99.521568],[16.40032,99.521568],[16.397169,99.521553],[16.395321,99.521553],[16.393999,99.521561],[16.39348,99.521561],[16.393221,99.521561],[16.391121,99.521568],[16.390341,99.521584],[16.38854,99.521942],[16.3883,99.522041],[16.38677,99.523033],[16.38658,99.523209],[16.385611,99.524483],[16.38533,99.52494],[16.38464,99.5261],[16.384501,99.526337],[16.38258,99.529541],[16.382441,99.529778],[16.382299,99.529999],[16.38088,99.53231],[16.380739,99.532539],[16.380051,99.53373],[16.37991,99.533958],[16.37948,99.53466],[16.377069,99.538559],[16.374229,99.543198],[16.37394,99.543663],[16.37365,99.544144],[16.370649,99.549042],[16.370359,99.549507],[16.36949,99.550911],[16.366779,99.555702],[16.365179,99.558617],[16.364639,99.559593],[16.36409,99.560547],[16.363819,99.561043],[16.363279,99.562012],[16.36249,99.563469],[16.360201,99.567574],[16.357809,99.572144],[16.354179,99.579102],[16.3515,99.584412],[16.35004,99.587318],[16.34803,99.591476],[16.345989,99.595329],[16.343031,99.599533],[16.341009,99.602783],[16.340269,99.605164],[16.338449,99.611328],[16.33709,99.614616],[16.33412,99.621323],[16.33148,99.627182],[16.331369,99.627449],[16.331261,99.627708],[16.330481,99.629509],[16.330259,99.630028],[16.327971,99.635368],[16.325199,99.641823],[16.32476,99.642838],[16.32181,99.649696],[16.319851,99.654007],[16.318529,99.655403],[16.31654,99.656693],[16.314871,99.657768],[16.312389,99.659416],[16.306021,99.663673],[16.305111,99.664284],[16.304211,99.664886],[16.303789,99.665169],[16.3034,99.665428],[16.30304,99.665657],[16.30287,99.665779],[16.30233,99.666168],[16.301941,99.666451],[16.3013,99.666878],[16.299049,99.668381],[16.29727,99.669563],[16.29705,99.669693],[16.2957,99.670593],[16.291679,99.673317],[16.28627,99.676964],[16.281839,99.679993],[16.279289,99.681396],[16.27492,99.682663],[16.27183,99.68354],[16.27051,99.683891],[16.269991,99.684036],[16.26354,99.685898],[16.26153,99.686478],[16.261141,99.6866],[16.260651,99.68676],[16.26017,99.686951],[16.25979,99.687103],[16.25938,99.687233],[16.258711,99.687469],[16.257021,99.688049],[16.252399,99.689629],[16.24692,99.691513],[16.2456,99.691933],[16.239849,99.693893],[16.238029,99.694511],[16.23308,99.696198],[16.23126,99.696831],[16.225599,99.698792],[16.218821,99.701103],[16.212601,99.703194],[16.20962,99.704193],[16.20705,99.70507],[16.206079,99.705429],[16.20174,99.706932],[16.19735,99.708397],[16.191231,99.710533],[16.188431,99.711472],[16.18173,99.713753],[16.18017,99.714302],[16.173941,99.716423],[16.16938,99.717972],[16.168091,99.718399],[16.16556,99.719292],[16.16477,99.719543],[16.16378,99.719856],[16.161659,99.720573],[16.16049,99.720901],[16.15974,99.721077],[16.159121,99.721191],[16.158421,99.721283],[16.157591,99.721336],[16.156981,99.721367],[16.15621,99.721359],[16.15048,99.721077],[16.14863,99.721024],[16.14603,99.720886],[16.13858,99.720573],[16.131781,99.720222],[16.12528,99.719902],[16.12373,99.719841],[16.122801,99.719818],[16.1194,99.719658],[16.118521,99.719597],[16.113729,99.719383],[16.11319,99.719353],[16.1068,99.719032],[16.105841,99.718987],[16.105129,99.719032],[16.10462,99.719116],[16.104019,99.719231],[16.10347,99.71936],[16.10277,99.719597],[16.10154,99.720123],[16.100809,99.720444],[16.099581,99.72094],[16.09844,99.72142],[16.09675,99.722153],[16.094219,99.723213],[16.09005,99.724953],[16.08955,99.725159],[16.084841,99.727127],[16.083389,99.72776],[16.077311,99.730301],[16.073151,99.732063],[16.07266,99.732262],[16.069929,99.733414],[16.06741,99.734489],[16.066401,99.73497],[16.065611,99.735367],[16.064939,99.735817],[16.06447,99.736214],[16.063801,99.73674],[16.06336,99.737137],[16.06078,99.739899],[16.056009,99.745132],[16.05513,99.746132],[16.05422,99.747093],[16.051439,99.750137],[16.050329,99.75135],[16.04903,99.752762],[16.04497,99.757187],[16.04143,99.761009],[16.041059,99.761414],[16.039579,99.763023],[16.037701,99.765007],[16.03714,99.76561],[16.036949,99.765823],[16.033899,99.769058],[16.03371,99.769257],[16.032,99.771072],[16.030279,99.772903],[16.03009,99.773102],[16.02557,99.777908],[16.02293,99.780693],[16.022169,99.781502],[16.02067,99.783081],[16.017441,99.786484],[16.016199,99.787788],[16.01602,99.787971],[16.01585,99.788147],[16.01568,99.788322],[16.015511,99.788498],[16.012739,99.791367],[16.011209,99.792999],[16.009171,99.795059],[16.00786,99.796494],[16.00614,99.798203],[16.0058,99.798553],[16.00466,99.799652],[16.003059,99.801308],[16.002541,99.801842],[16.00178,99.802597],[16.00106,99.803329],[15.99995,99.804489],[15.99944,99.805008],[15.99893,99.805519],[15.99852,99.805931],[15.99809,99.806351],[15.99742,99.807022],[15.99617,99.80825],[15.9937,99.810783],[15.98944,99.815048],[15.98454,99.819893],[15.97968,99.824661],[15.97439,99.829727],[15.97032,99.833603],[15.96583,99.83783],[15.96129,99.842163],[15.95713,99.846077],[15.95294,99.849953],[15.94795,99.854523],[15.9424,99.859627],[15.93697,99.864578],[15.93211,99.868973],[15.92862,99.872124],[15.9278,99.872879],[15.9247,99.875671],[15.92328,99.876953],[15.91854,99.880997],[15.91306,99.885612],[15.9105,99.887657],[15.90986,99.888168],[15.9086,99.889183],[15.90651,99.890747],[15.90628,99.890923],[15.90516,99.891769],[15.90126,99.894272],[15.89934,99.895317],[15.89693,99.896713],[15.8955,99.897507],[15.89383,99.898468],[15.89143,99.899841],[15.89,99.900673],[15.88886,99.90136],[15.88588,99.903069],[15.88534,99.903381],[15.88477,99.903732],[15.88452,99.903877],[15.8836,99.904411],[15.88287,99.904839],[15.8822,99.90519],[15.88194,99.905327],[15.88062,99.906067],[15.87939,99.906723],[15.87742,99.907837],[15.87723,99.907944],[15.87684,99.908173],[15.87643,99.908409],[15.87577,99.908791],[15.87485,99.909317],[15.87437,99.909599],[15.87366,99.910019],[15.86913,99.912613],[15.86472,99.915161],[15.86172,99.916901],[15.85842,99.918762],[15.8563,99.919983],[15.85584,99.920273],[15.85352,99.921623],[15.84915,99.924141],[15.848,99.924797],[15.84266,99.927872],[15.8408,99.92894],[15.83893,99.929993],[15.83869,99.930107],[15.83772,99.930634],[15.83604,99.931587],[15.83532,99.932007],[15.83225,99.933769],[15.83179,99.934036],[15.83115,99.934402],[15.83021,99.934952],[15.82925,99.935547],[15.82839,99.93605],[15.82702,99.936836],[15.82609,99.93734],[15.82586,99.937469],[15.82543,99.937714],[15.82486,99.938042],[15.82453,99.938217],[15.82423,99.938393],[15.82276,99.939194],[15.82242,99.939377],[15.82224,99.939491],[15.82184,99.939728],[15.81962,99.941002],[15.81839,99.941757],[15.81794,99.942009],[15.81565,99.943443],[15.81245,99.946007],[15.80879,99.949387],[15.80795,99.95015],[15.80672,99.951286],[15.80631,99.95166],[15.8061,99.951851],[15.80549,99.952423],[15.80023,99.957314],[15.79641,99.960907],[15.79151,99.965446],[15.79109,99.96582],[15.79089,99.966019],[15.79047,99.966408],[15.78922,99.967567],[15.78465,99.971817],[15.78341,99.972961],[15.77872,99.977364],[15.77314,99.98259],[15.77137,99.984322],[15.77118,99.984497],[15.771,99.98468],[15.7703,99.985336],[15.76963,99.985992],[15.76806,99.98748],[15.76747,99.988037],[15.76677,99.988701],[15.76587,99.989563],[15.76536,99.990021],[15.76506,99.990311],[15.76447,99.990868],[15.76404,99.99128],[15.76343,99.991859],[15.76275,99.9925],[15.76078,99.99437],[15.75662,99.99836],[15.75542,99.999496],[15.75523,99.99968],[15.75283,100.001961],[15.75206,100.002693],[15.75028,100.004356],[15.7501,100.004539],[15.74955,100.005058],[15.74901,100.005569],[15.74865,100.005913],[15.74847,100.006073],[15.74829,100.006241],[15.74811,100.006409],[15.74671,100.007736],[15.74604,100.008377],[15.74588,100.008537],[15.74571,100.00869],[15.74555,100.00885],[15.74347,100.010841],[15.74286,100.011513],[15.74271,100.011703],[15.74197,100.012627],[15.74139,100.013474],[15.74012,100.015778],[15.73951,100.017059],[15.73938,100.017326],[15.73767,100.020683],[15.73662,100.022697],[15.73636,100.023193],[15.73404,100.027718],[15.7334,100.028908],[15.73182,100.031929],[15.73156,100.03244],[15.73129,100.032944],[15.73064,100.034187],[15.72901,100.037308],[15.72816,100.038933],[15.72779,100.039627],[15.72742,100.040352],[15.72717,100.040833],[15.72655,100.042023],[15.7244,100.04612],[15.72409,100.046707],[15.72305,100.048714],[15.72204,100.050598],[15.72073,100.053078],[15.72005,100.054352],[15.71917,100.056023],[15.71907,100.05619],[15.71891,100.056511],[15.71863,100.057007],[15.71828,100.057648],[15.71801,100.058121],[15.71785,100.058388],[15.71766,100.058548],[15.71751,100.058578],[15.71732,100.058617],[15.71702,100.058617],[15.71687,100.058578],[15.71626,100.058357],[15.71531,100.058052],[15.71488,100.057907],[15.71418,100.057663],[15.71319,100.057289],[15.70982,100.056313],[15.70848,100.056099],[15.70526,100.055977],[15.70499,100.055977],[15.70418,100.055969],[15.69769,100.055939],[15.69256,100.055923],[15.68718,100.05587],[15.68639,100.055878],[15.68184,100.055962],[15.67809,100.056519],[15.67601,100.057114],[15.67575,100.05719],[15.67549,100.057281],[15.67423,100.05777],[15.67133,100.059227],[15.67039,100.059776],[15.66859,100.06102],[15.66796,100.061508],[15.66775,100.061684],[15.66653,100.062759],[15.66613,100.063141],[15.66593,100.063339],[15.66535,100.063927],[15.66513,100.064194],[15.66399,100.065514],[15.66335,100.066238],[15.6628,100.066879],[15.66244,100.067307],[15.65813,100.072357],[15.65441,100.076736],[15.65335,100.07798],[15.64987,100.082092],[15.64952,100.082497],[15.64579,100.086853],[15.64386,100.089127],[15.64161,100.091782],[15.63819,100.095734],[15.63676,100.097382],[15.63577,100.098457],[15.63527,100.099083],[15.63476,100.099693],[15.63253,100.10228],[15.63229,100.102562],[15.6313,100.103737],[15.63024,100.105003],[15.62668,100.109123],[15.6219,100.114677],[15.62155,100.115082],[15.62043,100.116333],[15.61751,100.119652],[15.61555,100.121933],[15.61525,100.122299],[15.61512,100.122459],[15.61465,100.122726],[15.61421,100.12278],[15.61356,100.12236],[15.61316,100.121872],[15.61283,100.121582],[15.6123,100.121407],[15.61209,100.121422],[15.61115,100.121536],[15.6109,100.121559],[15.61037,100.121597],[15.60577,100.122017],[15.60203,100.122414],[15.60097,100.122528],[15.59964,100.122673],[15.59883,100.122726],[15.59727,100.122887],[15.594,100.123238],[15.59322,100.123322],[15.59139,100.123497],[15.59112,100.123528],[15.58641,100.124046],[15.58456,100.12426],[15.58217,100.124512],[15.57952,100.124786],[15.57741,100.125023],[15.57477,100.125313],[15.57104,100.12571],[15.5673,100.126099],[15.56677,100.126152],[15.56257,100.126587],[15.55892,100.126907],[15.55866,100.126938],[15.55732,100.127083],[15.55625,100.12719],[15.55572,100.127258],[15.55546,100.127289],[15.55467,100.127388],[15.54787,100.128113],[15.54605,100.128242],[15.54499,100.128197],[15.54446,100.128113],[15.54343,100.127853],[15.5396,100.126534],[15.53935,100.126427],[15.53479,100.124977],[15.53266,100.124817],[15.53055,100.125191],[15.52954,100.125526],[15.52501,100.127136],[15.52288,100.127296],[15.52028,100.126984],[15.51816,100.126678],[15.51471,100.126213],[15.5098,100.125504],[15.50955,100.125473],[15.50904,100.125397],[15.50748,100.125252],[15.50665,100.125229],[15.50425,100.125526],[15.50321,100.125801],[15.50295,100.125893],[15.50144,100.126472],[15.49994,100.127098],[15.49968,100.127197],[15.4979,100.127907],[15.49206,100.130219],[15.49181,100.130333],[15.48732,100.132233],[15.48482,100.133888],[15.48358,100.134918],[15.48048,100.137543],[15.47986,100.138069],[15.47966,100.138237],[15.47863,100.139107],[15.4778,100.139793],[15.47758,100.139954],[15.4769,100.140404],[15.47667,100.140549],[15.4762,100.140823],[15.47547,100.141182],[15.47293,100.142067],[15.47161,100.142403],[15.46452,100.144142],[15.46318,100.144463],[15.46139,100.144882],[15.46078,100.145027],[15.45703,100.145958],[15.45379,100.14653],[15.45133,100.146538],[15.44864,100.146118],[15.44813,100.145958],[15.44761,100.145798],[15.44397,100.144928],[15.44036,100.144043],[15.43984,100.143913],[15.43825,100.143509],[15.43669,100.143097],[15.43405,100.142403],[15.43217,100.142311],[15.43031,100.142761],[15.42954,100.143051],[15.42879,100.143341],[15.42844,100.143471],[15.42729,100.143898],[15.42502,100.144737],[15.41997,100.146683],[15.41895,100.147003],[15.41788,100.147179],[15.41599,100.147247],[15.41572,100.147247],[15.41438,100.147217],[15.41276,100.147232],[15.41113,100.147217],[15.40869,100.147186],[15.40271,100.147087],[15.40135,100.147087],[15.40056,100.147079],[15.39872,100.147141],[15.39752,100.147209],[15.39729,100.147232],[15.39668,100.147301],[15.39601,100.147377],[15.39561,100.147438],[15.39551,100.147453],[15.3949,100.14756],[15.39478,100.147583],[15.39407,100.14772],[15.39362,100.147827],[15.393,100.148003],[15.39124,100.148438],[15.39037,100.148712],[15.39014,100.148788],[15.38919,100.149109],[15.38869,100.149261],[15.38818,100.149422],[15.38664,100.14994],[15.38307,100.151154],[15.38178,100.151604],[15.38048,100.152039],[15.38021,100.15213],[15.37995,100.152222],[15.37785,100.152931],[15.37759,100.153023],[15.37479,100.153976],[15.3707,100.155373],[15.36592,100.157043],[15.36289,100.158073],[15.35931,100.159286],[15.35477,100.16095],[15.35355,100.161484],[15.34929,100.163544],[15.34725,100.164627],[15.34634,100.165154],[15.34216,100.16748],[15.341,100.168121],[15.33988,100.168739],[15.3395,100.168953],[15.33886,100.169312],[15.33798,100.1698],[15.33737,100.170143],[15.33693,100.170387],[15.33648,100.170631],[15.33251,100.172836],[15.33088,100.173737],[15.32901,100.174782],[15.32783,100.17543],[15.32526,100.176849],[15.32505,100.176971],[15.32421,100.177437],[15.32274,100.178253],[15.32159,100.178886],[15.32127,100.17907],[15.31896,100.180351],[15.31723,100.18132],[15.3147,100.182716],[15.31442,100.182877],[15.31256,100.183907],[15.31003,100.185318],[15.30866,100.186073],[15.30612,100.187477],[15.30554,100.187843],[15.30511,100.18808],[15.30416,100.188568],[15.30307,100.189117],[15.30274,100.189278],[15.30025,100.190407],[15.2999,100.190559],[15.29957,100.190697],[15.2993,100.190811],[15.29896,100.190964],[15.29851,100.191147],[15.29838,100.1912],[15.29825,100.191261],[15.29813,100.191307],[15.29798,100.191368],[15.29782,100.191437],[15.2976,100.191521],[15.29703,100.191742],[15.29618,100.192047],[15.29541,100.192329],[15.29437,100.19268],[15.29415,100.192757],[15.29393,100.192833],[15.29348,100.192978],[15.29326,100.193047],[15.28926,100.194153],[15.28852,100.194344],[15.28729,100.194672],[15.28608,100.195],[15.28584,100.195061],[15.28535,100.19519],[15.28036,100.196571],[15.27729,100.197403],[15.27612,100.197723],[15.2747,100.198097],[15.27351,100.198418],[15.27231,100.198738],[15.26826,100.199837],[15.26282,100.201271],[15.26071,100.201843],[15.26047,100.20192],[15.25882,100.202377],[15.2581,100.202583],[15.25691,100.202904],[15.25644,100.203018],[15.25549,100.203247],[15.25526,100.2033],[15.2548,100.203407],[15.25265,100.203819],[15.24998,100.204338],[15.24949,100.20443],[15.24851,100.204643],[15.24778,100.204781],[15.24681,100.204987],[15.24633,100.205078],[15.24512,100.205307],[15.24278,100.20578],[15.24127,100.206078],[15.24049,100.20623],[15.23587,100.207352],[15.23538,100.207481],[15.23346,100.208],[15.23133,100.208572],[15.22951,100.209053],[15.22351,100.210709],[15.2228,100.210907],[15.22038,100.211639],[15.22014,100.211723],[15.21967,100.211884],[15.21848,100.212288],[15.21754,100.212608],[15.21614,100.21312],[15.21521,100.213493],[15.21316,100.214401],[15.20888,100.216461],[15.20757,100.217171],[15.20649,100.217796],[15.20231,100.220222],[15.19877,100.222237],[15.19429,100.224808],[15.19122,100.226486],[15.18906,100.227707],[15.18715,100.228844],[15.18267,100.231468],[15.18014,100.233093],[15.17931,100.23365],[15.17829,100.23436],[15.17748,100.234932],[15.17647,100.235672],[15.17547,100.236397],[15.17467,100.237],[15.17427,100.237297],[15.17085,100.239853],[15.16943,100.240891],[15.16743,100.242371],[15.16702,100.242668],[15.16662,100.242973],[15.1636,100.245178],[15.16119,100.246941],[15.15867,100.248703],[15.15807,100.249092],[15.1566,100.249992],[15.15618,100.250237],[15.1529,100.251968],[15.15093,100.25296],[15.14985,100.25354],[15.14877,100.254128],[15.14688,100.255127],[15.14652,100.25531],[15.14462,100.256218],[15.14441,100.25631],[15.14381,100.256569],[15.14345,100.256737],[15.14328,100.256813],[15.14258,100.257141],[15.1424,100.257233],[15.13979,100.258553],[15.13638,100.260277],[15.13618,100.260384],[15.13599,100.260468],[15.13366,100.261642],[15.13288,100.262032],[15.13269,100.262131],[15.13211,100.262428],[15.13091,100.263031],[15.13071,100.26313],[15.13028,100.263344],[15.13006,100.263458],[15.12984,100.263573],[15.12871,100.26413],[15.12803,100.26445],[15.12519,100.265984],[15.12263,100.267998],[15.12059,100.270264],[15.12029,100.270668],[15.11829,100.273659],[15.11704,100.275551],[15.11691,100.275757],[15.11476,100.279121],[15.11189,100.283524],[15.1103,100.286003],[15.10981,100.286713],[15.10929,100.287376],[15.107,100.289864],[15.1045,100.291901],[15.10075,100.294456],[15.09984,100.29509],[15.09925,100.295486],[15.09802,100.296333],[15.09573,100.29789],[15.09328,100.299507],[15.08991,100.301826],[15.08797,100.303169],[15.08675,100.304001],[15.08506,100.305168],[15.08359,100.306198],[15.08292,100.306671],[15.08214,100.307297],[15.08133,100.307953],[15.07951,100.30954],[15.07753,100.31144],[15.07606,100.312767],[15.07379,100.315063],[15.07118,100.317436],[15.06834,100.319649],[15.06525,100.32151],[15.05924,100.324608],[15.05301,100.327957],[15.04762,100.330757],[15.04751,100.330833],[15.04493,100.332314],[15.04151,100.334091],[15.0373,100.335579],[15.03228,100.336708],[15.02009,100.339088],[15.01539,100.340363],[15.01103,100.342216],[14.99827,100.348938],[14.98775,100.3545],[14.97862,100.359711],[14.94595,100.385002],[14.93855,100.390968],[14.93602,100.392723],[14.93327,100.394218],[14.9229,100.399612],[14.9125,100.405006],[14.90917,100.406914],[14.90763,100.408119],[14.90623,100.409462],[14.90454,100.411537],[14.90295,100.413712],[14.89979,100.418411],[14.89884,100.419594],[14.89781,100.420708],[14.89672,100.421722],[14.89556,100.422684],[14.88987,100.426567],[14.88409,100.430473],[14.87735,100.435089],[14.87514,100.43644],[14.87249,100.437813],[14.87109,100.438423],[14.86971,100.43895],[14.86837,100.439407],[14.86738,100.439743],[14.84928,100.445084],[14.84726,100.445663],[14.84332,100.446716],[14.83894,100.447487],[14.83473,100.44767],[14.82958,100.44735],[14.82374,100.446953],[14.81974,100.446632],[14.81552,100.447098],[14.81223,100.448128],[14.80827,100.450729],[14.80396,100.454041],[14.7992,100.45681],[14.79534,100.458],[14.79177,100.458366],[14.78836,100.457741],[14.78346,100.455803],[14.77892,100.453453],[14.77537,100.451897],[14.77126,100.450951],[14.76771,100.450951],[14.76466,100.451317],[14.76021,100.452454],[14.75194,100.45343],[14.74029,100.454597],[14.72864,100.454987],[14.71756,100.455673],[14.71203,100.455742],[14.70655,100.455513],[14.70081,100.456139],[14.69838,100.456802],[14.69604,100.457611],[14.69409,100.458519],[14.69224,100.459549],[14.68872,100.461807],[14.68175,100.466316],[14.67903,100.468048],[14.67772,100.468758],[14.67635,100.469383],[14.6747,100.470032],[14.6729,100.470589],[14.67138,100.470947],[14.6698,100.471199],[14.66144,100.472649],[14.65078,100.474442],[14.64606,100.474808],[14.6414,100.474693],[14.63213,100.473251],[14.61383,100.469772],[14.60978,100.468941],[14.60526,100.469658],[14.60155,100.470863],[14.596,100.473961],[14.58557,100.480904],[14.5814,100.483727],[14.57584,100.487503],[14.57241,100.489838],[14.56537,100.493813],[14.55793,100.497063],[14.5467,100.500923],[14.53397,100.504532],[14.52399,100.507629],[14.51725,100.512268],[14.51076,100.517433],[14.50352,100.520782],[14.48903,100.526711],[14.48318,100.529457],[14.47226,100.534416],[14.46707,100.536926],[14.46552,100.537682],[14.46439,100.538063],[14.4626,100.538567],[14.45988,100.539131],[14.45759,100.539543],[14.45528,100.540001],[14.45267,100.540497],[14.45009,100.540977],[14.44627,100.541733],[14.44432,100.542099],[14.4423,100.542282],[14.43974,100.54303],[14.43799,100.543922],[14.43635,100.545029],[14.43472,100.546593],[14.4333,100.548424],[14.42962,100.553459],[14.42807,100.555634],[14.42727,100.556686],[14.42557,100.558952],[14.41425,100.574028],[14.40527,100.584137],[14.40375,100.585831],[14.40259,100.587097],[14.40093,100.588966],[14.39634,100.594048],[14.39526,100.595238],[14.39514,100.595383],[14.39509,100.595413],[14.39261,100.597809],[14.38907,100.600853],[14.38355,100.604683],[14.38173,100.605766],[14.37816,100.607613],[14.37716,100.608047],[14.37459,100.609138],[14.37241,100.609978],[14.36911,100.610939],[14.36623,100.611748],[14.36269,100.612419],[14.35971,100.613007],[14.35777,100.613167],[14.35565,100.613297],[14.35309,100.613327],[14.34958,100.613258],[14.34487,100.613213],[14.332,100.613342],[14.32856,100.613327],[14.31873,100.613327],[14.30838,100.613342],[14.3044,100.613373],[14.30383,100.613373],[14.30248,100.613388],[14.28388,100.613457],[14.26434,100.613449],[14.26224,100.613487],[14.25709,100.613564],[14.2519,100.613564],[14.24813,100.613564],[14.24431,100.613411],[14.24005,100.612999],[14.23393,100.612228],[14.23293,100.612091],[14.23122,100.61187],[14.21575,100.609734],[14.21111,100.609123],[14.21052,100.609062],[14.20943,100.608963],[14.20799,100.60891],[14.20694,100.608932],[14.2055,100.608994],[14.2024,100.609047],[14.20071,100.609154],[14.19831,100.609467],[14.19601,100.609779],[14.19276,100.610519],[14.18953,100.61145],[14.18302,100.613777],[14.17835,100.61557],[14.17814,100.615677],[14.17804,100.615761],[14.17794,100.615837],[14.17783,100.615936],[14.17773,100.616058],[14.17759,100.616257],[14.17754,100.616348],[14.17745,100.616524],[14.17739,100.616699],[14.17736,100.616814],[14.17734,100.616943],[14.17734,100.617081],[14.17737,100.617218],[14.17741,100.617348],[14.17747,100.61747],[14.17755,100.617599],[14.17835,100.618568],[14.17858,100.618782],[14.17868,100.618927],[14.17905,100.619164],[14.17952,100.619453],[14.17988,100.619713],[14.18023,100.620003],[14.18057,100.620293],[14.18088,100.620598],[14.18122,100.620956],[14.18154,100.621353],[14.18183,100.621742],[14.1821,100.622139],[14.18238,100.622627],[14.18266,100.623169],[14.18351,100.624786],[14.18394,100.625603],[14.1876,100.6325],[14.18777,100.632629],[14.18804,100.632973],[14.18819,100.633118],[14.18844,100.633324],[14.1886,100.633423],[14.18879,100.633507],[14.18898,100.633583],[14.18944,100.633728],[14.18958,100.633781],[14.18973,100.633858],[14.18985,100.633949],[14.18996,100.634079],[14.19003,100.634178],[14.1901,100.6343],[14.19017,100.634453],[14.19021,100.634598],[14.19024,100.634697],[14.19024,100.634773],[14.19026,100.634903],[14.19025,100.635078],[14.19024,100.635193],[14.19022,100.635292],[14.1902,100.635384],[14.19014,100.635567],[14.19004,100.635803],[14.18993,100.636009],[14.18973,100.636276],[14.18955,100.636513],[14.18934,100.636711],[14.18917,100.636848],[14.18869,100.637123],[14.18505,100.63929],[14.18225,100.640869],[14.16198,100.65229],[14.15898,100.653976],[14.14369,100.662613],[14.14085,100.664207],[14.12254,100.67453],[14.11993,100.676003],[14.1014,100.686447],[14.09778,100.688477],[14.08837,100.693787],[14.08782,100.694069],[14.08718,100.694328],[14.08655,100.694542],[14.08592,100.694717],[14.08521,100.694847],[14.08467,100.694923],[14.0686,100.696533],[14.06346,100.697052],[14.05247,100.698151],[14.05158,100.698227],[14.05068,100.698273],[14.02581,100.698288],[14.02536,100.698311],[14.02491,100.698341],[14.02444,100.698387],[14.02399,100.698463],[14.0235,100.698547],[14.02317,100.698624],[14.02292,100.698692],[14.0224,100.698837],[14.02195,100.698982],[14.02148,100.69915],[14.02108,100.699318],[14.02067,100.699501],[14.01956,100.699989],[14.00956,100.704399],[13.99926,100.708946],[13.99298,100.711723],[13.99042,100.712837],[13.98989,100.713013],[13.98935,100.713173],[13.98881,100.713287],[13.98828,100.713371],[13.98776,100.713417],[13.98726,100.713463],[13.98675,100.713448],[13.9863,100.713417],[13.98523,100.713333],[13.98473,100.713333],[13.9826,100.713287],[13.95215,100.71286],[13.95173,100.712837],[13.95132,100.712822],[13.95075,100.712784],[13.9502,100.712723],[13.94955,100.712624],[13.94912,100.712547],[13.94865,100.712463],[13.94311,100.710999],[13.93615,100.709167],[13.93011,100.707581],[13.92421,100.706032],[13.92266,100.705643],[13.92128,100.705261],[13.92036,100.704964],[13.91983,100.704773],[13.91909,100.704483],[13.9177,100.703888],[13.91276,100.701317],[13.90788,100.698799],[13.90705,100.698357],[13.89609,100.692703],[13.89326,100.691231],[13.88801,100.688507],[13.88746,100.688217],[13.87732,100.682983],[13.87618,100.682381],[13.86972,100.679039],[13.86879,100.678574],[13.86822,100.678307],[13.86793,100.6782],[13.86763,100.678101],[13.86725,100.677994],[13.86686,100.677887],[13.8578,100.675797],[13.8572,100.675636],[13.85666,100.675484],[13.85623,100.675323],[13.85546,100.675003],[13.8538,100.674316],[13.85204,100.673592],[13.85131,100.673302],[13.85097,100.67318],[13.85063,100.67308],[13.85029,100.672997],[13.84993,100.672928],[13.84957,100.672882],[13.84612,100.672638],[13.84541,100.672592],[13.84291,100.672417],[13.84251,100.672401],[13.84197,100.672401],[13.84152,100.672432],[13.84111,100.672478],[13.84064,100.672546],[13.84026,100.672623],[13.83963,100.672783],[13.83788,100.673233],[13.83672,100.673523],[13.83597,100.673721],[13.83529,100.673866],[13.83487,100.673943],[13.83439,100.674011],[13.83402,100.674049],[13.83295,100.674118],[13.83175,100.674179],[13.82532,100.67453],[13.8245,100.674606],[13.82378,100.674713],[13.8232,100.674828],[13.82128,100.675308],[13.81476,100.677017],[13.79887,100.681221],[13.79574,100.682037],[13.78257,100.685516],[13.78209,100.685669],[13.78161,100.685822],[13.7809,100.686073],[13.78006,100.686363],[13.77943,100.686623],[13.77875,100.68692],[13.77829,100.687134],[13.77761,100.687462],[13.77604,100.688309],[13.77088,100.691109],[13.76983,100.691681],[13.76765,100.692863],[13.76654,100.693466],[13.76069,100.696648],[13.75988,100.69709],[13.75691,100.6987],[13.75131,100.701736],[13.75102,100.701881],[13.75072,100.702011],[13.75036,100.702148],[13.7501,100.70224],[13.74983,100.702316],[13.74956,100.7024],[13.74928,100.702469],[13.74898,100.70253],[13.7487,100.702583],[13.7481,100.70266],[13.74738,100.702713],[13.74684,100.702713],[13.74257,100.702789],[13.74221,100.70298],[13.73885,100.703033],[13.73849,100.703217],[13.73729,100.703247],[13.73711,100.703346],[13.7362,100.70343],[13.73587,100.703499],[13.73561,100.703598],[13.73523,100.70388],[13.73436,100.704857],[13.73386,100.705383],[13.73325,100.705803],[13.73292,100.706093],[13.73268,100.706451],[13.73245,100.707199],[13.73227,100.70813],[13.7322,100.708519],[13.73188,100.710297],[13.7304,100.723747],[13.73037,100.724022],[13.72961,100.73085],[13.72959,100.731033],[13.72935,100.73317],[13.72933,100.733917],[13.72933,100.734703],[13.72949,100.740051],[13.72953,100.741081],[13.72953,100.741257],[13.7296,100.744133],[13.7297,100.748718],[13.72977,100.751572],[13.72991,100.757378],[13.72997,100.757896],[13.7309,100.761551],[13.73172,100.764793],[13.7318,100.765182],[13.73183,100.765602],[13.73191,100.76786],[13.73211,100.771118],[13.73215,100.773232],[13.73228,100.783249],[13.73232,100.784142],[13.73249,100.785889],[13.73291,100.79023],[13.73429,100.803726],[13.73383,100.805557],[13.73315,100.807281],[13.73138,100.809334],[13.72858,100.811081],[13.72721,100.81176],[13.7256,100.812553],[13.71357,100.818466],[13.71015,100.820236],[13.67427,100.838043],[13.67241,100.840233],[13.66908,100.845444],[13.60214,100.949783],[13.59885,100.954903],[13.59275,100.964043],[13.57161,100.981888],[13.55248,100.997871],[13.5509,100.999191],[13.5466,101.002937],[13.54299,101.005966],[13.53928,101.009087],[13.5367,101.011261],[13.49601,101.045448],[13.4933,101.046761],[13.49057,101.04705],[13.47329,101.04612],[13.4541,101.046257],[13.44076,101.046288],[13.42756,101.046783],[13.39933,101.047531],[13.39226,101.047073],[13.38711,101.046272],[13.36243,101.038658],[13.35742,101.036041],[13.35643,101.035423],[13.35091,101.031921],[13.34394,101.027634],[13.32626,101.016411],[13.31824,101.010399],[13.303,100.998978],[13.30144,100.997482],[13.30042,100.99649],[13.29915,100.99559],[13.29733,100.994743],[13.29551,100.993729],[13.29331,100.992599],[13.29079,100.991959],[13.28824,100.991524],[13.2831,100.991096],[13.27806,100.990791],[13.27206,100.990356],[13.26595,100.989998],[13.26406,100.989861],[13.26223,100.989769],[13.26119,100.98983],[13.26009,100.98996],[13.25884,100.990173],[13.25766,100.990509],[13.25655,100.990868],[13.25397,100.991837],[13.25177,100.992706],[13.24063,100.996986],[13.23351,100.99971],[13.22734,101.002083],[13.22418,101.003311],[13.22106,101.004509],[13.21955,101.005058],[13.21801,101.005463],[13.21637,101.005692],[13.21487,101.005783],[13.21191,101.005524],[13.20789,101.004379],[13.20639,101.003883],[13.19684,101.00074],[13.19001,100.99852],[13.18317,100.996277],[13.17575,100.993828],[13.16839,100.99144],[13.16099,100.989037],[13.15633,100.987556],[13.15439,100.986961],[13.15364,100.986717],[13.15228,100.986397],[13.15062,100.986153],[13.14806,100.986031],[13.14536,100.985947],[13.14282,100.985809],[13.13809,100.985718],[13.13165,100.985413],[13.12547,100.985199],[13.12188,100.985008],[13.12003,100.985031],[13.11832,100.985123],[13.11127,100.986557],[13.10656,100.987534],[13.10132,100.988663],[13.09598,100.989754],[13.09082,100.990791],[13.08545,100.99192],[13.07498,100.994072],[13.06974,100.995102],[13.06474,100.996117],[13.05745,100.996262],[13.05021,100.996323],[13.03819,100.996429],[13.025,100.996498],[13.01834,100.996536],[13.01381,100.996597],[13.01173,100.996452],[13.00731,100.995232],[12.99751,100.991707],[12.99483,100.990753],[12.98278,100.986504],[12.97491,100.983803],[12.97186,100.982681],[12.96919,100.981857],[12.96762,100.981293],[12.96685,100.981194],[12.9663,100.981056],[12.96574,100.98101],[12.96515,100.981056],[12.96462,100.981377],[12.96341,100.982033],[12.96096,100.98378],[12.95902,100.984718],[12.95468,100.98716],[12.95261,100.988342],[12.94143,100.994949],[12.93028,101.001678],[12.92805,101.003357],[12.92681,101.00486],[12.92379,101.009621],[12.92007,101.015747],[12.91659,101.0214],[12.91547,101.022774],[12.9151,101.023117],[12.91215,101.025848],[12.90933,101.028763],[12.90849,101.029533],[12.90795,101.03009],[12.90274,101.035248],[12.90131,101.036652],[12.90082,101.03714],[12.89481,101.043053],[12.88653,101.051193],[12.88284,101.05481],[12.87155,101.065903],[12.86993,101.067871],[12.86114,101.083557],[12.85287,101.098701],[12.84665,101.109756],[12.84072,101.120407],[12.83925,101.121857],[12.83811,101.12278],[12.83599,101.12429],[12.83082,101.127808],[12.82666,101.130661],[12.82239,101.133537],[12.81921,101.135651],[12.81603,101.137787],[12.80908,101.142593],[12.80223,101.147209],[12.79566,101.151749],[12.78903,101.15638],[12.78129,101.163872],[12.77738,101.167793],[12.77337,101.171707],[12.76987,101.175087],[12.76591,101.179092],[12.76228,101.182678],[12.75869,101.186302],[12.75254,101.192291],[12.7495,101.195259],[12.74631,101.198151],[12.73827,101.20517],[12.73008,101.212349],[12.72737,101.214783],[12.72482,101.217682],[12.72087,101.222397],[12.71684,101.227226],[12.70798,101.237846],[12.70502,101.241524],[12.7044,101.242378],[12.7039,101.243347],[12.70129,101.250237],[12.69903,101.256577],[12.69825,101.264671],[12.69778,101.270447],[12.69759,101.273117],[12.69682,101.279663],[12.69649,101.282837],[12.69607,101.285477],[12.69359,101.291321],[12.69267,101.293213],[12.69164,101.294777],[12.69023,101.29615],[12.68867,101.297241],[12.68297,101.299988],[12.67723,101.302818],[12.66358,101.309792],[12.66238,101.311333],[12.66135,101.316528],[12.66116,101.317993],[12.65854,101.326317],[12.65777,101.328644],[12.65398,101.336578],[12.6483,101.344757],[12.64673,101.348091],[12.64639,101.348824],[12.64616,101.349297],[12.64595,101.349747],[12.64557,101.350563],[12.64334,101.355293],[12.64314,101.355721],[12.63985,101.362717],[12.63967,101.363518],[12.63899,101.372093],[12.64012,101.388603],[12.64075,101.398293],[12.64155,101.408882],[12.64237,101.422127],[12.64219,101.424332],[12.64124,101.42881],[12.64327,101.435623],[12.65019,101.447891],[12.65435,101.455276],[12.6613,101.472076],[12.66057,101.488861],[12.66082,101.495087],[12.66561,101.511528],[12.67204,101.521507],[12.68008,101.523369],[12.68229,101.525742],[12.68671,101.534187],[12.70008,101.541809],[12.70731,101.54882],[12.71304,101.560768],[12.71314,101.563553],[12.71917,101.568703],[12.72148,101.574471],[12.72651,101.577766],[12.73162,101.587303],[12.73595,101.595383],[12.75103,101.609909],[12.75394,101.613403],[12.7559,101.615753],[12.76348,101.624847],[12.77363,101.639168],[12.77632,101.64283],[12.78186,101.646896],[12.78272,101.650703],[12.78339,101.653229],[12.78356,101.653877],[12.78415,101.656662],[12.78494,101.6586],[12.7862,101.661133],[12.78678,101.662407],[12.78695,101.663277],[12.78691,101.664818],[12.78645,101.669197],[12.78565,101.679581],[12.78532,101.681557],[12.78398,101.68602],[12.78172,101.693832],[12.77642,101.711746],[12.77624,101.712372],[12.77546,101.715767],[12.77636,101.718887],[12.77753,101.722893],[12.78054,101.732933],[12.78879,101.760483],[12.78925,101.762283],[12.78942,101.766441],[12.78921,101.76889],[12.78892,101.772278],[12.78788,101.785912],[12.78737,101.788971],[12.78692,101.789993],[12.7862,101.791634],[12.78431,101.79554],[12.78356,101.796959],[12.78314,101.798241],[12.78285,101.800392],[12.78164,101.810562],[12.78092,101.815964],[12.78046,101.819359],[12.77996,101.821373],[12.77896,101.824249],[12.77678,101.830948],[12.77469,101.837212],[12.7741,101.838966],[12.77222,101.842232],[12.77109,101.843819],[12.76665,101.850388],[12.76581,101.851372],[12.76473,101.852402],[12.76247,101.854286],[12.76138,101.855186],[12.7597,101.857162],[12.75732,101.859947],[12.75564,101.861931],[12.75476,101.863258],[12.75255,101.867813],[12.74983,101.873299],[12.7466,101.880547],[12.74455,101.885017],[12.74267,101.889313],[12.74187,101.890121],[12.7407,101.8909],[12.73957,101.89167],[12.73878,101.892616],[12.73798,101.894157],[12.73551,101.899353],[12.73346,101.904243],[12.73224,101.907806],[12.73099,101.911499],[12.73091,101.912956],[12.73053,101.91626],[12.72299,101.941582],[12.72316,101.953247],[12.72295,101.954933],[12.72217,101.957153],[12.72216,101.958961],[12.72146,101.971413],[12.7209,101.972687],[12.72015,101.973846],[12.71939,101.975357],[12.71882,101.976128],[12.71659,101.978317],[12.71395,101.980293],[12.71165,101.981361],[12.70043,101.986168],[12.69917,101.986771],[12.69767,101.988274],[12.69088,101.995911],[12.68599,102.001244],[12.68335,102.00415],[12.6823,102.005096],[12.68121,102.005569],[12.67991,102.005608],[12.67862,102.005386],[12.67744,102.00518],[12.67636,102.005051],[12.67552,102.005013],[12.67451,102.00518],[12.65326,102.011581],[12.65151,102.012482],[12.65004,102.016434],[12.64939,102.018707],[12.64882,102.021049],[12.64871,102.021553],[12.64862,102.021927],[12.64854,102.022362],[12.6485,102.02282],[12.64855,102.023499],[12.64883,102.025787],[12.64942,102.03067],[12.65019,102.040031],[12.65722,102.058571],[12.66028,102.066811],[12.66145,102.071777],[12.66534,102.088951],[12.66677,102.0914],[12.66697,102.091743],[12.66748,102.092644],[12.6629,102.119957],[12.6499,102.129128],[12.64373,102.130623],[12.64176,102.131866],[12.63252,102.142036],[12.62387,102.151543],[12.62117,102.148933],[12.61644,102.141602],[12.61577,102.140556],[12.60959,102.134377],[12.60811,102.133591],[12.60534,102.133743],[12.60309,102.135002],[12.60275,102.1353],[12.60235,102.135674],[12.60058,102.137268],[12.59573,102.143303],[12.58852,102.155151],[12.57278,102.162529],[12.56758,102.162529],[12.55827,102.157852],[12.54606,102.155487],[12.54006,102.157417],[12.53078,102.157288],[12.53014,102.157707],[12.52137,102.163589],[12.51361,102.168503],[12.50319,102.170288],[12.50093,102.170937],[12.48798,102.174721],[12.48346,102.179352],[12.48312,102.181931],[12.47407,102.190857],[12.46938,102.195831],[12.46737,102.199783],[12.46502,102.206131],[12.4658,102.220001],[12.45995,102.230057],[12.45079,102.245682],[12.4543,102.258827],[12.45664,102.262444],[12.45698,102.269478],[12.45161,102.284752],[12.44726,102.288696],[12.4439,102.297287],[12.44038,102.300537],[12.43006,102.313637],[12.42664,102.318916],[12.41257,102.330421],[12.39741,102.350517],[12.39663,102.354973],[12.39218,102.364067],[12.38945,102.368896],[12.38737,102.370117],[12.38571,102.37117],[12.38241,102.373177],[12.381,102.374153],[12.37111,102.388428],[12.36611,102.395821],[12.36796,102.410751],[12.36292,102.425003],[12.34096,102.4468],[12.33492,102.456932],[12.32819,102.45916],[12.32289,102.459846],[12.31658,102.465607],[12.31094,102.468086],[12.30272,102.475471],[12.29473,102.480309],[12.28444,102.484909],[12.27337,102.493149],[12.25648,102.507713],[12.25171,102.509537],[12.25944,102.518356],[12.26459,102.532806],[12.26085,102.543793],[12.25926,102.553307],[12.25758,102.555817],[12.2537,102.560799],[12.25156,102.568703],[12.25103,102.578362],[12.25093,102.587677],[12.25035,102.608727],[12.25054,102.611641],[12.24529,102.625427],[12.23383,102.627869],[12.23004,102.632057],[12.22525,102.645149],[12.20238,102.657333],[12.19404,102.659683],[12.18628,102.665611],[12.16334,102.679649],[12.15023,102.683006],[12.13089,102.691048],[12.1194,102.694992],[12.11467,102.697151],[12.1053,102.700394],[12.09618,102.705383],[12.08143,102.718521],[12.07709,102.725151],[12.06748,102.731934],[12.06485,102.73616],[12.06065,102.739113],[12.05058,102.75132],[12.04662,102.753799],[12.04233,102.758507],[12.01981,102.769608],[12.01509,102.77037],[12.00404,102.770599],[11.98184,102.776588],[11.96461,102.783089],[11.92141,102.80452],[11.90769,102.808289],[11.90115,102.811401],[11.88415,102.814987],[11.87684,102.818672],[11.86838,102.820839],[11.84824,102.831734],[11.84367,102.837181],[11.81262,102.853706],[11.80578,102.860786],[11.78507,102.874878],[11.7791,102.883461],[11.77862,102.884491],[11.77812,102.886162],[11.77667,102.886948],[11.77323,102.888817],[11.77145,102.888847],[11.7708,102.889069],[11.76782,102.890984],[11.76454,102.894508],[11.75899,102.896049],[11.75711,102.896729],[11.75476,102.896507],[11.75231,102.897057],[11.75154,102.897423],[11.7498,102.897713],[11.74754,102.898857],[11.74599,102.899002],[11.74284,102.900726],[11.74084,102.901321],[11.73924,102.902321],[11.73823,102.902657],[11.73688,102.904053],[11.73105,102.906174],[11.72379,102.905197],[11.71887,102.907021],[11.71666,102.907227],[11.7156,102.907669],[11.71261,102.907578],[11.71073,102.907593],[11.70928,102.906769],[11.70047,102.906502],[11.69846,102.904984],[11.69535,102.904503],[11.69275,102.904793],[11.68926,102.903084],[11.68662,102.902481],[11.68326,102.903008],[11.68151,102.903816],[11.67983,102.904114],[11.67867,102.904861],[11.67712,102.905067],[11.67607,102.905533],[11.67155,102.904831],[11.6703,102.905792],[11.66651,102.906242],[11.66574,102.906036],[11.66491,102.906464],[11.66189,102.906693],[11.65979,102.907532],[11.65812,102.906967],[11.65571,102.907349],[11.65356,102.908577],[11.65165,102.908836],[11.64946,102.911377],[11.64477,102.916077],[11.6429,102.918373],[11.64362,102.923988],[11.64301,102.928268],[11.64347,102.933006],[11.63845,102.941254],[11.63771,102.943657],[11.63596,102.946564],[11.63056,102.94841],[11.62356,102.949257],[11.62305,102.959099],[11.61957,102.962143],[11.61888,102.962822],[11.6163,102.979683],[11.61549,102.983543],[11.6144,102.988731],[11.60786,102.99955],[11.602,103.010292],[11.60196,103.01226],[11.60207,103.013702],[11.60248,103.015457],[11.60349,103.018707],[11.60551,103.024986],[11.60552,103.025497],[11.60557,103.02755],[11.6056,103.030159],[11.60596,103.035187],[11.60501,103.03965],[11.60492,103.040741],[11.60497,103.043221],[11.60483,103.045799],[11.60459,103.051231],[11.60384,103.054947],[11.60387,103.055687],[11.60395,103.056992],[11.60426,103.060738],[11.60432,103.061996],[11.60429,103.062576],[11.60388,103.063538],[11.60186,103.065804],[11.60169,103.06633],[11.60166,103.066963],[11.60207,103.070351],[11.60197,103.071091],[11.60167,103.071609],[11.6012,103.072037],[11.60047,103.072578],[11.59986,103.072983],[11.59913,103.073311],[11.59821,103.073441],[11.59735,103.073799],[11.59625,103.074707],[11.59593,103.075119],[11.59537,103.076553],[11.59405,103.079643],[11.59234,103.082916],[11.59217,103.085197],[11.59172,103.085518],[11.58763,103.08609],[11.58631,103.087021],[11.58491,103.087578],[11.58245,103.087196],[11.58056,103.086647],[11.57998,103.08696],[11.57799,103.089256],[11.57315,103.091026],[11.5725,103.091621],[11.57233,103.091957],[11.57225,103.092667],[11.57285,103.094414],[11.57348,103.095551],[11.57386,103.096298],[11.5736,103.098068],[11.5731,103.099411],[11.57245,103.100128],[11.57032,103.103363],[11.57003,103.104584],[11.56918,103.108437],[11.56847,103.11319],[11.56842,103.117027],[11.56869,103.118782],[11.56872,103.119423],[11.56863,103.120323],[11.56853,103.121597],[11.56842,103.12207],[11.56795,103.122673],[11.5659,103.12368],[11.56546,103.124168],[11.56533,103.124733],[11.56502,103.128433],[11.5649,103.12986],[11.5649,103.130928],[11.56522,103.131577],[11.5656,103.131882],[11.56614,103.132057],[11.56714,103.132141],[11.56756,103.132301],[11.56791,103.132591],[11.56859,103.13308],[11.56917,103.133186],[11.57056,103.133148],[11.57129,103.133347],[11.57193,103.133659],[11.57353,103.135071],[11.57457,103.135872],[11.57491,103.136261],[11.57502,103.136902],[11.57487,103.137917],[11.57441,103.140404],[11.57429,103.141327],[11.57433,103.142113],[11.57444,103.142891],[11.57476,103.144463],[11.57497,103.144943],[11.57528,103.145447],[11.57682,103.146919],[11.57742,103.147034],[11.57778,103.147011],[11.57831,103.147133],[11.57866,103.147537],[11.57868,103.148178],[11.57848,103.148842],[11.57848,103.150169],[11.57856,103.15094],[11.57885,103.151627],[11.57896,103.152298],[11.57817,103.156929],[11.57748,103.15934],[11.57724,103.160477],[11.57753,103.162361],[11.57745,103.163803],[11.57709,103.165443],[11.57664,103.168533],[11.57636,103.172096],[11.57614,103.175041],[11.57617,103.176277],[11.5766,103.177353],[11.57753,103.179581],[11.57851,103.181953],[11.57915,103.183578],[11.57981,103.185051],[11.5804,103.185829],[11.58186,103.187073],[11.58236,103.187508],[11.58281,103.188171],[11.58325,103.188911],[11.58361,103.189934],[11.58373,103.193459],[11.58285,103.196899],[11.58268,103.199982],[11.58339,103.202049],[11.58439,103.203133],[11.58479,103.204308],[11.58481,103.206703],[11.58574,103.20929],[11.58657,103.21035],[11.58873,103.212334],[11.59018,103.213943],[11.5904,103.214432],[11.5906,103.21769],[11.59058,103.217781],[11.59035,103.218803],[11.5882,103.220268],[11.58678,103.221764],[11.58348,103.22261],[11.57834,103.220749],[11.57638,103.221848],[11.57541,103.223122],[11.57472,103.22464],[11.57318,103.228439],[11.57241,103.229523],[11.57052,103.231133],[11.56974,103.232101],[11.56895,103.233109],[11.5683,103.234047],[11.56771,103.234581],[11.56548,103.235992],[11.56257,103.237617],[11.56186,103.237663],[11.56118,103.237488],[11.5604,103.237297],[11.55926,103.237343],[11.55846,103.236687],[11.55735,103.234642],[11.55677,103.233994],[11.55431,103.233093],[11.55359,103.232971],[11.55289,103.233101],[11.55138,103.233681],[11.54972,103.234703],[11.54917,103.235039],[11.5485,103.235313],[11.54473,103.23539],[11.54185,103.236504],[11.54024,103.237099],[11.53936,103.237282],[11.53716,103.237579],[11.53528,103.237],[11.534,103.236366],[11.53277,103.235626],[11.53164,103.234917],[11.53099,103.234749],[11.52984,103.23455],[11.52888,103.234177],[11.52735,103.233299],[11.52659,103.232536],[11.5262,103.23188],[11.5253,103.230614],[11.52429,103.229973],[11.52392,103.229927],[11.52121,103.229973],[11.51972,103.229561],[11.51893,103.229263],[11.5182,103.229317],[11.51399,103.23159],[11.51297,103.231812],[11.51194,103.231857],[11.51011,103.23188],[11.50902,103.232224],[11.50693,103.233429],[11.50576,103.233551],[11.50494,103.233231],[11.50325,103.23259],[11.50252,103.232422],[11.50093,103.232712],[11.50011,103.232773],[11.49915,103.232857],[11.49806,103.232651],[11.49561,103.231987],[11.49041,103.228378],[11.48962,103.227768],[11.48887,103.227501],[11.48762,103.227386],[11.48165,103.227951],[11.47617,103.227783],[11.47501,103.227638],[11.47367,103.226982],[11.47107,103.225647],[11.46887,103.224922],[11.46673,103.224213],[11.46596,103.224083],[11.46513,103.224503],[11.46288,103.22673],[11.45861,103.229118],[11.45768,103.229927],[11.45594,103.235283],[11.45535,103.235847],[11.45436,103.235909],[11.45231,103.23494],[11.45074,103.234207],[11.44935,103.233437],[11.44882,103.232803],[11.4481,103.231903],[11.44777,103.231461],[11.44646,103.23069],[11.44483,103.229797],[11.44376,103.228737],[11.44315,103.22834],[11.44296,103.228027],[11.44312,103.227257],[11.44294,103.226593],[11.44219,103.225899],[11.44182,103.225731],[11.44121,103.225906],[11.44061,103.226013],[11.43851,103.225807],[11.43649,103.225662],[11.43577,103.225906],[11.43484,103.226486],[11.43371,103.22715],[11.43153,103.228653],[11.43091,103.228668],[11.43053,103.228401],[11.43026,103.22805],[11.42979,103.227699],[11.42935,103.227997],[11.42913,103.228737],[11.42871,103.229958],[11.42834,103.230888],[11.42772,103.232048],[11.42666,103.232628],[11.42512,103.231987],[11.42317,103.23111],[11.41956,103.229424],[11.41809,103.229721],[11.41689,103.230324],[11.41594,103.231331],[11.41515,103.232651],[11.41403,103.233566],[11.41247,103.233757],[11.41083,103.233849],[11.4076,103.234238],[11.40635,103.23497],[11.40458,103.235901],[11.40382,103.23703],[11.40074,103.243408],[11.39951,103.246849],[11.39861,103.247864],[11.39231,103.250717],[11.38318,103.25174],[11.38208,103.252617],[11.38027,103.256081],[11.37877,103.259323],[11.37654,103.260857],[11.37606,103.261749],[11.37449,103.264359],[11.37389,103.264664],[11.3691,103.264771],[11.36836,103.265198],[11.36669,103.267418],[11.35941,103.271683],[11.35284,103.28212],[11.34847,103.285744],[11.34724,103.286469],[11.34553,103.287643],[11.34518,103.288109],[11.34536,103.288788],[11.34643,103.289711],[11.34668,103.290863],[11.34588,103.292938],[11.34509,103.293678],[11.33875,103.295464],[11.33796,103.296097],[11.33729,103.297028],[11.33656,103.297882],[11.33186,103.300552],[11.33066,103.30188],[11.3304,103.302391],[11.33031,103.303093],[11.33047,103.305153],[11.33047,103.306183],[11.32961,103.30854],[11.32908,103.309013],[11.32749,103.309433],[11.32654,103.310249],[11.3261,103.311157],[11.32575,103.312737],[11.32507,103.31424],[11.32294,103.317398],[11.32109,103.320778],[11.32049,103.321167],[11.31987,103.321289],[11.31806,103.321457],[11.31508,103.321899],[11.31325,103.322609],[11.31258,103.322662],[11.3116,103.322113],[11.3109,103.321907],[11.30992,103.321991],[11.30893,103.32225],[11.30779,103.322746],[11.30688,103.323372],[11.3058,103.324211],[11.30497,103.324944],[11.30449,103.325333],[11.30392,103.325691],[11.30293,103.325844],[11.30268,103.325783],[11.29959,103.324966],[11.29905,103.324928],[11.2979,103.324837],[11.29723,103.324654],[11.29601,103.323753],[11.29476,103.323433],[11.29397,103.323624],[11.2925,103.324753],[11.29014,103.325653],[11.28738,103.326508],[11.28699,103.327026],[11.28605,103.32917],[11.28512,103.330017],[11.28327,103.330742],[11.28231,103.330727],[11.27854,103.329353],[11.27771,103.329453],[11.27648,103.330269],[11.27562,103.330856],[11.27447,103.331558],[11.27372,103.332024],[11.27274,103.332283],[11.27011,103.332947],[11.26775,103.333687],[11.26709,103.334099],[11.26572,103.335281],[11.26541,103.335876],[11.26491,103.337448],[11.26399,103.339478],[11.26304,103.341507],[11.26191,103.343407],[11.2606,103.345131],[11.25998,103.345482],[11.25803,103.345978],[11.25598,103.346603],[11.2535,103.347031],[11.25327,103.347191],[11.25276,103.34761],[11.25099,103.351044],[11.24909,103.354622],[11.24879,103.355293],[11.24842,103.355789],[11.24748,103.356209],[11.24567,103.356209],[11.24308,103.356209],[11.24239,103.356491],[11.24009,103.358109],[11.23948,103.358612],[11.23888,103.359482],[11.23785,103.361458],[11.23727,103.361908],[11.23649,103.362137],[11.23424,103.362457],[11.23186,103.36274],[11.23022,103.363487],[11.22925,103.363747],[11.22569,103.364067],[11.22477,103.364693],[11.22408,103.365273],[11.22289,103.366341],[11.22187,103.367439],[11.22114,103.36763],[11.22042,103.367523],[11.22021,103.367577],[11.21984,103.367989],[11.21934,103.368477],[11.21889,103.368767],[11.21749,103.369614],[11.21565,103.371063],[11.21389,103.37262],[11.21215,103.37439],[11.21129,103.375877],[11.21071,103.37722],[11.21017,103.377876],[11.20754,103.379547],[11.20646,103.380302],[11.20535,103.381142],[11.20467,103.382057],[11.20402,103.383331],[11.20299,103.385292],[11.20158,103.387016],[11.20094,103.387779],[11.19945,103.388924],[11.19743,103.390358],[11.19607,103.390877],[11.19556,103.390968],[11.19516,103.391029],[11.19458,103.391098],[11.19393,103.390984],[11.19326,103.390533],[11.19254,103.390106],[11.19202,103.389648],[11.19145,103.388702],[11.19104,103.388496],[11.19063,103.388634],[11.19037,103.389236],[11.19007,103.389633],[11.18963,103.389832],[11.1892,103.389771],[11.18897,103.389664],[11.18855,103.389473],[11.18803,103.389282],[11.1875,103.389397],[11.18686,103.390068],[11.18626,103.390823],[11.18613,103.391403],[11.18627,103.391899],[11.18647,103.392479],[11.18649,103.392998],[11.1864,103.393242],[11.18608,103.393578],[11.18541,103.393738],[11.1844,103.393951],[11.184,103.394127],[11.18359,103.394417],[11.18341,103.394943],[11.18338,103.395569],[11.18366,103.396118],[11.18396,103.396408],[11.18422,103.396881],[11.18416,103.397163],[11.18315,103.398163],[11.18271,103.399933],[11.18287,103.401947],[11.18255,103.403778],[11.18269,103.404312],[11.18305,103.404793],[11.18307,103.405411],[11.18288,103.407066],[11.183,103.407387],[11.18321,103.407898],[11.18416,103.408882],[11.18428,103.409531],[11.18365,103.410843],[11.18349,103.411758],[11.18326,103.414078],[11.18286,103.416344],[11.18285,103.420883],[11.18364,103.424301],[11.1816,103.43045],[11.18061,103.4356],[11.17133,103.445473],[11.17097,103.446518],[11.17128,103.447769],[11.17192,103.449387],[11.17298,103.450996],[11.17648,103.454811],[11.18074,103.458771],[11.18119,103.459801],[11.18182,103.464951],[11.18233,103.465736],[11.18585,103.468758],[11.18979,103.471992],[11.19473,103.474182],[11.19598,103.474953],[11.19772,103.476303],[11.19857,103.476929],[11.19942,103.477669],[11.20113,103.478958],[11.20304,103.480507],[11.20471,103.481773],[11.20656,103.483238],[11.20854,103.484772],[11.20998,103.486183],[11.21027,103.486923],[11.21045,103.487823],[11.21039,103.489372],[11.21008,103.49366],[11.20821,103.51046],[11.20727,103.51165],[11.20585,103.513023],[11.20319,103.515953],[11.20203,103.519188],[11.20101,103.522598],[11.19859,103.532829],[11.19582,103.539001],[11.19552,103.544373],[11.19414,103.549026],[11.19365,103.553429],[11.19193,103.557022],[11.19208,103.559959],[11.19363,103.562714],[11.19476,103.56871],[11.19292,103.574707],[11.19234,103.575996],[11.19049,103.579964],[11.19004,103.581207],[11.18869,103.585373],[11.18686,103.587471],[11.18619,103.589417],[11.18608,103.590813],[11.18591,103.594711],[11.18573,103.595322],[11.1852,103.595947],[11.1827,103.597633],[11.18065,103.598991],[11.1801,103.5998],[11.17972,103.600929],[11.17936,103.602127],[11.17823,103.604088],[11.1776,103.605919],[11.17711,103.607857],[11.17699,103.608253],[11.17684,103.608704],[11.17675,103.609093],[11.17663,103.609612],[11.176,103.611229],[11.17401,103.615463],[11.17314,103.619499],[11.17309,103.620338],[11.17312,103.621239],[11.17308,103.624657],[11.1727,103.631561],[11.17279,103.632179],[11.17314,103.632736],[11.17592,103.635521],[11.17691,103.636276],[11.17731,103.636833],[11.17748,103.637352],[11.1775,103.638008],[11.17767,103.639717],[11.17787,103.640297],[11.17843,103.640999],[11.17895,103.641747],[11.17928,103.642517],[11.17927,103.643646],[11.17883,103.645798],[11.17867,103.646828],[11.17881,103.648117],[11.17961,103.651459],[11.17982,103.652237],[11.18029,103.653122],[11.18186,103.654266],[11.1829,103.655678],[11.1831,103.657021],[11.18229,103.659958],[11.18197,103.661087],[11.18152,103.662033],[11.17997,103.663933],[11.17963,103.66465],[11.17872,103.666634],[11.17818,103.667557],[11.1777,103.668221],[11.17682,103.668671],[11.17575,103.669441],[11.17496,103.670227],[11.17445,103.671227],[11.17418,103.671707],[11.1741,103.673157],[11.17405,103.674454],[11.17397,103.67588],[11.17366,103.676682],[11.17308,103.677841],[11.17065,103.682823],[11.17009,103.686668],[11.16957,103.690979],[11.16915,103.692131],[11.16804,103.693398],[11.16752,103.694008],[11.16648,103.695183],[11.16421,103.697701],[11.15985,103.702187],[11.15614,103.711243],[11.15262,103.720367],[11.15229,103.72171],[11.15202,103.723969],[11.1517,103.726891],[11.15096,103.732788],[11.15073,103.733566],[11.15039,103.734428],[11.14969,103.735809],[11.1481,103.738739],[11.14768,103.74202],[11.14836,103.743347],[11.14942,103.744827],[11.15026,103.745934],[11.15069,103.74662],[11.15106,103.747192],[11.15114,103.747833],[11.15095,103.748703],[11.14987,103.750328],[11.14856,103.752373],[11.14835,103.753464],[11.14851,103.754333],[11.14922,103.756638],[11.14941,103.757294],[11.14952,103.757881],[11.14919,103.758911],[11.14651,103.76133],[11.1442,103.763733],[11.14196,103.766197],[11.13964,103.768623],[11.13886,103.769012],[11.1381,103.76931],[11.13718,103.769592],[11.13477,103.770317],[11.13238,103.771004],[11.13146,103.771141],[11.13038,103.771156],[11.12787,103.771088],[11.12668,103.77153],[11.12241,103.773743],[11.12171,103.773857],[11.12084,103.773911],[11.12001,103.773933],[11.11721,103.773972],[11.10998,103.775299],[11.10607,103.774773],[11.1045,103.775162],[11.10346,103.775337],[11.10286,103.775177],[11.1018,103.774887],[11.09952,103.775078],[11.09706,103.775284],[11.09649,103.775337],[11.09577,103.775627],[11.09525,103.776192],[11.0947,103.777184],[11.09453,103.779541],[11.09447,103.781898],[11.09466,103.783058],[11.09488,103.784233],[11.09502,103.78524],[11.09505,103.785767],[11.09496,103.786369],[11.09466,103.787041],[11.09433,103.787537],[11.09375,103.788277],[11.09328,103.789017],[11.09195,103.791183],[11.09117,103.792397],[11.09022,103.79364],[11.08845,103.796211],[11.08748,103.798477],[11.08641,103.7995],[11.08534,103.79982],[11.08406,103.799927],[11.08297,103.799973],[11.08174,103.799881],[11.07517,103.796448],[11.07028,103.795197],[11.06735,103.795021],[11.06615,103.794579],[11.06494,103.794243],[11.0645,103.794113],[11.06399,103.794029],[11.0629,103.793983],[11.06133,103.793953],[11.06056,103.793938],[11.06005,103.793953],[11.05928,103.794083],[11.05789,103.794296],[11.05707,103.794327],[11.05632,103.793892],[11.0545,103.79258],[11.05322,103.792236],[11.05209,103.792221],[11.05152,103.792267],[11.05095,103.79245],[11.04974,103.793556],[11.04763,103.795731],[11.04724,103.796448],[11.04712,103.797119],[11.04707,103.797707],[11.04714,103.798843],[11.04714,103.800903],[11.04725,103.802391],[11.04753,103.803543],[11.05113,103.81208],[11.05209,103.814003],[11.05402,103.816803],[11.05514,103.818604],[11.05573,103.820747],[11.05638,103.82383],[11.057,103.825287],[11.05763,103.826073],[11.06003,103.828537],[11.06042,103.83004],[11.06021,103.83284],[11.06045,103.833878],[11.06309,103.839684],[11.06362,103.840446],[11.07223,103.848389],[11.07265,103.849403],[11.07273,103.850739],[11.07205,103.852127],[11.07038,103.854652],[11.07001,103.856651],[11.07053,103.858231],[11.0738,103.861671],[11.07438,103.863029],[11.07604,103.867943],[11.08074,103.876663],[11.08276,103.883034],[11.08504,103.887573],[11.08747,103.891853],[11.09351,103.902863],[11.09626,103.907677],[11.09797,103.910271],[11.09986,103.912628],[11.10172,103.914497],[11.11719,103.928207],[11.12314,103.933548],[11.12609,103.937073],[11.12849,103.940979],[11.13351,103.950737],[11.13833,103.960007],[11.14351,103.970093],[11.14877,103.980263],[11.15045,103.983887],[11.15166,103.987389],[11.15335,103.990837],[11.15434,103.992569],[11.16036,104.000847],[11.1649,104.007309],[11.16648,104.00956],[11.17444,104.020821],[11.17617,104.023148],[11.17744,104.024361],[11.1804,104.026291],[11.18675,104.032623],[11.18853,104.034492],[11.18943,104.035606],[11.1903,104.037193],[11.19067,104.038139],[11.19143,104.040947],[11.19232,104.044868],[11.19301,104.049026],[11.19386,104.055923],[11.19406,104.057426],[11.19365,104.060654],[11.19418,104.071198],[11.19437,104.073151],[11.19465,104.074532],[11.19516,104.07576],[11.20094,104.086983],[11.20212,104.08889],[11.20234,104.089523],[11.20257,104.090561],[11.20284,104.091293],[11.20358,104.092796],[11.20381,104.093384],[11.20417,104.094589],[11.20428,104.095154],[11.20439,104.09597],[11.20459,104.096642],[11.20479,104.097198],[11.20496,104.097893],[11.20516,104.099487],[11.20535,104.100258],[11.20553,104.100502],[11.20604,104.10096],[11.20737,104.101891],[11.20792,104.102623],[11.20809,104.103104],[11.20937,104.108627],[11.21023,104.112587],[11.2122,104.117897],[11.21319,104.120369],[11.21763,104.127892],[11.22001,104.131653],[11.22482,104.137657],[11.2308,104.146797],[11.24009,104.161209],[11.24535,104.16938],[11.25656,104.18306],[11.26132,104.188797],[11.26612,104.195312],[11.26954,104.199753],[11.27281,104.205101],[11.27728,104.212517],[11.27887,104.215157],[11.28602,104.227188],[11.29414,104.241119],[11.30092,104.252647],[11.30841,104.265282],[11.31258,104.272278],[11.31552,104.278542],[11.31805,104.282516],[11.32065,104.286133],[11.32409,104.291763],[11.32748,104.297836],[11.33257,104.305969],[11.34071,104.319382],[11.34404,104.324768],[11.34898,104.329353],[11.35067,104.331482],[11.35595,104.340073],[11.35931,104.34671],[11.36522,104.355904],[11.36764,104.358238],[11.37237,104.362923],[11.37664,104.368263],[11.37729,104.369011],[11.38512,104.374298],[11.39029,104.38002],[11.39617,104.38681],[11.3989,104.392479],[11.4047,104.399544],[11.40971,104.409241],[11.41611,104.424797],[11.41866,104.42984],[11.42282,104.446877],[11.4267,104.457939],[11.43018,104.46505],[11.43874,104.476578],[11.44111,104.480171],[11.44412,104.485619],[11.44534,104.487007],[11.44653,104.488136],[11.4482,104.48912],[11.45309,104.491272],[11.45469,104.492531],[11.45604,104.495033],[11.4585,104.504662],[11.45999,104.51059],[11.46157,104.517471],[11.4626,104.521729],[11.46297,104.522919],[11.46348,104.523781],[11.46505,104.525787],[11.46582,104.527733],[11.46739,104.531898],[11.47216,104.544884],[11.47508,104.553177],[11.47558,104.566727],[11.47516,104.57859],[11.47593,104.584923],[11.47684,104.58889],[11.47796,104.591553],[11.4827,104.61026],[11.48373,104.615677],[11.48535,104.624268],[11.48672,104.630508],[11.48914,104.63916],[11.4909,104.647552],[11.49224,104.652893],[11.49312,104.657547],[11.49447,104.66188],[11.49498,104.663223],[11.49638,104.66687],[11.49774,104.670662],[11.49856,104.672638],[11.49964,104.676613],[11.50056,104.679749],[11.50305,104.686951],[11.50356,104.694168],[11.50428,104.699677],[11.50513,104.704674],[11.50695,104.712051],[11.50716,104.715637],[11.5071,104.724953],[11.50695,104.728851],[11.50735,104.733101],[11.50765,104.734657],[11.5088,104.738792],[11.51005,104.744072],[11.51144,104.750343],[11.51393,104.763412],[11.51486,104.767693],[11.51789,104.77317],[11.51962,104.776314],[11.52081,104.778954],[11.52391,104.790916],[11.52485,104.794319],[11.52508,104.794853],[11.52576,104.796127],[11.526,104.796539],[11.5275,104.799171],[11.52917,104.80204],[11.5295,104.802589],[11.52975,104.803032],[11.53017,104.803993],[11.53039,104.804741],[11.53051,104.805389],[11.53062,104.805977],[11.53119,104.809479],[11.53182,104.813492],[11.53254,104.81739],[11.53259,104.817734],[11.53285,104.819397],[11.53309,104.820824],[11.5333,104.822166],[11.53381,104.825127],[11.53402,104.826477],[11.53435,104.828453],[11.53438,104.828537],[11.53437,104.828773],[11.53431,104.829033],[11.5342,104.829201],[11.53414,104.829323],[11.53413,104.829643],[11.53463,104.830093],[11.53414,104.830704],[11.53351,104.831467],[11.53081,104.834793],[11.52835,104.837891],[11.52877,104.841797],[11.52904,104.844307],[11.52908,104.844551],[11.53072,104.855827],[11.53079,104.856331],[11.53114,104.858963],[11.53308,104.873177],[11.53473,104.885193],[11.53474,104.885353],[11.53458,104.885536],[11.53447,104.885757],[11.53425,104.885963],[11.53221,104.886429],[11.53208,104.886452],[11.52989,104.886871],[11.52962,104.886932],[11.52785,104.887291],[11.52576,104.887718],[11.52572,104.888298],[11.52556,104.889893],[11.52537,104.890633],[11.52427,104.894363],[11.52349,104.897171],[11.5231,104.898407],[11.52284,104.899269],[11.52256,104.9002],[11.52215,104.901703],[11.52156,104.903717],[11.52088,104.906128],[11.52042,104.907951],[11.5193,104.913322],[11.51897,104.915192],[11.51894,104.915604],[11.51896,104.916061],[11.51903,104.916496],[11.51917,104.916962],[11.51975,104.91864],[11.51983,104.918854],[11.52025,104.919617],[11.5207,104.920212],[11.52108,104.920509],[11.52147,104.920723],[11.52208,104.920898],[11.52358,104.920998],[11.52505,104.921097],[11.52677,104.921227],[11.527,104.92186],[11.52883,104.926086],[11.52992,104.928574],[11.5299,104.92897],[11.53005,104.929619],[11.5302,104.930206],[11.53026,104.930496],[11.53027,104.930717],[11.53014,104.930946],[11.5296,104.931168],[11.52902,104.931396],[11.52877,104.931587],[11.52823,104.931801],[11.52758,104.931999],[11.52638,104.932114],[11.5239,104.93235],[11.51604,104.935379],[11.51338,104.935677],[11.51252,104.935997],[11.50867,104.937866],[11.50674,104.938766],[11.50388,104.939621],[11.50249,104.940048],[11.49697,104.942436],[11.49289,104.94355],[11.49186,104.94355],[11.49092,104.943123],[11.48942,104.942436],[11.48809,104.941818],[11.48757,104.94165],[11.48726,104.941727],[11.48513,104.942841],[11.48492,104.942963],[11.48385,104.943527],[11.48288,104.944061],[11.48157,104.944771],[11.48138,104.944633],[11.48112,104.944733],[11.48108,104.945053],[11.47857,104.946381],[11.47776,104.946823],[11.47264,104.949509],[11.47149,104.950127],[11.46992,104.950981],[11.46587,104.953209],[11.46406,104.954208],[11.46098,104.955994],[11.46003,104.956543],[11.45616,104.958847],[11.45244,104.961067],[11.45039,104.962288],[11.44289,104.966873],[11.44102,104.968018],[11.43993,104.968681],[11.43116,104.973999],[11.42561,104.977943],[11.4193,104.985237],[11.40634,104.999748],[11.40146,105.004936],[11.40073,105.005623],[11.39999,105.005829],[11.39922,105.005791],[11.39655,105.005074],[11.39496,105.004761],[11.3919,105.00444],[11.38985,105.004044],[11.38363,105.001984],[11.37883,105.001343],[11.37475,105.001892],[11.37105,105.003014],[11.36419,105.000473],[11.35815,105.001381],[11.35153,105.004639],[11.34709,105.007607],[11.34363,105.010948],[11.34161,105.013443],[11.33983,105.016502],[11.33843,105.019676],[11.33641,105.022873],[11.33367,105.025948],[11.32995,105.028282]]; \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/touchzoomemu.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/touchzoomemu.html new file mode 100644 index 000000000..6402f6b2d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/touchzoomemu.html @@ -0,0 +1,193 @@ + + + + Leaflet debug page + + + + + + + + +
+
Hack1Touch
+
Hack2Touch
+
Hack3Touch
+
Hack4Touch
+
Print Buffer
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/us-states.js b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/us-states.js new file mode 100644 index 000000000..7f6af2fb3 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/us-states.js @@ -0,0 +1,54 @@ +var statesData = {"type":"FeatureCollection","features":[ +{"type":"Feature","id":"01","properties":{"name":"Alabama","density":94.65},"geometry":{"type":"Polygon","coordinates":[[[-87.359296,35.00118],[-85.606675,34.984749],[-85.431413,34.124869],[-85.184951,32.859696],[-85.069935,32.580372],[-84.960397,32.421541],[-85.004212,32.322956],[-84.889196,32.262709],[-85.058981,32.13674],[-85.053504,32.01077],[-85.141136,31.840985],[-85.042551,31.539753],[-85.113751,31.27686],[-85.004212,31.003013],[-85.497137,30.997536],[-87.600282,30.997536],[-87.633143,30.86609],[-87.408589,30.674397],[-87.446927,30.510088],[-87.37025,30.427934],[-87.518128,30.280057],[-87.655051,30.247195],[-87.90699,30.411504],[-87.934375,30.657966],[-88.011052,30.685351],[-88.10416,30.499135],[-88.137022,30.318396],[-88.394438,30.367688],[-88.471115,31.895754],[-88.241084,33.796253],[-88.098683,34.891641],[-88.202745,34.995703],[-87.359296,35.00118]]]}}, +{"type":"Feature","id":"02","properties":{"name":"Alaska","density":1.264},"geometry":{"type":"MultiPolygon","coordinates":[[[[-131.602021,55.117982],[-131.569159,55.28229],[-131.355558,55.183705],[-131.38842,55.01392],[-131.645836,55.035827],[-131.602021,55.117982]]],[[[-131.832052,55.42469],[-131.645836,55.304197],[-131.749898,55.128935],[-131.832052,55.189182],[-131.832052,55.42469]]],[[[-132.976733,56.437924],[-132.735747,56.459832],[-132.631685,56.421493],[-132.664547,56.273616],[-132.878148,56.240754],[-133.069841,56.333862],[-132.976733,56.437924]]],[[[-133.595627,56.350293],[-133.162949,56.317431],[-133.05341,56.125739],[-132.620732,55.912138],[-132.472854,55.780691],[-132.4619,55.671152],[-132.357838,55.649245],[-132.341408,55.506844],[-132.166146,55.364444],[-132.144238,55.238474],[-132.029222,55.276813],[-131.97993,55.178228],[-131.958022,54.789365],[-132.029222,54.701734],[-132.308546,54.718165],[-132.385223,54.915335],[-132.483808,54.898904],[-132.686455,55.046781],[-132.746701,54.997489],[-132.916486,55.046781],[-132.889102,54.898904],[-132.73027,54.937242],[-132.626209,54.882473],[-132.675501,54.679826],[-132.867194,54.701734],[-133.157472,54.95915],[-133.239626,55.090597],[-133.223195,55.22752],[-133.453227,55.216566],[-133.453227,55.320628],[-133.277964,55.331582],[-133.102702,55.42469],[-133.17938,55.588998],[-133.387503,55.62186],[-133.420365,55.884753],[-133.497042,56.0162],[-133.639442,55.923092],[-133.694212,56.070969],[-133.546335,56.142169],[-133.666827,56.311955],[-133.595627,56.350293]]],[[[-133.738027,55.556137],[-133.546335,55.490413],[-133.414888,55.572568],[-133.283441,55.534229],[-133.420365,55.386352],[-133.633966,55.430167],[-133.738027,55.556137]]],[[[-133.907813,56.930849],[-134.050213,57.029434],[-133.885905,57.095157],[-133.343688,57.002049],[-133.102702,57.007526],[-132.932917,56.82131],[-132.620732,56.667956],[-132.653593,56.55294],[-132.817901,56.492694],[-133.042456,56.520078],[-133.201287,56.448878],[-133.420365,56.492694],[-133.66135,56.448878],[-133.710643,56.684386],[-133.688735,56.837741],[-133.869474,56.843218],[-133.907813,56.930849]]],[[[-134.115936,56.48174],[-134.25286,56.558417],[-134.400737,56.722725],[-134.417168,56.848695],[-134.296675,56.908941],[-134.170706,56.848695],[-134.143321,56.952757],[-133.748981,56.772017],[-133.710643,56.596755],[-133.847566,56.574848],[-133.935197,56.377678],[-133.836612,56.322908],[-133.957105,56.092877],[-134.110459,56.142169],[-134.132367,55.999769],[-134.230952,56.070969],[-134.291198,56.350293],[-134.115936,56.48174]]],[[[-134.636246,56.28457],[-134.669107,56.169554],[-134.806031,56.235277],[-135.178463,56.67891],[-135.413971,56.810356],[-135.331817,56.914418],[-135.424925,57.166357],[-135.687818,57.369004],[-135.419448,57.566174],[-135.298955,57.48402],[-135.063447,57.418296],[-134.849846,57.407343],[-134.844369,57.248511],[-134.636246,56.728202],[-134.636246,56.28457]]],[[[-134.712923,58.223407],[-134.373353,58.14673],[-134.176183,58.157683],[-134.187137,58.081006],[-133.902336,57.807159],[-134.099505,57.850975],[-134.148798,57.757867],[-133.935197,57.615466],[-133.869474,57.363527],[-134.083075,57.297804],[-134.154275,57.210173],[-134.499322,57.029434],[-134.603384,57.034911],[-134.6472,57.226604],[-134.575999,57.341619],[-134.608861,57.511404],[-134.729354,57.719528],[-134.707446,57.829067],[-134.784123,58.097437],[-134.91557,58.212453],[-134.953908,58.409623],[-134.712923,58.223407]]],[[[-135.857603,57.330665],[-135.715203,57.330665],[-135.567326,57.149926],[-135.633049,57.023957],[-135.857603,56.996572],[-135.824742,57.193742],[-135.857603,57.330665]]],[[[-136.279328,58.206976],[-135.978096,58.201499],[-135.780926,58.28913],[-135.496125,58.168637],[-135.64948,58.037191],[-135.59471,57.987898],[-135.45231,58.135776],[-135.107263,58.086483],[-134.91557,57.976944],[-135.025108,57.779775],[-134.937477,57.763344],[-134.822462,57.500451],[-135.085355,57.462112],[-135.572802,57.675713],[-135.556372,57.456635],[-135.709726,57.369004],[-135.890465,57.407343],[-136.000004,57.544266],[-136.208128,57.637374],[-136.366959,57.829067],[-136.569606,57.916698],[-136.558652,58.075529],[-136.421728,58.130299],[-136.377913,58.267222],[-136.279328,58.206976]]],[[[-147.079854,60.200582],[-147.501579,59.948643],[-147.53444,59.850058],[-147.874011,59.784335],[-147.80281,59.937689],[-147.435855,60.09652],[-147.205824,60.271782],[-147.079854,60.200582]]],[[[-147.561825,60.578491],[-147.616594,60.370367],[-147.758995,60.156767],[-147.956165,60.227967],[-147.791856,60.474429],[-147.561825,60.578491]]],[[[-147.786379,70.245291],[-147.682318,70.201475],[-147.162008,70.15766],[-146.888161,70.185044],[-146.510252,70.185044],[-146.099482,70.146706],[-145.858496,70.168614],[-145.622988,70.08646],[-145.195787,69.993352],[-144.620708,69.971444],[-144.461877,70.026213],[-144.078491,70.059075],[-143.914183,70.130275],[-143.497935,70.141229],[-143.503412,70.091936],[-143.25695,70.119321],[-142.747594,70.042644],[-142.402547,69.916674],[-142.079408,69.856428],[-142.008207,69.801659],[-141.712453,69.790705],[-141.433129,69.697597],[-141.378359,69.63735],[-141.208574,69.686643],[-141.00045,69.648304],[-141.00045,60.304644],[-140.53491,60.22249],[-140.474664,60.310121],[-139.987216,60.184151],[-139.696939,60.342983],[-139.088998,60.359413],[-139.198537,60.091043],[-139.045183,59.997935],[-138.700135,59.910304],[-138.623458,59.767904],[-137.604747,59.242118],[-137.445916,58.908024],[-137.265177,59.001132],[-136.827022,59.159963],[-136.580559,59.16544],[-136.465544,59.285933],[-136.476498,59.466672],[-136.301236,59.466672],[-136.25742,59.625503],[-135.945234,59.663842],[-135.479694,59.800766],[-135.025108,59.565257],[-135.068924,59.422857],[-134.959385,59.280456],[-134.701969,59.247595],[-134.378829,59.033994],[-134.400737,58.973748],[-134.25286,58.858732],[-133.842089,58.727285],[-133.173903,58.152206],[-133.075318,57.998852],[-132.867194,57.845498],[-132.560485,57.505928],[-132.253777,57.21565],[-132.368792,57.095157],[-132.05113,57.051341],[-132.127807,56.876079],[-131.870391,56.804879],[-131.837529,56.602232],[-131.580113,56.613186],[-131.087188,56.405062],[-130.78048,56.366724],[-130.621648,56.268139],[-130.468294,56.240754],[-130.424478,56.142169],[-130.101339,56.114785],[-130.002754,55.994292],[-130.150631,55.769737],[-130.128724,55.583521],[-129.986323,55.276813],[-130.095862,55.200136],[-130.336847,54.920812],[-130.687372,54.718165],[-130.785957,54.822227],[-130.917403,54.789365],[-131.010511,54.997489],[-130.983126,55.08512],[-131.092665,55.189182],[-130.862634,55.298721],[-130.928357,55.337059],[-131.158389,55.200136],[-131.284358,55.287767],[-131.426759,55.238474],[-131.843006,55.457552],[-131.700606,55.698537],[-131.963499,55.616383],[-131.974453,55.49589],[-132.182576,55.588998],[-132.226392,55.704014],[-132.083991,55.829984],[-132.127807,55.955953],[-132.324977,55.851892],[-132.522147,56.076446],[-132.642639,56.032631],[-132.719317,56.218847],[-132.527624,56.339339],[-132.341408,56.339339],[-132.396177,56.487217],[-132.297592,56.67891],[-132.450946,56.673433],[-132.768609,56.837741],[-132.993164,57.034911],[-133.51895,57.177311],[-133.507996,57.577128],[-133.677781,57.62642],[-133.639442,57.790728],[-133.814705,57.834544],[-134.072121,58.053622],[-134.143321,58.168637],[-134.586953,58.206976],[-135.074401,58.502731],[-135.282525,59.192825],[-135.38111,59.033994],[-135.337294,58.891593],[-135.140124,58.617746],[-135.189417,58.573931],[-135.05797,58.349376],[-135.085355,58.201499],[-135.277048,58.234361],[-135.430402,58.398669],[-135.633049,58.426053],[-135.91785,58.382238],[-135.912373,58.617746],[-136.087635,58.814916],[-136.246466,58.75467],[-136.876314,58.962794],[-136.931084,58.902547],[-136.586036,58.836824],[-136.317666,58.672516],[-136.213604,58.667039],[-136.180743,58.535592],[-136.043819,58.382238],[-136.388867,58.294607],[-136.591513,58.349376],[-136.59699,58.212453],[-136.859883,58.316515],[-136.947514,58.393192],[-137.111823,58.393192],[-137.566409,58.590362],[-137.900502,58.765624],[-137.933364,58.869686],[-138.11958,59.02304],[-138.634412,59.132579],[-138.919213,59.247595],[-139.417615,59.379041],[-139.746231,59.505011],[-139.718846,59.641934],[-139.625738,59.598119],[-139.5162,59.68575],[-139.625738,59.88292],[-139.488815,59.992458],[-139.554538,60.041751],[-139.801,59.833627],[-140.315833,59.696704],[-140.92925,59.745996],[-141.444083,59.871966],[-141.46599,59.970551],[-141.706976,59.948643],[-141.964392,60.019843],[-142.539471,60.085566],[-142.873564,60.091043],[-143.623905,60.036274],[-143.892275,59.997935],[-144.231845,60.140336],[-144.65357,60.206059],[-144.785016,60.29369],[-144.834309,60.441568],[-145.124586,60.430614],[-145.223171,60.299167],[-145.738004,60.474429],[-145.820158,60.551106],[-146.351421,60.408706],[-146.608837,60.238921],[-146.718376,60.397752],[-146.608837,60.485383],[-146.455483,60.463475],[-145.951604,60.578491],[-146.017328,60.666122],[-146.252836,60.622307],[-146.345944,60.737322],[-146.565022,60.753753],[-146.784099,61.044031],[-146.866253,60.972831],[-147.172962,60.934492],[-147.271547,60.972831],[-147.375609,60.879723],[-147.758995,60.912584],[-147.775426,60.808523],[-148.032842,60.781138],[-148.153334,60.819476],[-148.065703,61.005692],[-148.175242,61.000215],[-148.350504,60.803046],[-148.109519,60.737322],[-148.087611,60.594922],[-147.939734,60.441568],[-148.027365,60.277259],[-148.219058,60.332029],[-148.273827,60.249875],[-148.087611,60.217013],[-147.983549,59.997935],[-148.251919,59.95412],[-148.399797,59.997935],[-148.635305,59.937689],[-148.755798,59.986981],[-149.067984,59.981505],[-149.05703,60.063659],[-149.204907,60.008889],[-149.287061,59.904827],[-149.418508,59.997935],[-149.582816,59.866489],[-149.511616,59.806242],[-149.741647,59.729565],[-149.949771,59.718611],[-150.031925,59.61455],[-150.25648,59.521442],[-150.409834,59.554303],[-150.579619,59.444764],[-150.716543,59.450241],[-151.001343,59.225687],[-151.308052,59.209256],[-151.406637,59.280456],[-151.592853,59.159963],[-151.976239,59.253071],[-151.888608,59.422857],[-151.636669,59.483103],[-151.47236,59.472149],[-151.423068,59.537872],[-151.127313,59.669319],[-151.116359,59.778858],[-151.505222,59.63098],[-151.828361,59.718611],[-151.8667,59.778858],[-151.702392,60.030797],[-151.423068,60.211536],[-151.379252,60.359413],[-151.297098,60.386798],[-151.264237,60.545629],[-151.406637,60.720892],[-151.06159,60.786615],[-150.404357,61.038554],[-150.245526,60.939969],[-150.042879,60.912584],[-149.741647,61.016646],[-150.075741,61.15357],[-150.207187,61.257632],[-150.47008,61.246678],[-150.656296,61.29597],[-150.711066,61.252155],[-151.023251,61.180954],[-151.165652,61.044031],[-151.477837,61.011169],[-151.800977,60.852338],[-151.833838,60.748276],[-152.080301,60.693507],[-152.13507,60.578491],[-152.310332,60.507291],[-152.392486,60.304644],[-152.732057,60.173197],[-152.567748,60.069136],[-152.704672,59.915781],[-153.022334,59.888397],[-153.049719,59.691227],[-153.345474,59.620026],[-153.438582,59.702181],[-153.586459,59.548826],[-153.761721,59.543349],[-153.72886,59.433811],[-154.117723,59.368087],[-154.1944,59.066856],[-153.750768,59.050425],[-153.400243,58.968271],[-153.301658,58.869686],[-153.444059,58.710854],[-153.679567,58.612269],[-153.898645,58.606793],[-153.920553,58.519161],[-154.062953,58.4863],[-153.99723,58.376761],[-154.145107,58.212453],[-154.46277,58.059098],[-154.643509,58.059098],[-154.818771,58.004329],[-154.988556,58.015283],[-155.120003,57.955037],[-155.081664,57.872883],[-155.328126,57.829067],[-155.377419,57.708574],[-155.547204,57.785251],[-155.73342,57.549743],[-156.045606,57.566174],[-156.023698,57.440204],[-156.209914,57.473066],[-156.34136,57.418296],[-156.34136,57.248511],[-156.549484,56.985618],[-156.883577,56.952757],[-157.157424,56.832264],[-157.20124,56.766541],[-157.376502,56.859649],[-157.672257,56.607709],[-157.754411,56.67891],[-157.918719,56.657002],[-157.957058,56.514601],[-158.126843,56.459832],[-158.32949,56.48174],[-158.488321,56.339339],[-158.208997,56.295524],[-158.510229,55.977861],[-159.375585,55.873799],[-159.616571,55.594475],[-159.676817,55.654722],[-159.643955,55.829984],[-159.813741,55.857368],[-160.027341,55.791645],[-160.060203,55.720445],[-160.394296,55.605429],[-160.536697,55.473983],[-160.580512,55.567091],[-160.668143,55.457552],[-160.865313,55.528752],[-161.232268,55.358967],[-161.506115,55.364444],[-161.467776,55.49589],[-161.588269,55.62186],[-161.697808,55.517798],[-161.686854,55.408259],[-162.053809,55.074166],[-162.179779,55.15632],[-162.218117,55.03035],[-162.470057,55.052258],[-162.508395,55.249428],[-162.661749,55.293244],[-162.716519,55.222043],[-162.579595,55.134412],[-162.645319,54.997489],[-162.847965,54.926289],[-163.00132,55.079643],[-163.187536,55.090597],[-163.220397,55.03035],[-163.034181,54.942719],[-163.373752,54.800319],[-163.14372,54.76198],[-163.138243,54.696257],[-163.329936,54.74555],[-163.587352,54.614103],[-164.085754,54.61958],[-164.332216,54.531949],[-164.354124,54.466226],[-164.638925,54.389548],[-164.847049,54.416933],[-164.918249,54.603149],[-164.710125,54.663395],[-164.551294,54.88795],[-164.34317,54.893427],[-163.894061,55.041304],[-163.532583,55.046781],[-163.39566,54.904381],[-163.291598,55.008443],[-163.313505,55.128935],[-163.105382,55.183705],[-162.880827,55.183705],[-162.579595,55.446598],[-162.245502,55.682106],[-161.807347,55.89023],[-161.292514,55.983338],[-161.078914,55.939523],[-160.87079,55.999769],[-160.816021,55.912138],[-160.931036,55.813553],[-160.805067,55.736876],[-160.766728,55.857368],[-160.509312,55.868322],[-160.438112,55.791645],[-160.27928,55.76426],[-160.273803,55.857368],[-160.536697,55.939523],[-160.558604,55.994292],[-160.383342,56.251708],[-160.147834,56.399586],[-159.830171,56.541986],[-159.326293,56.667956],[-158.959338,56.848695],[-158.784076,56.782971],[-158.641675,56.810356],[-158.701922,56.925372],[-158.658106,57.034911],[-158.378782,57.264942],[-157.995396,57.41282],[-157.688688,57.609989],[-157.705118,57.719528],[-157.458656,58.497254],[-157.07527,58.705377],[-157.119086,58.869686],[-158.039212,58.634177],[-158.32949,58.661562],[-158.40069,58.760147],[-158.564998,58.803962],[-158.619768,58.913501],[-158.767645,58.864209],[-158.860753,58.694424],[-158.701922,58.480823],[-158.893615,58.387715],[-159.0634,58.420577],[-159.392016,58.760147],[-159.616571,58.929932],[-159.731586,58.929932],[-159.808264,58.803962],[-159.906848,58.782055],[-160.054726,58.886116],[-160.235465,58.902547],[-160.317619,59.072332],[-160.854359,58.88064],[-161.33633,58.743716],[-161.374669,58.667039],[-161.752577,58.552023],[-161.938793,58.656085],[-161.769008,58.776578],[-161.829255,59.061379],[-161.955224,59.36261],[-161.703285,59.48858],[-161.911409,59.740519],[-162.092148,59.88292],[-162.234548,60.091043],[-162.448149,60.178674],[-162.502918,59.997935],[-162.760334,59.959597],[-163.171105,59.844581],[-163.66403,59.795289],[-163.9324,59.806242],[-164.162431,59.866489],[-164.189816,60.02532],[-164.386986,60.074613],[-164.699171,60.29369],[-164.962064,60.337506],[-165.268773,60.578491],[-165.060649,60.68803],[-165.016834,60.890677],[-165.175665,60.846861],[-165.197573,60.972831],[-165.120896,61.076893],[-165.323543,61.170001],[-165.34545,61.071416],[-165.591913,61.109754],[-165.624774,61.279539],[-165.816467,61.301447],[-165.920529,61.416463],[-165.915052,61.558863],[-166.106745,61.49314],[-166.139607,61.630064],[-165.904098,61.662925],[-166.095791,61.81628],[-165.756221,61.827233],[-165.756221,62.013449],[-165.674067,62.139419],[-165.044219,62.539236],[-164.912772,62.659728],[-164.819664,62.637821],[-164.874433,62.807606],[-164.633448,63.097884],[-164.425324,63.212899],[-164.036462,63.262192],[-163.73523,63.212899],[-163.313505,63.037637],[-163.039658,63.059545],[-162.661749,63.22933],[-162.272887,63.486746],[-162.075717,63.514131],[-162.026424,63.448408],[-161.555408,63.448408],[-161.13916,63.503177],[-160.766728,63.771547],[-160.766728,63.837271],[-160.952944,64.08921],[-160.974852,64.237087],[-161.26513,64.395918],[-161.374669,64.532842],[-161.078914,64.494503],[-160.79959,64.609519],[-160.783159,64.719058],[-161.144637,64.921705],[-161.413007,64.762873],[-161.664946,64.790258],[-161.900455,64.702627],[-162.168825,64.680719],[-162.234548,64.620473],[-162.541257,64.532842],[-162.634365,64.384965],[-162.787719,64.324718],[-162.858919,64.49998],[-163.045135,64.538319],[-163.176582,64.401395],[-163.253259,64.467119],[-163.598306,64.565704],[-164.304832,64.560227],[-164.80871,64.450688],[-165.000403,64.434257],[-165.411174,64.49998],[-166.188899,64.576658],[-166.391546,64.636904],[-166.484654,64.735489],[-166.413454,64.872412],[-166.692778,64.987428],[-166.638008,65.113398],[-166.462746,65.179121],[-166.517516,65.337952],[-166.796839,65.337952],[-167.026871,65.381768],[-167.47598,65.414629],[-167.711489,65.496784],[-168.072967,65.578938],[-168.105828,65.682999],[-167.541703,65.819923],[-166.829701,66.049954],[-166.3313,66.186878],[-166.046499,66.110201],[-165.756221,66.09377],[-165.690498,66.203309],[-165.86576,66.21974],[-165.88219,66.312848],[-165.186619,66.466202],[-164.403417,66.581218],[-163.981692,66.592172],[-163.751661,66.553833],[-163.872153,66.389525],[-163.828338,66.274509],[-163.915969,66.192355],[-163.768091,66.060908],[-163.494244,66.082816],[-163.149197,66.060908],[-162.749381,66.088293],[-162.634365,66.039001],[-162.371472,66.028047],[-162.14144,66.077339],[-161.840208,66.02257],[-161.549931,66.241647],[-161.341807,66.252601],[-161.199406,66.208786],[-161.128206,66.334755],[-161.528023,66.395002],[-161.911409,66.345709],[-161.87307,66.510017],[-162.174302,66.68528],[-162.502918,66.740049],[-162.601503,66.89888],[-162.344087,66.937219],[-162.015471,66.778388],[-162.075717,66.652418],[-161.916886,66.553833],[-161.571838,66.438817],[-161.489684,66.55931],[-161.884024,66.718141],[-161.714239,67.002942],[-161.851162,67.052235],[-162.240025,66.991988],[-162.639842,67.008419],[-162.700088,67.057712],[-162.902735,67.008419],[-163.740707,67.128912],[-163.757138,67.254881],[-164.009077,67.534205],[-164.211724,67.638267],[-164.534863,67.725898],[-165.192096,67.966884],[-165.493328,68.059992],[-165.794559,68.081899],[-166.243668,68.246208],[-166.681824,68.339316],[-166.703731,68.372177],[-166.375115,68.42147],[-166.227238,68.574824],[-166.216284,68.881533],[-165.329019,68.859625],[-164.255539,68.930825],[-163.976215,68.985595],[-163.532583,69.138949],[-163.110859,69.374457],[-163.023228,69.609966],[-162.842489,69.812613],[-162.470057,69.982398],[-162.311225,70.108367],[-161.851162,70.311014],[-161.779962,70.256245],[-161.396576,70.239814],[-160.837928,70.343876],[-160.487404,70.453415],[-159.649432,70.792985],[-159.33177,70.809416],[-159.298908,70.760123],[-158.975769,70.798462],[-158.658106,70.787508],[-158.033735,70.831323],[-157.420318,70.979201],[-156.812377,71.285909],[-156.565915,71.351633],[-156.522099,71.296863],[-155.585543,71.170894],[-155.508865,71.083263],[-155.832005,70.968247],[-155.979882,70.96277],[-155.974405,70.809416],[-155.503388,70.858708],[-155.476004,70.940862],[-155.262403,71.017539],[-155.191203,70.973724],[-155.032372,71.148986],[-154.566832,70.990155],[-154.643509,70.869662],[-154.353231,70.8368],[-154.183446,70.7656],[-153.931507,70.880616],[-153.487874,70.886093],[-153.235935,70.924431],[-152.589656,70.886093],[-152.26104,70.842277],[-152.419871,70.606769],[-151.817408,70.546523],[-151.773592,70.486276],[-151.187559,70.382214],[-151.182082,70.431507],[-150.760358,70.49723],[-150.355064,70.491753],[-150.349588,70.436984],[-150.114079,70.431507],[-149.867617,70.508184],[-149.462323,70.519138],[-149.177522,70.486276],[-148.78866,70.404122],[-148.607921,70.420553],[-148.350504,70.305537],[-148.202627,70.349353],[-147.961642,70.316491],[-147.786379,70.245291]]],[[[-152.94018,58.026237],[-152.945657,57.982421],[-153.290705,58.048145],[-153.044242,58.305561],[-152.819688,58.327469],[-152.666333,58.562977],[-152.496548,58.354853],[-152.354148,58.426053],[-152.080301,58.311038],[-152.080301,58.152206],[-152.480117,58.130299],[-152.655379,58.059098],[-152.94018,58.026237]]],[[[-153.958891,57.538789],[-153.67409,57.670236],[-153.931507,57.69762],[-153.936983,57.812636],[-153.723383,57.889313],[-153.570028,57.834544],[-153.548121,57.719528],[-153.46049,57.796205],[-153.455013,57.96599],[-153.268797,57.889313],[-153.235935,57.998852],[-153.071627,57.933129],[-152.874457,57.933129],[-152.721103,57.993375],[-152.469163,57.889313],[-152.469163,57.599035],[-152.151501,57.620943],[-152.359625,57.42925],[-152.74301,57.505928],[-152.60061,57.379958],[-152.710149,57.275896],[-152.907319,57.325188],[-152.912796,57.128019],[-153.214027,57.073249],[-153.312612,56.991095],[-153.498828,57.067772],[-153.695998,56.859649],[-153.849352,56.837741],[-154.013661,56.744633],[-154.073907,56.969187],[-154.303938,56.848695],[-154.314892,56.919895],[-154.523016,56.991095],[-154.539447,57.193742],[-154.742094,57.275896],[-154.627078,57.511404],[-154.227261,57.659282],[-153.980799,57.648328],[-153.958891,57.538789]]],[[[-154.53397,56.602232],[-154.742094,56.399586],[-154.807817,56.432447],[-154.53397,56.602232]]],[[[-155.634835,55.923092],[-155.476004,55.912138],[-155.530773,55.704014],[-155.793666,55.731399],[-155.837482,55.802599],[-155.634835,55.923092]]],[[[-159.890418,55.28229],[-159.950664,55.068689],[-160.257373,54.893427],[-160.109495,55.161797],[-160.005433,55.134412],[-159.890418,55.28229]]],[[[-160.520266,55.358967],[-160.33405,55.358967],[-160.339527,55.249428],[-160.525743,55.128935],[-160.690051,55.211089],[-160.794113,55.134412],[-160.854359,55.320628],[-160.79959,55.380875],[-160.520266,55.358967]]],[[[-162.256456,54.981058],[-162.234548,54.893427],[-162.349564,54.838658],[-162.437195,54.931766],[-162.256456,54.981058]]],[[[-162.415287,63.634624],[-162.563165,63.536039],[-162.612457,63.62367],[-162.415287,63.634624]]],[[[-162.80415,54.488133],[-162.590549,54.449795],[-162.612457,54.367641],[-162.782242,54.373118],[-162.80415,54.488133]]],[[[-165.548097,54.29644],[-165.476897,54.181425],[-165.630251,54.132132],[-165.685021,54.252625],[-165.548097,54.29644]]],[[[-165.73979,54.15404],[-166.046499,54.044501],[-166.112222,54.121178],[-165.980775,54.219763],[-165.73979,54.15404]]],[[[-166.364161,60.359413],[-166.13413,60.397752],[-166.084837,60.326552],[-165.88219,60.342983],[-165.685021,60.277259],[-165.646682,59.992458],[-165.750744,59.89935],[-166.00816,59.844581],[-166.062929,59.745996],[-166.440838,59.855535],[-166.6161,59.850058],[-166.994009,59.992458],[-167.125456,59.992458],[-167.344534,60.074613],[-167.421211,60.206059],[-167.311672,60.238921],[-166.93924,60.206059],[-166.763978,60.310121],[-166.577762,60.321075],[-166.495608,60.392275],[-166.364161,60.359413]]],[[[-166.375115,54.01164],[-166.210807,53.934962],[-166.5449,53.748746],[-166.539423,53.715885],[-166.117699,53.852808],[-166.112222,53.776131],[-166.282007,53.683023],[-166.555854,53.622777],[-166.583239,53.529669],[-166.878994,53.431084],[-167.13641,53.425607],[-167.306195,53.332499],[-167.623857,53.250345],[-167.793643,53.337976],[-167.459549,53.442038],[-167.355487,53.425607],[-167.103548,53.513238],[-167.163794,53.611823],[-167.021394,53.715885],[-166.807793,53.666592],[-166.785886,53.732316],[-167.015917,53.754223],[-167.141887,53.825424],[-167.032348,53.945916],[-166.643485,54.017116],[-166.561331,53.880193],[-166.375115,54.01164]]],[[[-168.790446,53.157237],[-168.40706,53.34893],[-168.385152,53.431084],[-168.237275,53.524192],[-168.007243,53.568007],[-167.886751,53.518715],[-167.842935,53.387268],[-168.270136,53.244868],[-168.500168,53.036744],[-168.686384,52.965544],[-168.790446,53.157237]]],[[[-169.74891,52.894344],[-169.705095,52.795759],[-169.962511,52.790282],[-169.989896,52.856005],[-169.74891,52.894344]]],[[[-170.148727,57.221127],[-170.28565,57.128019],[-170.313035,57.221127],[-170.148727,57.221127]]],[[[-170.669036,52.697174],[-170.603313,52.604066],[-170.789529,52.538343],[-170.816914,52.636928],[-170.669036,52.697174]]],[[[-171.742517,63.716778],[-170.94836,63.5689],[-170.488297,63.69487],[-170.280174,63.683916],[-170.093958,63.612716],[-170.044665,63.492223],[-169.644848,63.4265],[-169.518879,63.366254],[-168.99857,63.338869],[-168.686384,63.295053],[-168.856169,63.147176],[-169.108108,63.180038],[-169.376478,63.152653],[-169.513402,63.08693],[-169.639372,62.939052],[-169.831064,63.075976],[-170.055619,63.169084],[-170.263743,63.180038],[-170.362328,63.2841],[-170.866206,63.415546],[-171.101715,63.421023],[-171.463193,63.306007],[-171.73704,63.366254],[-171.852055,63.486746],[-171.742517,63.716778]]],[[[-172.432611,52.390465],[-172.41618,52.275449],[-172.607873,52.253542],[-172.569535,52.352127],[-172.432611,52.390465]]],[[[-173.626584,52.14948],[-173.495138,52.105664],[-173.122706,52.111141],[-173.106275,52.07828],[-173.549907,52.028987],[-173.626584,52.14948]]],[[[-174.322156,52.280926],[-174.327632,52.379511],[-174.185232,52.41785],[-173.982585,52.319265],[-174.059262,52.226157],[-174.179755,52.231634],[-174.141417,52.127572],[-174.333109,52.116618],[-174.738403,52.007079],[-174.968435,52.039941],[-174.902711,52.116618],[-174.656249,52.105664],[-174.322156,52.280926]]],[[[-176.469116,51.853725],[-176.288377,51.870156],[-176.288377,51.744186],[-176.518409,51.760617],[-176.80321,51.61274],[-176.912748,51.80991],[-176.792256,51.815386],[-176.775825,51.963264],[-176.627947,51.968741],[-176.627947,51.859202],[-176.469116,51.853725]]],[[[-177.153734,51.946833],[-177.044195,51.897541],[-177.120872,51.727755],[-177.274226,51.678463],[-177.279703,51.782525],[-177.153734,51.946833]]],[[[-178.123152,51.919448],[-177.953367,51.913971],[-177.800013,51.793479],[-177.964321,51.651078],[-178.123152,51.919448]]],[[[-187.107557,52.992929],[-187.293773,52.927205],[-187.304726,52.823143],[-188.90491,52.762897],[-188.642017,52.927205],[-188.642017,53.003883],[-187.107557,52.992929]]]]}}, +{"type":"Feature","id":"04","properties":{"name":"Arizona","density":57.05},"geometry":{"type":"Polygon","coordinates":[[[-109.042503,37.000263],[-109.04798,31.331629],[-111.074448,31.331629],[-112.246513,31.704061],[-114.815198,32.492741],[-114.72209,32.717295],[-114.524921,32.755634],[-114.470151,32.843265],[-114.524921,33.029481],[-114.661844,33.034958],[-114.727567,33.40739],[-114.524921,33.54979],[-114.497536,33.697668],[-114.535874,33.933176],[-114.415382,34.108438],[-114.256551,34.174162],[-114.136058,34.305608],[-114.333228,34.448009],[-114.470151,34.710902],[-114.634459,34.87521],[-114.634459,35.00118],[-114.574213,35.138103],[-114.596121,35.324319],[-114.678275,35.516012],[-114.738521,36.102045],[-114.371566,36.140383],[-114.251074,36.01989],[-114.152489,36.025367],[-114.048427,36.195153],[-114.048427,37.000263],[-110.499369,37.00574],[-109.042503,37.000263]]]}}, +{"type":"Feature","id":"05","properties":{"name":"Arkansas","density":56.43},"geometry":{"type":"Polygon","coordinates":[[[-94.473842,36.501861],[-90.152536,36.496384],[-90.064905,36.304691],[-90.218259,36.184199],[-90.377091,35.997983],[-89.730812,35.997983],[-89.763673,35.811767],[-89.911551,35.756997],[-89.944412,35.603643],[-90.130628,35.439335],[-90.114197,35.198349],[-90.212782,35.023087],[-90.311367,34.995703],[-90.251121,34.908072],[-90.409952,34.831394],[-90.481152,34.661609],[-90.585214,34.617794],[-90.568783,34.420624],[-90.749522,34.365854],[-90.744046,34.300131],[-90.952169,34.135823],[-90.891923,34.026284],[-91.072662,33.867453],[-91.231493,33.560744],[-91.056231,33.429298],[-91.143862,33.347144],[-91.089093,33.13902],[-91.16577,33.002096],[-93.608485,33.018527],[-94.041164,33.018527],[-94.041164,33.54979],[-94.183564,33.593606],[-94.380734,33.544313],[-94.484796,33.637421],[-94.430026,35.395519],[-94.616242,36.501861],[-94.473842,36.501861]]]}}, +{"type":"Feature","id":"06","properties":{"name":"California","density":241.7},"geometry":{"type":"Polygon","coordinates":[[[-123.233256,42.006186],[-122.378853,42.011663],[-121.037003,41.995232],[-120.001861,41.995232],[-119.996384,40.264519],[-120.001861,38.999346],[-118.71478,38.101128],[-117.498899,37.21934],[-116.540435,36.501861],[-115.85034,35.970598],[-114.634459,35.00118],[-114.634459,34.87521],[-114.470151,34.710902],[-114.333228,34.448009],[-114.136058,34.305608],[-114.256551,34.174162],[-114.415382,34.108438],[-114.535874,33.933176],[-114.497536,33.697668],[-114.524921,33.54979],[-114.727567,33.40739],[-114.661844,33.034958],[-114.524921,33.029481],[-114.470151,32.843265],[-114.524921,32.755634],[-114.72209,32.717295],[-116.04751,32.624187],[-117.126467,32.536556],[-117.24696,32.668003],[-117.252437,32.876127],[-117.329114,33.122589],[-117.471515,33.297851],[-117.7837,33.538836],[-118.183517,33.763391],[-118.260194,33.703145],[-118.413548,33.741483],[-118.391641,33.840068],[-118.566903,34.042715],[-118.802411,33.998899],[-119.218659,34.146777],[-119.278905,34.26727],[-119.558229,34.415147],[-119.875891,34.40967],[-120.138784,34.475393],[-120.472878,34.448009],[-120.64814,34.579455],[-120.609801,34.858779],[-120.670048,34.902595],[-120.631709,35.099764],[-120.894602,35.247642],[-120.905556,35.450289],[-121.004141,35.461243],[-121.168449,35.636505],[-121.283465,35.674843],[-121.332757,35.784382],[-121.716143,36.195153],[-121.896882,36.315645],[-121.935221,36.638785],[-121.858544,36.6114],[-121.787344,36.803093],[-121.929744,36.978355],[-122.105006,36.956447],[-122.335038,37.115279],[-122.417192,37.241248],[-122.400761,37.361741],[-122.515777,37.520572],[-122.515777,37.783465],[-122.329561,37.783465],[-122.406238,38.15042],[-122.488392,38.112082],[-122.504823,37.931343],[-122.701993,37.893004],[-122.937501,38.029928],[-122.97584,38.265436],[-123.129194,38.451652],[-123.331841,38.566668],[-123.44138,38.698114],[-123.737134,38.95553],[-123.687842,39.032208],[-123.824765,39.366301],[-123.764519,39.552517],[-123.85215,39.831841],[-124.109566,40.105688],[-124.361506,40.259042],[-124.410798,40.439781],[-124.158859,40.877937],[-124.109566,41.025814],[-124.158859,41.14083],[-124.065751,41.442061],[-124.147905,41.715908],[-124.257444,41.781632],[-124.213628,42.000709],[-123.233256,42.006186]]]}}, +{"type":"Feature","id":"08","properties":{"name":"Colorado","density":49.33},"geometry":{"type":"Polygon","coordinates":[[[-107.919731,41.003906],[-105.728954,40.998429],[-104.053011,41.003906],[-102.053927,41.003906],[-102.053927,40.001626],[-102.042974,36.994786],[-103.001438,37.000263],[-104.337812,36.994786],[-106.868158,36.994786],[-107.421329,37.000263],[-109.042503,37.000263],[-109.042503,38.166851],[-109.058934,38.27639],[-109.053457,39.125316],[-109.04798,40.998429],[-107.919731,41.003906]]]}}, +{"type":"Feature","id":"09","properties":{"name":"Connecticut","density":739.1},"geometry":{"type":"Polygon","coordinates":[[[-73.053528,42.039048],[-71.799309,42.022617],[-71.799309,42.006186],[-71.799309,41.414677],[-71.859555,41.321569],[-71.947186,41.338],[-72.385341,41.261322],[-72.905651,41.28323],[-73.130205,41.146307],[-73.371191,41.102491],[-73.655992,40.987475],[-73.727192,41.102491],[-73.48073,41.21203],[-73.55193,41.294184],[-73.486206,42.050002],[-73.053528,42.039048]]]}}, +{"type":"Feature","id":"10","properties":{"name":"Delaware","density":464.3},"geometry":{"type":"Polygon","coordinates":[[[-75.414089,39.804456],[-75.507197,39.683964],[-75.611259,39.61824],[-75.589352,39.459409],[-75.441474,39.311532],[-75.403136,39.065069],[-75.189535,38.807653],[-75.09095,38.796699],[-75.047134,38.451652],[-75.693413,38.462606],[-75.786521,39.722302],[-75.616736,39.831841],[-75.414089,39.804456]]]}}, +{"type":"Feature","id":"11","properties":{"name":"District of Columbia","density":10065},"geometry":{"type":"Polygon","coordinates":[[[-77.035264,38.993869],[-76.909294,38.895284],[-77.040741,38.791222],[-77.117418,38.933623],[-77.035264,38.993869]]]}}, +{"type":"Feature","id":"12","properties":{"name":"Florida","density":353.4},"geometry":{"type":"Polygon","coordinates":[[[-85.497137,30.997536],[-85.004212,31.003013],[-84.867289,30.712735],[-83.498053,30.647012],[-82.216449,30.570335],[-82.167157,30.356734],[-82.046664,30.362211],[-82.002849,30.564858],[-82.041187,30.751074],[-81.948079,30.827751],[-81.718048,30.745597],[-81.444201,30.707258],[-81.383954,30.27458],[-81.257985,29.787132],[-80.967707,29.14633],[-80.524075,28.461713],[-80.589798,28.41242],[-80.56789,28.094758],[-80.381674,27.738757],[-80.091397,27.021277],[-80.03115,26.796723],[-80.036627,26.566691],[-80.146166,25.739673],[-80.239274,25.723243],[-80.337859,25.465826],[-80.304997,25.383672],[-80.49669,25.197456],[-80.573367,25.241272],[-80.759583,25.164595],[-81.077246,25.120779],[-81.170354,25.224841],[-81.126538,25.378195],[-81.351093,25.821827],[-81.526355,25.903982],[-81.679709,25.843735],[-81.800202,26.090198],[-81.833064,26.292844],[-82.041187,26.517399],[-82.09048,26.665276],[-82.057618,26.878877],[-82.172634,26.917216],[-82.145249,26.791246],[-82.249311,26.758384],[-82.566974,27.300601],[-82.692943,27.437525],[-82.391711,27.837342],[-82.588881,27.815434],[-82.720328,27.689464],[-82.851774,27.886634],[-82.676512,28.434328],[-82.643651,28.888914],[-82.764143,28.998453],[-82.802482,29.14633],[-82.994175,29.179192],[-83.218729,29.420177],[-83.399469,29.518762],[-83.410422,29.66664],[-83.536392,29.721409],[-83.640454,29.885717],[-84.02384,30.104795],[-84.357933,30.055502],[-84.341502,29.902148],[-84.451041,29.929533],[-84.867289,29.743317],[-85.310921,29.699501],[-85.299967,29.80904],[-85.404029,29.940487],[-85.924338,30.236241],[-86.29677,30.362211],[-86.630863,30.395073],[-86.910187,30.373165],[-87.518128,30.280057],[-87.37025,30.427934],[-87.446927,30.510088],[-87.408589,30.674397],[-87.633143,30.86609],[-87.600282,30.997536],[-85.497137,30.997536]]]}}, +{"type":"Feature","id":"13","properties":{"name":"Georgia","density":169.5},"geometry":{"type":"Polygon","coordinates":[[[-83.109191,35.00118],[-83.322791,34.787579],[-83.339222,34.683517],[-83.005129,34.469916],[-82.901067,34.486347],[-82.747713,34.26727],[-82.714851,34.152254],[-82.55602,33.94413],[-82.325988,33.81816],[-82.194542,33.631944],[-81.926172,33.462159],[-81.937125,33.347144],[-81.761863,33.160928],[-81.493493,33.007573],[-81.42777,32.843265],[-81.416816,32.629664],[-81.279893,32.558464],[-81.121061,32.290094],[-81.115584,32.120309],[-80.885553,32.032678],[-81.132015,31.693108],[-81.175831,31.517845],[-81.279893,31.364491],[-81.290846,31.20566],[-81.400385,31.13446],[-81.444201,30.707258],[-81.718048,30.745597],[-81.948079,30.827751],[-82.041187,30.751074],[-82.002849,30.564858],[-82.046664,30.362211],[-82.167157,30.356734],[-82.216449,30.570335],[-83.498053,30.647012],[-84.867289,30.712735],[-85.004212,31.003013],[-85.113751,31.27686],[-85.042551,31.539753],[-85.141136,31.840985],[-85.053504,32.01077],[-85.058981,32.13674],[-84.889196,32.262709],[-85.004212,32.322956],[-84.960397,32.421541],[-85.069935,32.580372],[-85.184951,32.859696],[-85.431413,34.124869],[-85.606675,34.984749],[-84.319594,34.990226],[-83.618546,34.984749],[-83.109191,35.00118]]]}}, +{"type":"Feature","id":"15","properties":{"name":"Hawaii","density":214.1},"geometry":{"type":"MultiPolygon","coordinates":[[[[-155.634835,18.948267],[-155.881297,19.035898],[-155.919636,19.123529],[-155.886774,19.348084],[-156.062036,19.73147],[-155.925113,19.857439],[-155.826528,20.032702],[-155.897728,20.147717],[-155.87582,20.26821],[-155.596496,20.12581],[-155.284311,20.021748],[-155.092618,19.868393],[-155.092618,19.736947],[-154.807817,19.523346],[-154.983079,19.348084],[-155.295265,19.26593],[-155.514342,19.134483],[-155.634835,18.948267]]],[[[-156.587823,21.029505],[-156.472807,20.892581],[-156.324929,20.952827],[-156.00179,20.793996],[-156.051082,20.651596],[-156.379699,20.580396],[-156.445422,20.60778],[-156.461853,20.783042],[-156.631638,20.821381],[-156.697361,20.919966],[-156.587823,21.029505]]],[[[-156.982162,21.210244],[-157.080747,21.106182],[-157.310779,21.106182],[-157.239579,21.221198],[-156.982162,21.210244]]],[[[-157.951581,21.697691],[-157.842042,21.462183],[-157.896811,21.325259],[-158.110412,21.303352],[-158.252813,21.582676],[-158.126843,21.588153],[-157.951581,21.697691]]],[[[-159.468693,22.228955],[-159.353678,22.218001],[-159.298908,22.113939],[-159.33177,21.966061],[-159.446786,21.872953],[-159.764448,21.987969],[-159.726109,22.152277],[-159.468693,22.228955]]]]}}, +{"type":"Feature","id":"16","properties":{"name":"Idaho","density":19.15},"geometry":{"type":"Polygon","coordinates":[[[-116.04751,49.000239],[-116.04751,47.976051],[-115.724371,47.696727],[-115.718894,47.42288],[-115.527201,47.302388],[-115.324554,47.258572],[-115.302646,47.187372],[-114.930214,46.919002],[-114.886399,46.809463],[-114.623506,46.705401],[-114.612552,46.639678],[-114.322274,46.645155],[-114.464674,46.272723],[-114.492059,46.037214],[-114.387997,45.88386],[-114.568736,45.774321],[-114.497536,45.670259],[-114.546828,45.560721],[-114.333228,45.456659],[-114.086765,45.593582],[-113.98818,45.703121],[-113.807441,45.604536],[-113.834826,45.522382],[-113.736241,45.330689],[-113.571933,45.128042],[-113.45144,45.056842],[-113.456917,44.865149],[-113.341901,44.782995],[-113.133778,44.772041],[-113.002331,44.448902],[-112.887315,44.394132],[-112.783254,44.48724],[-112.471068,44.481763],[-112.241036,44.569394],[-112.104113,44.520102],[-111.868605,44.563917],[-111.819312,44.509148],[-111.616665,44.547487],[-111.386634,44.75561],[-111.227803,44.580348],[-111.047063,44.476286],[-111.047063,42.000709],[-112.164359,41.995232],[-114.04295,41.995232],[-117.027882,42.000709],[-117.027882,43.830007],[-116.896436,44.158624],[-116.97859,44.240778],[-117.170283,44.257209],[-117.241483,44.394132],[-117.038836,44.750133],[-116.934774,44.782995],[-116.830713,44.930872],[-116.847143,45.02398],[-116.732128,45.144473],[-116.671881,45.319735],[-116.463758,45.61549],[-116.545912,45.752413],[-116.78142,45.823614],[-116.918344,45.993399],[-116.92382,46.168661],[-117.055267,46.343923],[-117.038836,46.426077],[-117.044313,47.762451],[-117.033359,49.000239],[-116.04751,49.000239]]]}}, +{"type":"Feature","id":"17","properties":{"name":"Illinois","density":231.5},"geometry":{"type":"Polygon","coordinates":[[[-90.639984,42.510065],[-88.788778,42.493634],[-87.802929,42.493634],[-87.83579,42.301941],[-87.682436,42.077386],[-87.523605,41.710431],[-87.529082,39.34987],[-87.63862,39.169131],[-87.512651,38.95553],[-87.49622,38.780268],[-87.62219,38.637868],[-87.655051,38.506421],[-87.83579,38.292821],[-87.950806,38.27639],[-87.923421,38.15042],[-88.000098,38.101128],[-88.060345,37.865619],[-88.027483,37.799896],[-88.15893,37.657496],[-88.065822,37.482234],[-88.476592,37.389126],[-88.514931,37.285064],[-88.421823,37.153617],[-88.547792,37.071463],[-88.914747,37.224817],[-89.029763,37.213863],[-89.183118,37.038601],[-89.133825,36.983832],[-89.292656,36.994786],[-89.517211,37.279587],[-89.435057,37.34531],[-89.517211,37.537003],[-89.517211,37.690357],[-89.84035,37.903958],[-89.949889,37.88205],[-90.059428,38.013497],[-90.355183,38.216144],[-90.349706,38.374975],[-90.179921,38.632391],[-90.207305,38.725499],[-90.10872,38.845992],[-90.251121,38.917192],[-90.470199,38.961007],[-90.585214,38.867899],[-90.661891,38.928146],[-90.727615,39.256762],[-91.061708,39.470363],[-91.368417,39.727779],[-91.494386,40.034488],[-91.50534,40.237135],[-91.417709,40.379535],[-91.401278,40.560274],[-91.121954,40.669813],[-91.09457,40.823167],[-90.963123,40.921752],[-90.946692,41.097014],[-91.111001,41.239415],[-91.045277,41.414677],[-90.656414,41.463969],[-90.344229,41.589939],[-90.311367,41.743293],[-90.179921,41.809016],[-90.141582,42.000709],[-90.168967,42.126679],[-90.393521,42.225264],[-90.420906,42.329326],[-90.639984,42.510065]]]}}, +{"type":"Feature","id":"18","properties":{"name":"Indiana","density":181.7},"geometry":{"type":"Polygon","coordinates":[[[-85.990061,41.759724],[-84.807042,41.759724],[-84.807042,41.694001],[-84.801565,40.500028],[-84.817996,39.103408],[-84.894673,39.059592],[-84.812519,38.785745],[-84.987781,38.780268],[-85.173997,38.68716],[-85.431413,38.730976],[-85.42046,38.533806],[-85.590245,38.451652],[-85.655968,38.325682],[-85.83123,38.27639],[-85.924338,38.024451],[-86.039354,37.958727],[-86.263908,38.051835],[-86.302247,38.166851],[-86.521325,38.040881],[-86.504894,37.931343],[-86.729448,37.893004],[-86.795172,37.991589],[-87.047111,37.893004],[-87.129265,37.788942],[-87.381204,37.93682],[-87.512651,37.903958],[-87.600282,37.975158],[-87.682436,37.903958],[-87.934375,37.893004],[-88.027483,37.799896],[-88.060345,37.865619],[-88.000098,38.101128],[-87.923421,38.15042],[-87.950806,38.27639],[-87.83579,38.292821],[-87.655051,38.506421],[-87.62219,38.637868],[-87.49622,38.780268],[-87.512651,38.95553],[-87.63862,39.169131],[-87.529082,39.34987],[-87.523605,41.710431],[-87.42502,41.644708],[-87.118311,41.644708],[-86.822556,41.759724],[-85.990061,41.759724]]]}}, +{"type":"Feature","id":"19","properties":{"name":"Iowa","density":54.81},"geometry":{"type":"Polygon","coordinates":[[[-91.368417,43.501391],[-91.215062,43.501391],[-91.204109,43.353514],[-91.056231,43.254929],[-91.176724,43.134436],[-91.143862,42.909881],[-91.067185,42.75105],[-90.711184,42.636034],[-90.639984,42.510065],[-90.420906,42.329326],[-90.393521,42.225264],[-90.168967,42.126679],[-90.141582,42.000709],[-90.179921,41.809016],[-90.311367,41.743293],[-90.344229,41.589939],[-90.656414,41.463969],[-91.045277,41.414677],[-91.111001,41.239415],[-90.946692,41.097014],[-90.963123,40.921752],[-91.09457,40.823167],[-91.121954,40.669813],[-91.401278,40.560274],[-91.417709,40.379535],[-91.527248,40.412397],[-91.729895,40.615043],[-91.833957,40.609566],[-93.257961,40.582182],[-94.632673,40.571228],[-95.7664,40.587659],[-95.881416,40.719105],[-95.826646,40.976521],[-95.925231,41.201076],[-95.919754,41.453015],[-96.095016,41.540646],[-96.122401,41.67757],[-96.062155,41.798063],[-96.127878,41.973325],[-96.264801,42.039048],[-96.44554,42.488157],[-96.631756,42.707235],[-96.544125,42.855112],[-96.511264,43.052282],[-96.434587,43.123482],[-96.560556,43.222067],[-96.527695,43.397329],[-96.582464,43.479483],[-96.451017,43.501391],[-91.368417,43.501391]]]}}, +{"type":"Feature","id":"20","properties":{"name":"Kansas","density":35.09},"geometry":{"type":"Polygon","coordinates":[[[-101.90605,40.001626],[-95.306337,40.001626],[-95.207752,39.908518],[-94.884612,39.831841],[-95.109167,39.541563],[-94.983197,39.442978],[-94.824366,39.20747],[-94.610765,39.158177],[-94.616242,37.000263],[-100.087706,37.000263],[-102.042974,36.994786],[-102.053927,40.001626],[-101.90605,40.001626]]]}}, +{"type":"Feature","id":"21","properties":{"name":"Kentucky","density":110},"geometry":{"type":"Polygon","coordinates":[[[-83.903347,38.769315],[-83.678792,38.632391],[-83.519961,38.703591],[-83.142052,38.626914],[-83.032514,38.725499],[-82.890113,38.758361],[-82.846298,38.588575],[-82.731282,38.561191],[-82.594358,38.424267],[-82.621743,38.123036],[-82.50125,37.931343],[-82.342419,37.783465],[-82.293127,37.668449],[-82.101434,37.553434],[-81.969987,37.537003],[-82.353373,37.268633],[-82.720328,37.120755],[-82.720328,37.044078],[-82.868205,36.978355],[-82.879159,36.890724],[-83.070852,36.852385],[-83.136575,36.742847],[-83.673316,36.600446],[-83.689746,36.584015],[-84.544149,36.594969],[-85.289013,36.627831],[-85.486183,36.616877],[-86.592525,36.655216],[-87.852221,36.633308],[-88.071299,36.677123],[-88.054868,36.496384],[-89.298133,36.507338],[-89.418626,36.496384],[-89.363857,36.622354],[-89.215979,36.578538],[-89.133825,36.983832],[-89.183118,37.038601],[-89.029763,37.213863],[-88.914747,37.224817],[-88.547792,37.071463],[-88.421823,37.153617],[-88.514931,37.285064],[-88.476592,37.389126],[-88.065822,37.482234],[-88.15893,37.657496],[-88.027483,37.799896],[-87.934375,37.893004],[-87.682436,37.903958],[-87.600282,37.975158],[-87.512651,37.903958],[-87.381204,37.93682],[-87.129265,37.788942],[-87.047111,37.893004],[-86.795172,37.991589],[-86.729448,37.893004],[-86.504894,37.931343],[-86.521325,38.040881],[-86.302247,38.166851],[-86.263908,38.051835],[-86.039354,37.958727],[-85.924338,38.024451],[-85.83123,38.27639],[-85.655968,38.325682],[-85.590245,38.451652],[-85.42046,38.533806],[-85.431413,38.730976],[-85.173997,38.68716],[-84.987781,38.780268],[-84.812519,38.785745],[-84.894673,39.059592],[-84.817996,39.103408],[-84.43461,39.103408],[-84.231963,38.895284],[-84.215533,38.807653],[-83.903347,38.769315]]]}}, +{"type":"Feature","id":"22","properties":{"name":"Louisiana","density":105},"geometry":{"type":"Polygon","coordinates":[[[-93.608485,33.018527],[-91.16577,33.002096],[-91.072662,32.887081],[-91.143862,32.843265],[-91.154816,32.640618],[-91.006939,32.514649],[-90.985031,32.218894],[-91.105524,31.988862],[-91.341032,31.846462],[-91.401278,31.621907],[-91.499863,31.643815],[-91.516294,31.27686],[-91.636787,31.265906],[-91.565587,31.068736],[-91.636787,30.997536],[-89.747242,30.997536],[-89.845827,30.66892],[-89.681519,30.449842],[-89.643181,30.285534],[-89.522688,30.181472],[-89.818443,30.044549],[-89.84035,29.945964],[-89.599365,29.88024],[-89.495303,30.039072],[-89.287179,29.88024],[-89.30361,29.754271],[-89.424103,29.699501],[-89.648657,29.748794],[-89.621273,29.655686],[-89.69795,29.513285],[-89.506257,29.387316],[-89.199548,29.348977],[-89.09001,29.2011],[-89.002379,29.179192],[-89.16121,29.009407],[-89.336472,29.042268],[-89.484349,29.217531],[-89.851304,29.310638],[-89.851304,29.480424],[-90.032043,29.425654],[-90.021089,29.283254],[-90.103244,29.151807],[-90.23469,29.129899],[-90.333275,29.277777],[-90.563307,29.283254],[-90.645461,29.129899],[-90.798815,29.086084],[-90.963123,29.179192],[-91.09457,29.190146],[-91.220539,29.436608],[-91.445094,29.546147],[-91.532725,29.529716],[-91.620356,29.73784],[-91.883249,29.710455],[-91.888726,29.836425],[-92.146142,29.715932],[-92.113281,29.622824],[-92.31045,29.535193],[-92.617159,29.579009],[-92.97316,29.715932],[-93.2251,29.776178],[-93.767317,29.726886],[-93.838517,29.688547],[-93.926148,29.787132],[-93.690639,30.143133],[-93.767317,30.334826],[-93.696116,30.438888],[-93.728978,30.575812],[-93.630393,30.679874],[-93.526331,30.93729],[-93.542762,31.15089],[-93.816609,31.556184],[-93.822086,31.775262],[-94.041164,31.994339],[-94.041164,33.018527],[-93.608485,33.018527]]]}}, +{"type":"Feature","id":"23","properties":{"name":"Maine","density":43.04},"geometry":{"type":"Polygon","coordinates":[[[-70.703921,43.057759],[-70.824413,43.128959],[-70.807983,43.227544],[-70.966814,43.34256],[-71.032537,44.657025],[-71.08183,45.303304],[-70.649151,45.440228],[-70.720352,45.511428],[-70.556043,45.664782],[-70.386258,45.735983],[-70.41912,45.796229],[-70.260289,45.889337],[-70.309581,46.064599],[-70.210996,46.327492],[-70.057642,46.415123],[-69.997395,46.694447],[-69.225147,47.461219],[-69.044408,47.428357],[-69.033454,47.242141],[-68.902007,47.176418],[-68.578868,47.285957],[-68.376221,47.285957],[-68.233821,47.357157],[-67.954497,47.198326],[-67.790188,47.066879],[-67.779235,45.944106],[-67.801142,45.675736],[-67.456095,45.604536],[-67.505388,45.48952],[-67.417757,45.379982],[-67.488957,45.281397],[-67.346556,45.128042],[-67.16034,45.160904],[-66.979601,44.804903],[-67.187725,44.646072],[-67.308218,44.706318],[-67.406803,44.596779],[-67.549203,44.624164],[-67.565634,44.531056],[-67.75185,44.54201],[-68.047605,44.328409],[-68.118805,44.476286],[-68.222867,44.48724],[-68.173574,44.328409],[-68.403606,44.251732],[-68.458375,44.377701],[-68.567914,44.311978],[-68.82533,44.311978],[-68.830807,44.459856],[-68.984161,44.426994],[-68.956777,44.322932],[-69.099177,44.103854],[-69.071793,44.043608],[-69.258008,43.923115],[-69.444224,43.966931],[-69.553763,43.840961],[-69.707118,43.82453],[-69.833087,43.720469],[-69.986442,43.742376],[-70.030257,43.851915],[-70.254812,43.676653],[-70.194565,43.567114],[-70.358873,43.528776],[-70.369827,43.435668],[-70.556043,43.320652],[-70.703921,43.057759]]]}}, +{"type":"Feature","id":"24","properties":{"name":"Maryland","density":596.3},"geometry":{"type":"MultiPolygon","coordinates":[[[[-75.994645,37.95325],[-76.016553,37.95325],[-76.043938,37.95325],[-75.994645,37.95325]]],[[[-79.477979,39.722302],[-75.786521,39.722302],[-75.693413,38.462606],[-75.047134,38.451652],[-75.244304,38.029928],[-75.397659,38.013497],[-75.671506,37.95325],[-75.885106,37.909435],[-75.879629,38.073743],[-75.961783,38.139466],[-75.846768,38.210667],[-76.000122,38.374975],[-76.049415,38.303775],[-76.257538,38.320205],[-76.328738,38.500944],[-76.263015,38.500944],[-76.257538,38.736453],[-76.191815,38.829561],[-76.279446,39.147223],[-76.169907,39.333439],[-76.000122,39.366301],[-75.972737,39.557994],[-76.098707,39.536086],[-76.104184,39.437501],[-76.367077,39.311532],[-76.443754,39.196516],[-76.460185,38.906238],[-76.55877,38.769315],[-76.514954,38.539283],[-76.383508,38.380452],[-76.399939,38.259959],[-76.317785,38.139466],[-76.3616,38.057312],[-76.591632,38.216144],[-76.920248,38.292821],[-77.018833,38.446175],[-77.205049,38.358544],[-77.276249,38.479037],[-77.128372,38.632391],[-77.040741,38.791222],[-76.909294,38.895284],[-77.035264,38.993869],[-77.117418,38.933623],[-77.248864,39.026731],[-77.456988,39.076023],[-77.456988,39.223901],[-77.566527,39.306055],[-77.719881,39.322485],[-77.834897,39.601809],[-78.004682,39.601809],[-78.174467,39.694917],[-78.267575,39.61824],[-78.431884,39.623717],[-78.470222,39.514178],[-78.765977,39.585379],[-78.963147,39.437501],[-79.094593,39.470363],[-79.291763,39.300578],[-79.488933,39.20747],[-79.477979,39.722302]]]]}}, +{"type":"Feature","id":"25","properties":{"name":"Massachusetts","density":840.2},"geometry":{"type":"Polygon","coordinates":[[[-70.917521,42.887974],[-70.818936,42.871543],[-70.780598,42.696281],[-70.824413,42.55388],[-70.983245,42.422434],[-70.988722,42.269079],[-70.769644,42.247172],[-70.638197,42.08834],[-70.660105,41.962371],[-70.550566,41.929509],[-70.539613,41.814493],[-70.260289,41.715908],[-69.937149,41.809016],[-70.008349,41.672093],[-70.484843,41.5516],[-70.660105,41.546123],[-70.764167,41.639231],[-70.928475,41.611847],[-70.933952,41.540646],[-71.120168,41.496831],[-71.196845,41.67757],[-71.22423,41.710431],[-71.328292,41.781632],[-71.383061,42.01714],[-71.530939,42.01714],[-71.799309,42.006186],[-71.799309,42.022617],[-73.053528,42.039048],[-73.486206,42.050002],[-73.508114,42.08834],[-73.267129,42.745573],[-72.456542,42.729142],[-71.29543,42.696281],[-71.185891,42.789389],[-70.917521,42.887974]]]}}, +{"type":"Feature","id":"26","properties":{"name":"Michigan","density":173.9},"geometry":{"type":"MultiPolygon","coordinates":[[[[-83.454238,41.732339],[-84.807042,41.694001],[-84.807042,41.759724],[-85.990061,41.759724],[-86.822556,41.759724],[-86.619909,41.891171],[-86.482986,42.115725],[-86.357016,42.252649],[-86.263908,42.444341],[-86.209139,42.718189],[-86.231047,43.013943],[-86.526801,43.594499],[-86.433693,43.813577],[-86.499417,44.07647],[-86.269385,44.34484],[-86.220093,44.569394],[-86.252954,44.689887],[-86.088646,44.73918],[-86.066738,44.903488],[-85.809322,44.947303],[-85.612152,45.128042],[-85.628583,44.766564],[-85.524521,44.750133],[-85.393075,44.930872],[-85.387598,45.237581],[-85.305444,45.314258],[-85.031597,45.363551],[-85.119228,45.577151],[-84.938489,45.75789],[-84.713934,45.768844],[-84.461995,45.653829],[-84.215533,45.637398],[-84.09504,45.494997],[-83.908824,45.484043],[-83.596638,45.352597],[-83.4871,45.358074],[-83.317314,45.144473],[-83.454238,45.029457],[-83.322791,44.88158],[-83.273499,44.711795],[-83.333745,44.339363],[-83.536392,44.246255],[-83.585684,44.054562],[-83.82667,43.988839],[-83.958116,43.758807],[-83.908824,43.671176],[-83.667839,43.589022],[-83.481623,43.714992],[-83.262545,43.972408],[-82.917498,44.070993],[-82.747713,43.994316],[-82.643651,43.851915],[-82.539589,43.435668],[-82.523158,43.227544],[-82.413619,42.975605],[-82.517681,42.614127],[-82.681989,42.559357],[-82.687466,42.690804],[-82.797005,42.652465],[-82.922975,42.351234],[-83.125621,42.236218],[-83.185868,42.006186],[-83.437807,41.814493],[-83.454238,41.732339]]],[[[-85.508091,45.730506],[-85.49166,45.610013],[-85.623106,45.588105],[-85.568337,45.75789],[-85.508091,45.730506]]],[[[-87.589328,45.095181],[-87.742682,45.199243],[-87.649574,45.341643],[-87.885083,45.363551],[-87.791975,45.500474],[-87.781021,45.675736],[-87.989145,45.796229],[-88.10416,45.922199],[-88.531362,46.020784],[-88.662808,45.987922],[-89.09001,46.135799],[-90.119674,46.338446],[-90.229213,46.508231],[-90.415429,46.568478],[-90.026566,46.672539],[-89.851304,46.793032],[-89.413149,46.842325],[-89.128348,46.990202],[-88.996902,46.995679],[-88.887363,47.099741],[-88.575177,47.247618],[-88.416346,47.373588],[-88.180837,47.455742],[-87.956283,47.384542],[-88.350623,47.077833],[-88.443731,46.973771],[-88.438254,46.787555],[-88.246561,46.929956],[-87.901513,46.908048],[-87.633143,46.809463],[-87.392158,46.535616],[-87.260711,46.486323],[-87.008772,46.530139],[-86.948526,46.469893],[-86.696587,46.437031],[-86.159846,46.667063],[-85.880522,46.68897],[-85.508091,46.678016],[-85.256151,46.754694],[-85.064458,46.760171],[-85.02612,46.480847],[-84.82895,46.442508],[-84.63178,46.486323],[-84.549626,46.4206],[-84.418179,46.502754],[-84.127902,46.530139],[-84.122425,46.179615],[-83.990978,46.031737],[-83.793808,45.993399],[-83.7719,46.091984],[-83.580208,46.091984],[-83.476146,45.987922],[-83.563777,45.911245],[-84.111471,45.976968],[-84.374364,45.933153],[-84.659165,46.053645],[-84.741319,45.944106],[-84.70298,45.850998],[-84.82895,45.872906],[-85.015166,46.00983],[-85.338305,46.091984],[-85.502614,46.097461],[-85.661445,45.966014],[-85.924338,45.933153],[-86.209139,45.960537],[-86.324155,45.905768],[-86.351539,45.796229],[-86.663725,45.703121],[-86.647294,45.834568],[-86.784218,45.861952],[-86.838987,45.725029],[-87.069019,45.719552],[-87.17308,45.659305],[-87.326435,45.423797],[-87.611236,45.122565],[-87.589328,45.095181]]],[[[-88.805209,47.976051],[-89.057148,47.850082],[-89.188594,47.833651],[-89.177641,47.937713],[-88.547792,48.173221],[-88.668285,48.008913],[-88.805209,47.976051]]]]}}, +{"type":"Feature","id":"27","properties":{"name":"Minnesota","density":67.14},"geometry":{"type":"Polygon","coordinates":[[[-92.014696,46.705401],[-92.091373,46.749217],[-92.29402,46.667063],[-92.29402,46.075553],[-92.354266,46.015307],[-92.639067,45.933153],[-92.869098,45.719552],[-92.885529,45.577151],[-92.770513,45.566198],[-92.644544,45.440228],[-92.75956,45.286874],[-92.737652,45.117088],[-92.808852,44.750133],[-92.545959,44.569394],[-92.337835,44.552964],[-92.233773,44.443425],[-91.927065,44.333886],[-91.877772,44.202439],[-91.592971,44.032654],[-91.43414,43.994316],[-91.242447,43.775238],[-91.269832,43.616407],[-91.215062,43.501391],[-91.368417,43.501391],[-96.451017,43.501391],[-96.451017,45.297827],[-96.681049,45.412843],[-96.856311,45.604536],[-96.582464,45.818137],[-96.560556,45.933153],[-96.598895,46.332969],[-96.719387,46.437031],[-96.801542,46.656109],[-96.785111,46.924479],[-96.823449,46.968294],[-96.856311,47.609096],[-97.053481,47.948667],[-97.130158,48.140359],[-97.16302,48.545653],[-97.097296,48.682577],[-97.228743,49.000239],[-95.152983,49.000239],[-95.152983,49.383625],[-94.955813,49.372671],[-94.824366,49.295994],[-94.69292,48.775685],[-94.588858,48.715438],[-94.260241,48.699007],[-94.221903,48.649715],[-93.838517,48.627807],[-93.794701,48.518268],[-93.466085,48.545653],[-93.466085,48.589469],[-93.208669,48.644238],[-92.984114,48.62233],[-92.726698,48.540176],[-92.655498,48.436114],[-92.50762,48.447068],[-92.370697,48.222514],[-92.304974,48.315622],[-92.053034,48.359437],[-92.009219,48.266329],[-91.713464,48.200606],[-91.713464,48.112975],[-91.565587,48.041775],[-91.264355,48.080113],[-91.083616,48.178698],[-90.837154,48.238944],[-90.749522,48.091067],[-90.579737,48.123929],[-90.377091,48.091067],[-90.141582,48.112975],[-89.873212,47.987005],[-89.615796,48.008913],[-89.637704,47.954144],[-89.971797,47.828174],[-90.437337,47.729589],[-90.738569,47.625527],[-91.171247,47.368111],[-91.357463,47.20928],[-91.642264,47.028541],[-92.091373,46.787555],[-92.014696,46.705401]]]}}, +{"type":"Feature","id":"28","properties":{"name":"Mississippi","density":63.50},"geometry":{"type":"Polygon","coordinates":[[[-88.471115,34.995703],[-88.202745,34.995703],[-88.098683,34.891641],[-88.241084,33.796253],[-88.471115,31.895754],[-88.394438,30.367688],[-88.503977,30.323872],[-88.744962,30.34578],[-88.843547,30.411504],[-89.084533,30.367688],[-89.418626,30.252672],[-89.522688,30.181472],[-89.643181,30.285534],[-89.681519,30.449842],[-89.845827,30.66892],[-89.747242,30.997536],[-91.636787,30.997536],[-91.565587,31.068736],[-91.636787,31.265906],[-91.516294,31.27686],[-91.499863,31.643815],[-91.401278,31.621907],[-91.341032,31.846462],[-91.105524,31.988862],[-90.985031,32.218894],[-91.006939,32.514649],[-91.154816,32.640618],[-91.143862,32.843265],[-91.072662,32.887081],[-91.16577,33.002096],[-91.089093,33.13902],[-91.143862,33.347144],[-91.056231,33.429298],[-91.231493,33.560744],[-91.072662,33.867453],[-90.891923,34.026284],[-90.952169,34.135823],[-90.744046,34.300131],[-90.749522,34.365854],[-90.568783,34.420624],[-90.585214,34.617794],[-90.481152,34.661609],[-90.409952,34.831394],[-90.251121,34.908072],[-90.311367,34.995703],[-88.471115,34.995703]]]}}, +{"type":"Feature","id":"29","properties":{"name":"Missouri","density":87.26},"geometry":{"type":"Polygon","coordinates":[[[-91.833957,40.609566],[-91.729895,40.615043],[-91.527248,40.412397],[-91.417709,40.379535],[-91.50534,40.237135],[-91.494386,40.034488],[-91.368417,39.727779],[-91.061708,39.470363],[-90.727615,39.256762],[-90.661891,38.928146],[-90.585214,38.867899],[-90.470199,38.961007],[-90.251121,38.917192],[-90.10872,38.845992],[-90.207305,38.725499],[-90.179921,38.632391],[-90.349706,38.374975],[-90.355183,38.216144],[-90.059428,38.013497],[-89.949889,37.88205],[-89.84035,37.903958],[-89.517211,37.690357],[-89.517211,37.537003],[-89.435057,37.34531],[-89.517211,37.279587],[-89.292656,36.994786],[-89.133825,36.983832],[-89.215979,36.578538],[-89.363857,36.622354],[-89.418626,36.496384],[-89.484349,36.496384],[-89.539119,36.496384],[-89.533642,36.249922],[-89.730812,35.997983],[-90.377091,35.997983],[-90.218259,36.184199],[-90.064905,36.304691],[-90.152536,36.496384],[-94.473842,36.501861],[-94.616242,36.501861],[-94.616242,37.000263],[-94.610765,39.158177],[-94.824366,39.20747],[-94.983197,39.442978],[-95.109167,39.541563],[-94.884612,39.831841],[-95.207752,39.908518],[-95.306337,40.001626],[-95.552799,40.264519],[-95.7664,40.587659],[-94.632673,40.571228],[-93.257961,40.582182],[-91.833957,40.609566]]]}}, +{"type":"Feature","id":"30","properties":{"name":"Montana","density":6.858},"geometry":{"type":"Polygon","coordinates":[[[-104.047534,49.000239],[-104.042057,47.861036],[-104.047534,45.944106],[-104.042057,44.996596],[-104.058488,44.996596],[-105.91517,45.002073],[-109.080842,45.002073],[-111.05254,45.002073],[-111.047063,44.476286],[-111.227803,44.580348],[-111.386634,44.75561],[-111.616665,44.547487],[-111.819312,44.509148],[-111.868605,44.563917],[-112.104113,44.520102],[-112.241036,44.569394],[-112.471068,44.481763],[-112.783254,44.48724],[-112.887315,44.394132],[-113.002331,44.448902],[-113.133778,44.772041],[-113.341901,44.782995],[-113.456917,44.865149],[-113.45144,45.056842],[-113.571933,45.128042],[-113.736241,45.330689],[-113.834826,45.522382],[-113.807441,45.604536],[-113.98818,45.703121],[-114.086765,45.593582],[-114.333228,45.456659],[-114.546828,45.560721],[-114.497536,45.670259],[-114.568736,45.774321],[-114.387997,45.88386],[-114.492059,46.037214],[-114.464674,46.272723],[-114.322274,46.645155],[-114.612552,46.639678],[-114.623506,46.705401],[-114.886399,46.809463],[-114.930214,46.919002],[-115.302646,47.187372],[-115.324554,47.258572],[-115.527201,47.302388],[-115.718894,47.42288],[-115.724371,47.696727],[-116.04751,47.976051],[-116.04751,49.000239],[-111.50165,48.994762],[-109.453274,49.000239],[-104.047534,49.000239]]]}}, +{"type":"Feature","id":"31","properties":{"name":"Nebraska","density":23.97},"geometry":{"type":"Polygon","coordinates":[[[-103.324578,43.002989],[-101.626726,42.997512],[-98.499393,42.997512],[-98.466531,42.94822],[-97.951699,42.767481],[-97.831206,42.866066],[-97.688806,42.844158],[-97.217789,42.844158],[-96.692003,42.657942],[-96.626279,42.515542],[-96.44554,42.488157],[-96.264801,42.039048],[-96.127878,41.973325],[-96.062155,41.798063],[-96.122401,41.67757],[-96.095016,41.540646],[-95.919754,41.453015],[-95.925231,41.201076],[-95.826646,40.976521],[-95.881416,40.719105],[-95.7664,40.587659],[-95.552799,40.264519],[-95.306337,40.001626],[-101.90605,40.001626],[-102.053927,40.001626],[-102.053927,41.003906],[-104.053011,41.003906],[-104.053011,43.002989],[-103.324578,43.002989]]]}}, +{"type":"Feature","id":"32","properties":{"name":"Nevada","density":24.80},"geometry":{"type":"Polygon","coordinates":[[[-117.027882,42.000709],[-114.04295,41.995232],[-114.048427,37.000263],[-114.048427,36.195153],[-114.152489,36.025367],[-114.251074,36.01989],[-114.371566,36.140383],[-114.738521,36.102045],[-114.678275,35.516012],[-114.596121,35.324319],[-114.574213,35.138103],[-114.634459,35.00118],[-115.85034,35.970598],[-116.540435,36.501861],[-117.498899,37.21934],[-118.71478,38.101128],[-120.001861,38.999346],[-119.996384,40.264519],[-120.001861,41.995232],[-118.698349,41.989755],[-117.027882,42.000709]]]}}, +{"type":"Feature","id":"33","properties":{"name":"New Hampshire","density":147},"geometry":{"type":"Polygon","coordinates":[[[-71.08183,45.303304],[-71.032537,44.657025],[-70.966814,43.34256],[-70.807983,43.227544],[-70.824413,43.128959],[-70.703921,43.057759],[-70.818936,42.871543],[-70.917521,42.887974],[-71.185891,42.789389],[-71.29543,42.696281],[-72.456542,42.729142],[-72.544173,42.80582],[-72.533219,42.953697],[-72.445588,43.008466],[-72.456542,43.150867],[-72.379864,43.572591],[-72.204602,43.769761],[-72.116971,43.994316],[-72.02934,44.07647],[-72.034817,44.322932],[-71.700724,44.41604],[-71.536416,44.585825],[-71.629524,44.750133],[-71.4926,44.914442],[-71.503554,45.013027],[-71.361154,45.270443],[-71.131122,45.243058],[-71.08183,45.303304]]]}}, +{"type":"Feature","id":"34","properties":{"name":"New Jersey","density":1189 },"geometry":{"type":"Polygon","coordinates":[[[-74.236547,41.14083],[-73.902454,40.998429],[-74.022947,40.708151],[-74.187255,40.642428],[-74.274886,40.489074],[-74.001039,40.412397],[-73.979131,40.297381],[-74.099624,39.760641],[-74.411809,39.360824],[-74.614456,39.245808],[-74.795195,38.993869],[-74.888303,39.158177],[-75.178581,39.240331],[-75.534582,39.459409],[-75.55649,39.607286],[-75.561967,39.629194],[-75.507197,39.683964],[-75.414089,39.804456],[-75.145719,39.88661],[-75.129289,39.963288],[-74.82258,40.127596],[-74.773287,40.215227],[-75.058088,40.417874],[-75.069042,40.543843],[-75.195012,40.576705],[-75.205966,40.691721],[-75.052611,40.866983],[-75.134765,40.971045],[-74.882826,41.179168],[-74.828057,41.288707],[-74.69661,41.359907],[-74.236547,41.14083]]]}}, +{"type":"Feature","id":"35","properties":{"name":"New Mexico","density":17.16},"geometry":{"type":"Polygon","coordinates":[[[-107.421329,37.000263],[-106.868158,36.994786],[-104.337812,36.994786],[-103.001438,37.000263],[-103.001438,36.501861],[-103.039777,36.501861],[-103.045254,34.01533],[-103.067161,33.002096],[-103.067161,31.999816],[-106.616219,31.999816],[-106.643603,31.901231],[-106.528588,31.786216],[-108.210008,31.786216],[-108.210008,31.331629],[-109.04798,31.331629],[-109.042503,37.000263],[-107.421329,37.000263]]]}}, +{"type":"Feature","id":"36","properties":{"name":"New York","density":412.3},"geometry":{"type":"Polygon","coordinates":[[[-73.343806,45.013027],[-73.332852,44.804903],[-73.387622,44.618687],[-73.294514,44.437948],[-73.321898,44.246255],[-73.436914,44.043608],[-73.349283,43.769761],[-73.404052,43.687607],[-73.245221,43.523299],[-73.278083,42.833204],[-73.267129,42.745573],[-73.508114,42.08834],[-73.486206,42.050002],[-73.55193,41.294184],[-73.48073,41.21203],[-73.727192,41.102491],[-73.655992,40.987475],[-73.22879,40.905321],[-73.141159,40.965568],[-72.774204,40.965568],[-72.587988,40.998429],[-72.28128,41.157261],[-72.259372,41.042245],[-72.100541,40.992952],[-72.467496,40.845075],[-73.239744,40.625997],[-73.562884,40.582182],[-73.776484,40.593136],[-73.935316,40.543843],[-74.022947,40.708151],[-73.902454,40.998429],[-74.236547,41.14083],[-74.69661,41.359907],[-74.740426,41.431108],[-74.89378,41.436584],[-75.074519,41.60637],[-75.052611,41.754247],[-75.173104,41.869263],[-75.249781,41.863786],[-75.35932,42.000709],[-79.76278,42.000709],[-79.76278,42.252649],[-79.76278,42.269079],[-79.149363,42.55388],[-79.050778,42.690804],[-78.853608,42.783912],[-78.930285,42.953697],[-79.012439,42.986559],[-79.072686,43.260406],[-78.486653,43.375421],[-77.966344,43.369944],[-77.75822,43.34256],[-77.533665,43.233021],[-77.391265,43.276836],[-76.958587,43.271359],[-76.695693,43.34256],[-76.41637,43.523299],[-76.235631,43.528776],[-76.230154,43.802623],[-76.137046,43.961454],[-76.3616,44.070993],[-76.312308,44.196962],[-75.912491,44.366748],[-75.764614,44.514625],[-75.282643,44.848718],[-74.828057,45.018503],[-74.148916,44.991119],[-73.343806,45.013027]]]}}, +{"type":"Feature","id":"37","properties":{"name":"North Carolina","density":198.2},"geometry":{"type":"Polygon","coordinates":[[[-80.978661,36.562108],[-80.294043,36.545677],[-79.510841,36.5402],[-75.868676,36.551154],[-75.75366,36.151337],[-76.032984,36.189676],[-76.071322,36.140383],[-76.410893,36.080137],[-76.460185,36.025367],[-76.68474,36.008937],[-76.673786,35.937736],[-76.399939,35.987029],[-76.3616,35.943213],[-76.060368,35.992506],[-75.961783,35.899398],[-75.781044,35.937736],[-75.715321,35.696751],[-75.775568,35.581735],[-75.89606,35.570781],[-76.147999,35.324319],[-76.482093,35.313365],[-76.536862,35.14358],[-76.394462,34.973795],[-76.279446,34.940933],[-76.493047,34.661609],[-76.673786,34.694471],[-76.991448,34.667086],[-77.210526,34.60684],[-77.555573,34.415147],[-77.82942,34.163208],[-77.971821,33.845545],[-78.179944,33.916745],[-78.541422,33.851022],[-79.675149,34.80401],[-80.797922,34.820441],[-80.781491,34.935456],[-80.934845,35.105241],[-81.038907,35.044995],[-81.044384,35.149057],[-82.276696,35.198349],[-82.550543,35.160011],[-82.764143,35.066903],[-83.109191,35.00118],[-83.618546,34.984749],[-84.319594,34.990226],[-84.29221,35.225734],[-84.09504,35.247642],[-84.018363,35.41195],[-83.7719,35.559827],[-83.498053,35.565304],[-83.251591,35.718659],[-82.994175,35.773428],[-82.775097,35.997983],[-82.638174,36.063706],[-82.610789,35.965121],[-82.216449,36.156814],[-82.03571,36.118475],[-81.909741,36.304691],[-81.723525,36.353984],[-81.679709,36.589492],[-80.978661,36.562108]]]}}, +{"type":"Feature","id":"38","properties":{"name":"North Dakota","density":9.916},"geometry":{"type":"Polygon","coordinates":[[[-97.228743,49.000239],[-97.097296,48.682577],[-97.16302,48.545653],[-97.130158,48.140359],[-97.053481,47.948667],[-96.856311,47.609096],[-96.823449,46.968294],[-96.785111,46.924479],[-96.801542,46.656109],[-96.719387,46.437031],[-96.598895,46.332969],[-96.560556,45.933153],[-104.047534,45.944106],[-104.042057,47.861036],[-104.047534,49.000239],[-97.228743,49.000239]]]}}, +{"type":"Feature","id":"39","properties":{"name":"Ohio","density":281.9},"geometry":{"type":"Polygon","coordinates":[[[-80.518598,41.978802],[-80.518598,40.636951],[-80.666475,40.582182],[-80.595275,40.472643],[-80.600752,40.319289],[-80.737675,40.078303],[-80.830783,39.711348],[-81.219646,39.388209],[-81.345616,39.344393],[-81.455155,39.410117],[-81.57017,39.267716],[-81.685186,39.273193],[-81.811156,39.0815],[-81.783771,38.966484],[-81.887833,38.873376],[-82.03571,39.026731],[-82.221926,38.785745],[-82.172634,38.632391],[-82.293127,38.577622],[-82.331465,38.446175],[-82.594358,38.424267],[-82.731282,38.561191],[-82.846298,38.588575],[-82.890113,38.758361],[-83.032514,38.725499],[-83.142052,38.626914],[-83.519961,38.703591],[-83.678792,38.632391],[-83.903347,38.769315],[-84.215533,38.807653],[-84.231963,38.895284],[-84.43461,39.103408],[-84.817996,39.103408],[-84.801565,40.500028],[-84.807042,41.694001],[-83.454238,41.732339],[-83.065375,41.595416],[-82.933929,41.513262],[-82.835344,41.589939],[-82.616266,41.431108],[-82.479343,41.381815],[-82.013803,41.513262],[-81.739956,41.485877],[-81.444201,41.672093],[-81.011523,41.852832],[-80.518598,41.978802],[-80.518598,41.978802]]]}}, +{"type":"Feature","id":"40","properties":{"name":"Oklahoma","density":55.22},"geometry":{"type":"Polygon","coordinates":[[[-100.087706,37.000263],[-94.616242,37.000263],[-94.616242,36.501861],[-94.430026,35.395519],[-94.484796,33.637421],[-94.868182,33.74696],[-94.966767,33.861976],[-95.224183,33.960561],[-95.289906,33.87293],[-95.547322,33.878407],[-95.602092,33.933176],[-95.8376,33.834591],[-95.936185,33.889361],[-96.149786,33.840068],[-96.346956,33.686714],[-96.423633,33.774345],[-96.631756,33.845545],[-96.850834,33.845545],[-96.922034,33.960561],[-97.173974,33.736006],[-97.256128,33.861976],[-97.371143,33.823637],[-97.458774,33.905791],[-97.694283,33.982469],[-97.869545,33.851022],[-97.946222,33.987946],[-98.088623,34.004376],[-98.170777,34.113915],[-98.36247,34.157731],[-98.488439,34.064623],[-98.570593,34.146777],[-98.767763,34.135823],[-98.986841,34.223454],[-99.189488,34.2125],[-99.260688,34.404193],[-99.57835,34.415147],[-99.698843,34.382285],[-99.923398,34.573978],[-100.000075,34.563024],[-100.000075,36.501861],[-101.812942,36.501861],[-103.001438,36.501861],[-103.001438,37.000263],[-102.042974,36.994786],[-100.087706,37.000263]]]}}, +{"type":"Feature","id":"41","properties":{"name":"Oregon","density":40.33},"geometry":{"type":"Polygon","coordinates":[[[-123.211348,46.174138],[-123.11824,46.185092],[-122.904639,46.08103],[-122.811531,45.960537],[-122.762239,45.659305],[-122.247407,45.549767],[-121.809251,45.708598],[-121.535404,45.725029],[-121.217742,45.670259],[-121.18488,45.604536],[-120.637186,45.746937],[-120.505739,45.697644],[-120.209985,45.725029],[-119.963522,45.823614],[-119.525367,45.911245],[-119.125551,45.933153],[-118.988627,45.998876],[-116.918344,45.993399],[-116.78142,45.823614],[-116.545912,45.752413],[-116.463758,45.61549],[-116.671881,45.319735],[-116.732128,45.144473],[-116.847143,45.02398],[-116.830713,44.930872],[-116.934774,44.782995],[-117.038836,44.750133],[-117.241483,44.394132],[-117.170283,44.257209],[-116.97859,44.240778],[-116.896436,44.158624],[-117.027882,43.830007],[-117.027882,42.000709],[-118.698349,41.989755],[-120.001861,41.995232],[-121.037003,41.995232],[-122.378853,42.011663],[-123.233256,42.006186],[-124.213628,42.000709],[-124.356029,42.115725],[-124.432706,42.438865],[-124.416275,42.663419],[-124.553198,42.838681],[-124.454613,43.002989],[-124.383413,43.271359],[-124.235536,43.55616],[-124.169813,43.8081],[-124.060274,44.657025],[-124.076705,44.772041],[-123.97812,45.144473],[-123.939781,45.659305],[-123.994551,45.944106],[-123.945258,46.113892],[-123.545441,46.261769],[-123.370179,46.146753],[-123.211348,46.174138]]]}}, +{"type":"Feature","id":"42","properties":{"name":"Pennsylvania","density":284.3},"geometry":{"type":"Polygon","coordinates":[[[-79.76278,42.252649],[-79.76278,42.000709],[-75.35932,42.000709],[-75.249781,41.863786],[-75.173104,41.869263],[-75.052611,41.754247],[-75.074519,41.60637],[-74.89378,41.436584],[-74.740426,41.431108],[-74.69661,41.359907],[-74.828057,41.288707],[-74.882826,41.179168],[-75.134765,40.971045],[-75.052611,40.866983],[-75.205966,40.691721],[-75.195012,40.576705],[-75.069042,40.543843],[-75.058088,40.417874],[-74.773287,40.215227],[-74.82258,40.127596],[-75.129289,39.963288],[-75.145719,39.88661],[-75.414089,39.804456],[-75.616736,39.831841],[-75.786521,39.722302],[-79.477979,39.722302],[-80.518598,39.722302],[-80.518598,40.636951],[-80.518598,41.978802],[-80.518598,41.978802],[-80.332382,42.033571],[-79.76278,42.269079],[-79.76278,42.252649]]]}}, +{"type":"Feature","id":"44","properties":{"name":"Rhode Island","density":1006 },"geometry":{"type":"MultiPolygon","coordinates":[[[[-71.196845,41.67757],[-71.120168,41.496831],[-71.317338,41.474923],[-71.196845,41.67757]]],[[[-71.530939,42.01714],[-71.383061,42.01714],[-71.328292,41.781632],[-71.22423,41.710431],[-71.344723,41.726862],[-71.448785,41.578985],[-71.481646,41.370861],[-71.859555,41.321569],[-71.799309,41.414677],[-71.799309,42.006186],[-71.530939,42.01714]]]]}}, +{"type":"Feature","id":"45","properties":{"name":"South Carolina","density":155.4},"geometry":{"type":"Polygon","coordinates":[[[-82.764143,35.066903],[-82.550543,35.160011],[-82.276696,35.198349],[-81.044384,35.149057],[-81.038907,35.044995],[-80.934845,35.105241],[-80.781491,34.935456],[-80.797922,34.820441],[-79.675149,34.80401],[-78.541422,33.851022],[-78.716684,33.80173],[-78.935762,33.637421],[-79.149363,33.380005],[-79.187701,33.171881],[-79.357487,33.007573],[-79.582041,33.007573],[-79.631334,32.887081],[-79.866842,32.755634],[-79.998289,32.613234],[-80.206412,32.552987],[-80.430967,32.399633],[-80.452875,32.328433],[-80.660998,32.246279],[-80.885553,32.032678],[-81.115584,32.120309],[-81.121061,32.290094],[-81.279893,32.558464],[-81.416816,32.629664],[-81.42777,32.843265],[-81.493493,33.007573],[-81.761863,33.160928],[-81.937125,33.347144],[-81.926172,33.462159],[-82.194542,33.631944],[-82.325988,33.81816],[-82.55602,33.94413],[-82.714851,34.152254],[-82.747713,34.26727],[-82.901067,34.486347],[-83.005129,34.469916],[-83.339222,34.683517],[-83.322791,34.787579],[-83.109191,35.00118],[-82.764143,35.066903]]]}}, +{"type":"Feature","id":"46","properties":{"name":"South Dakota","density":98.07},"geometry":{"type":"Polygon","coordinates":[[[-104.047534,45.944106],[-96.560556,45.933153],[-96.582464,45.818137],[-96.856311,45.604536],[-96.681049,45.412843],[-96.451017,45.297827],[-96.451017,43.501391],[-96.582464,43.479483],[-96.527695,43.397329],[-96.560556,43.222067],[-96.434587,43.123482],[-96.511264,43.052282],[-96.544125,42.855112],[-96.631756,42.707235],[-96.44554,42.488157],[-96.626279,42.515542],[-96.692003,42.657942],[-97.217789,42.844158],[-97.688806,42.844158],[-97.831206,42.866066],[-97.951699,42.767481],[-98.466531,42.94822],[-98.499393,42.997512],[-101.626726,42.997512],[-103.324578,43.002989],[-104.053011,43.002989],[-104.058488,44.996596],[-104.042057,44.996596],[-104.047534,45.944106]]]}}, +{"type":"Feature","id":"47","properties":{"name":"Tennessee","density":88.08},"geometry":{"type":"Polygon","coordinates":[[[-88.054868,36.496384],[-88.071299,36.677123],[-87.852221,36.633308],[-86.592525,36.655216],[-85.486183,36.616877],[-85.289013,36.627831],[-84.544149,36.594969],[-83.689746,36.584015],[-83.673316,36.600446],[-81.679709,36.589492],[-81.723525,36.353984],[-81.909741,36.304691],[-82.03571,36.118475],[-82.216449,36.156814],[-82.610789,35.965121],[-82.638174,36.063706],[-82.775097,35.997983],[-82.994175,35.773428],[-83.251591,35.718659],[-83.498053,35.565304],[-83.7719,35.559827],[-84.018363,35.41195],[-84.09504,35.247642],[-84.29221,35.225734],[-84.319594,34.990226],[-85.606675,34.984749],[-87.359296,35.00118],[-88.202745,34.995703],[-88.471115,34.995703],[-90.311367,34.995703],[-90.212782,35.023087],[-90.114197,35.198349],[-90.130628,35.439335],[-89.944412,35.603643],[-89.911551,35.756997],[-89.763673,35.811767],[-89.730812,35.997983],[-89.533642,36.249922],[-89.539119,36.496384],[-89.484349,36.496384],[-89.418626,36.496384],[-89.298133,36.507338],[-88.054868,36.496384]]]}}, +{"type":"Feature","id":"48","properties":{"name":"Texas","density":98.07},"geometry":{"type":"Polygon","coordinates":[[[-101.812942,36.501861],[-100.000075,36.501861],[-100.000075,34.563024],[-99.923398,34.573978],[-99.698843,34.382285],[-99.57835,34.415147],[-99.260688,34.404193],[-99.189488,34.2125],[-98.986841,34.223454],[-98.767763,34.135823],[-98.570593,34.146777],[-98.488439,34.064623],[-98.36247,34.157731],[-98.170777,34.113915],[-98.088623,34.004376],[-97.946222,33.987946],[-97.869545,33.851022],[-97.694283,33.982469],[-97.458774,33.905791],[-97.371143,33.823637],[-97.256128,33.861976],[-97.173974,33.736006],[-96.922034,33.960561],[-96.850834,33.845545],[-96.631756,33.845545],[-96.423633,33.774345],[-96.346956,33.686714],[-96.149786,33.840068],[-95.936185,33.889361],[-95.8376,33.834591],[-95.602092,33.933176],[-95.547322,33.878407],[-95.289906,33.87293],[-95.224183,33.960561],[-94.966767,33.861976],[-94.868182,33.74696],[-94.484796,33.637421],[-94.380734,33.544313],[-94.183564,33.593606],[-94.041164,33.54979],[-94.041164,33.018527],[-94.041164,31.994339],[-93.822086,31.775262],[-93.816609,31.556184],[-93.542762,31.15089],[-93.526331,30.93729],[-93.630393,30.679874],[-93.728978,30.575812],[-93.696116,30.438888],[-93.767317,30.334826],[-93.690639,30.143133],[-93.926148,29.787132],[-93.838517,29.688547],[-94.002825,29.68307],[-94.523134,29.546147],[-94.70935,29.622824],[-94.742212,29.787132],[-94.873659,29.672117],[-94.966767,29.699501],[-95.016059,29.557101],[-94.911997,29.496854],[-94.895566,29.310638],[-95.081782,29.113469],[-95.383014,28.867006],[-95.985477,28.604113],[-96.045724,28.647929],[-96.226463,28.582205],[-96.23194,28.642452],[-96.478402,28.598636],[-96.593418,28.724606],[-96.664618,28.697221],[-96.401725,28.439805],[-96.593418,28.357651],[-96.774157,28.406943],[-96.801542,28.226204],[-97.026096,28.039988],[-97.256128,27.694941],[-97.404005,27.333463],[-97.513544,27.360848],[-97.540929,27.229401],[-97.425913,27.262263],[-97.480682,26.99937],[-97.557359,26.988416],[-97.562836,26.840538],[-97.469728,26.758384],[-97.442344,26.457153],[-97.332805,26.353091],[-97.30542,26.161398],[-97.217789,25.991613],[-97.524498,25.887551],[-97.650467,26.018997],[-97.885976,26.06829],[-98.198161,26.057336],[-98.466531,26.221644],[-98.669178,26.238075],[-98.822533,26.369522],[-99.030656,26.413337],[-99.173057,26.539307],[-99.266165,26.840538],[-99.446904,27.021277],[-99.424996,27.174632],[-99.50715,27.33894],[-99.479765,27.48134],[-99.605735,27.640172],[-99.709797,27.656603],[-99.879582,27.799003],[-99.934351,27.979742],[-100.082229,28.14405],[-100.29583,28.280974],[-100.399891,28.582205],[-100.498476,28.66436],[-100.629923,28.905345],[-100.673738,29.102515],[-100.799708,29.244915],[-101.013309,29.370885],[-101.062601,29.458516],[-101.259771,29.535193],[-101.413125,29.754271],[-101.851281,29.803563],[-102.114174,29.792609],[-102.338728,29.869286],[-102.388021,29.765225],[-102.629006,29.732363],[-102.809745,29.524239],[-102.919284,29.190146],[-102.97953,29.184669],[-103.116454,28.987499],[-103.280762,28.982022],[-103.527224,29.135376],[-104.146119,29.381839],[-104.266611,29.513285],[-104.507597,29.639255],[-104.677382,29.924056],[-104.688336,30.181472],[-104.858121,30.389596],[-104.896459,30.570335],[-105.005998,30.685351],[-105.394861,30.855136],[-105.602985,31.085167],[-105.77277,31.167321],[-105.953509,31.364491],[-106.205448,31.468553],[-106.38071,31.731446],[-106.528588,31.786216],[-106.643603,31.901231],[-106.616219,31.999816],[-103.067161,31.999816],[-103.067161,33.002096],[-103.045254,34.01533],[-103.039777,36.501861],[-103.001438,36.501861],[-101.812942,36.501861]]]}}, +{"type":"Feature","id":"49","properties":{"name":"Utah","density":34.30},"geometry":{"type":"Polygon","coordinates":[[[-112.164359,41.995232],[-111.047063,42.000709],[-111.047063,40.998429],[-109.04798,40.998429],[-109.053457,39.125316],[-109.058934,38.27639],[-109.042503,38.166851],[-109.042503,37.000263],[-110.499369,37.00574],[-114.048427,37.000263],[-114.04295,41.995232],[-112.164359,41.995232]]]}}, +{"type":"Feature","id":"50","properties":{"name":"Vermont","density":67.73},"geometry":{"type":"Polygon","coordinates":[[[-71.503554,45.013027],[-71.4926,44.914442],[-71.629524,44.750133],[-71.536416,44.585825],[-71.700724,44.41604],[-72.034817,44.322932],[-72.02934,44.07647],[-72.116971,43.994316],[-72.204602,43.769761],[-72.379864,43.572591],[-72.456542,43.150867],[-72.445588,43.008466],[-72.533219,42.953697],[-72.544173,42.80582],[-72.456542,42.729142],[-73.267129,42.745573],[-73.278083,42.833204],[-73.245221,43.523299],[-73.404052,43.687607],[-73.349283,43.769761],[-73.436914,44.043608],[-73.321898,44.246255],[-73.294514,44.437948],[-73.387622,44.618687],[-73.332852,44.804903],[-73.343806,45.013027],[-72.308664,45.002073],[-71.503554,45.013027]]]}}, +{"type":"Feature","id":"51","properties":{"name":"Virginia","density":204.5},"geometry":{"type":"MultiPolygon","coordinates":[[[[-75.397659,38.013497],[-75.244304,38.029928],[-75.375751,37.860142],[-75.512674,37.799896],[-75.594828,37.569865],[-75.802952,37.197433],[-75.972737,37.120755],[-76.027507,37.257679],[-75.939876,37.564388],[-75.671506,37.95325],[-75.397659,38.013497]]],[[[-76.016553,37.95325],[-75.994645,37.95325],[-76.043938,37.95325],[-76.016553,37.95325]]],[[[-78.349729,39.464886],[-77.82942,39.130793],[-77.719881,39.322485],[-77.566527,39.306055],[-77.456988,39.223901],[-77.456988,39.076023],[-77.248864,39.026731],[-77.117418,38.933623],[-77.040741,38.791222],[-77.128372,38.632391],[-77.248864,38.588575],[-77.325542,38.446175],[-77.281726,38.342113],[-77.013356,38.374975],[-76.964064,38.216144],[-76.613539,38.15042],[-76.514954,38.024451],[-76.235631,37.887527],[-76.3616,37.608203],[-76.246584,37.389126],[-76.383508,37.285064],[-76.399939,37.159094],[-76.273969,37.082417],[-76.410893,36.961924],[-76.619016,37.120755],[-76.668309,37.065986],[-76.48757,36.95097],[-75.994645,36.923586],[-75.868676,36.551154],[-79.510841,36.5402],[-80.294043,36.545677],[-80.978661,36.562108],[-81.679709,36.589492],[-83.673316,36.600446],[-83.136575,36.742847],[-83.070852,36.852385],[-82.879159,36.890724],[-82.868205,36.978355],[-82.720328,37.044078],[-82.720328,37.120755],[-82.353373,37.268633],[-81.969987,37.537003],[-81.986418,37.454849],[-81.849494,37.285064],[-81.679709,37.20291],[-81.55374,37.208387],[-81.362047,37.339833],[-81.225123,37.235771],[-80.967707,37.290541],[-80.513121,37.482234],[-80.474782,37.421987],[-80.29952,37.509618],[-80.294043,37.690357],[-80.184505,37.849189],[-79.998289,37.997066],[-79.921611,38.177805],[-79.724442,38.364021],[-79.647764,38.594052],[-79.477979,38.457129],[-79.313671,38.413313],[-79.209609,38.495467],[-78.996008,38.851469],[-78.870039,38.763838],[-78.404499,39.169131],[-78.349729,39.464886]]]]}}, +{"type":"Feature","id":"53","properties":{"name":"Washington","density":102.6},"geometry":{"type":"MultiPolygon","coordinates":[[[[-117.033359,49.000239],[-117.044313,47.762451],[-117.038836,46.426077],[-117.055267,46.343923],[-116.92382,46.168661],[-116.918344,45.993399],[-118.988627,45.998876],[-119.125551,45.933153],[-119.525367,45.911245],[-119.963522,45.823614],[-120.209985,45.725029],[-120.505739,45.697644],[-120.637186,45.746937],[-121.18488,45.604536],[-121.217742,45.670259],[-121.535404,45.725029],[-121.809251,45.708598],[-122.247407,45.549767],[-122.762239,45.659305],[-122.811531,45.960537],[-122.904639,46.08103],[-123.11824,46.185092],[-123.211348,46.174138],[-123.370179,46.146753],[-123.545441,46.261769],[-123.72618,46.300108],[-123.874058,46.239861],[-124.065751,46.327492],[-124.027412,46.464416],[-123.895966,46.535616],[-124.098612,46.74374],[-124.235536,47.285957],[-124.31769,47.357157],[-124.427229,47.740543],[-124.624399,47.88842],[-124.706553,48.184175],[-124.597014,48.381345],[-124.394367,48.288237],[-123.983597,48.162267],[-123.704273,48.167744],[-123.424949,48.118452],[-123.162056,48.167744],[-123.036086,48.080113],[-122.800578,48.08559],[-122.636269,47.866512],[-122.515777,47.882943],[-122.493869,47.587189],[-122.422669,47.318818],[-122.324084,47.346203],[-122.422669,47.576235],[-122.395284,47.800789],[-122.230976,48.030821],[-122.362422,48.123929],[-122.373376,48.288237],[-122.471961,48.468976],[-122.422669,48.600422],[-122.488392,48.753777],[-122.647223,48.775685],[-122.795101,48.8907],[-122.756762,49.000239],[-117.033359,49.000239]]],[[[-122.718423,48.310145],[-122.586977,48.35396],[-122.608885,48.151313],[-122.767716,48.227991],[-122.718423,48.310145]]],[[[-123.025132,48.583992],[-122.915593,48.715438],[-122.767716,48.556607],[-122.811531,48.419683],[-123.041563,48.458022],[-123.025132,48.583992]]]]}}, +{"type":"Feature","id":"54","properties":{"name":"West Virginia","density":77.06},"geometry":{"type":"Polygon","coordinates":[[[-80.518598,40.636951],[-80.518598,39.722302],[-79.477979,39.722302],[-79.488933,39.20747],[-79.291763,39.300578],[-79.094593,39.470363],[-78.963147,39.437501],[-78.765977,39.585379],[-78.470222,39.514178],[-78.431884,39.623717],[-78.267575,39.61824],[-78.174467,39.694917],[-78.004682,39.601809],[-77.834897,39.601809],[-77.719881,39.322485],[-77.82942,39.130793],[-78.349729,39.464886],[-78.404499,39.169131],[-78.870039,38.763838],[-78.996008,38.851469],[-79.209609,38.495467],[-79.313671,38.413313],[-79.477979,38.457129],[-79.647764,38.594052],[-79.724442,38.364021],[-79.921611,38.177805],[-79.998289,37.997066],[-80.184505,37.849189],[-80.294043,37.690357],[-80.29952,37.509618],[-80.474782,37.421987],[-80.513121,37.482234],[-80.967707,37.290541],[-81.225123,37.235771],[-81.362047,37.339833],[-81.55374,37.208387],[-81.679709,37.20291],[-81.849494,37.285064],[-81.986418,37.454849],[-81.969987,37.537003],[-82.101434,37.553434],[-82.293127,37.668449],[-82.342419,37.783465],[-82.50125,37.931343],[-82.621743,38.123036],[-82.594358,38.424267],[-82.331465,38.446175],[-82.293127,38.577622],[-82.172634,38.632391],[-82.221926,38.785745],[-82.03571,39.026731],[-81.887833,38.873376],[-81.783771,38.966484],[-81.811156,39.0815],[-81.685186,39.273193],[-81.57017,39.267716],[-81.455155,39.410117],[-81.345616,39.344393],[-81.219646,39.388209],[-80.830783,39.711348],[-80.737675,40.078303],[-80.600752,40.319289],[-80.595275,40.472643],[-80.666475,40.582182],[-80.518598,40.636951]]]}}, +{"type":"Feature","id":"55","properties":{"name":"Wisconsin","density":105.2},"geometry":{"type":"Polygon","coordinates":[[[-90.415429,46.568478],[-90.229213,46.508231],[-90.119674,46.338446],[-89.09001,46.135799],[-88.662808,45.987922],[-88.531362,46.020784],[-88.10416,45.922199],[-87.989145,45.796229],[-87.781021,45.675736],[-87.791975,45.500474],[-87.885083,45.363551],[-87.649574,45.341643],[-87.742682,45.199243],[-87.589328,45.095181],[-87.627666,44.974688],[-87.819359,44.95278],[-87.983668,44.722749],[-88.043914,44.563917],[-87.928898,44.536533],[-87.775544,44.640595],[-87.611236,44.837764],[-87.403112,44.914442],[-87.238804,45.166381],[-87.03068,45.22115],[-87.047111,45.089704],[-87.189511,44.969211],[-87.468835,44.552964],[-87.545512,44.322932],[-87.540035,44.158624],[-87.644097,44.103854],[-87.737205,43.8793],[-87.704344,43.687607],[-87.791975,43.561637],[-87.912467,43.249452],[-87.885083,43.002989],[-87.76459,42.783912],[-87.802929,42.493634],[-88.788778,42.493634],[-90.639984,42.510065],[-90.711184,42.636034],[-91.067185,42.75105],[-91.143862,42.909881],[-91.176724,43.134436],[-91.056231,43.254929],[-91.204109,43.353514],[-91.215062,43.501391],[-91.269832,43.616407],[-91.242447,43.775238],[-91.43414,43.994316],[-91.592971,44.032654],[-91.877772,44.202439],[-91.927065,44.333886],[-92.233773,44.443425],[-92.337835,44.552964],[-92.545959,44.569394],[-92.808852,44.750133],[-92.737652,45.117088],[-92.75956,45.286874],[-92.644544,45.440228],[-92.770513,45.566198],[-92.885529,45.577151],[-92.869098,45.719552],[-92.639067,45.933153],[-92.354266,46.015307],[-92.29402,46.075553],[-92.29402,46.667063],[-92.091373,46.749217],[-92.014696,46.705401],[-91.790141,46.694447],[-91.09457,46.864232],[-90.837154,46.95734],[-90.749522,46.88614],[-90.886446,46.754694],[-90.55783,46.584908],[-90.415429,46.568478]]]}}, +{"type":"Feature","id":"56","properties":{"name":"Wyoming","density":5.851},"geometry":{"type":"Polygon","coordinates":[[[-109.080842,45.002073],[-105.91517,45.002073],[-104.058488,44.996596],[-104.053011,43.002989],[-104.053011,41.003906],[-105.728954,40.998429],[-107.919731,41.003906],[-109.04798,40.998429],[-111.047063,40.998429],[-111.047063,42.000709],[-111.047063,44.476286],[-111.05254,45.002073],[-109.080842,45.002073]]]}}, +{"type":"Feature","id":"72","properties":{"name":"Puerto Rico","density":1082 },"geometry":{"type":"Polygon","coordinates":[[[-66.448338,17.984326],[-66.771478,18.006234],[-66.924832,17.929556],[-66.985078,17.973372],[-67.209633,17.956941],[-67.154863,18.19245],[-67.269879,18.362235],[-67.094617,18.515589],[-66.957694,18.488204],[-66.409999,18.488204],[-65.840398,18.433435],[-65.632274,18.367712],[-65.626797,18.203403],[-65.730859,18.186973],[-65.834921,18.017187],[-66.234737,17.929556],[-66.448338,17.984326]]]}} +]}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-bounds.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-bounds.html new file mode 100644 index 000000000..3984a6944 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-bounds.html @@ -0,0 +1,69 @@ + + + + Leaflet debug page + + + + + + + + +
+ + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-canvas.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-canvas.html new file mode 100644 index 000000000..16e1be79a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-canvas.html @@ -0,0 +1,105 @@ + + + + Leaflet debug page + + + + + + + + +
+ + + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-mobile.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-mobile.html new file mode 100644 index 000000000..66385d458 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-mobile.html @@ -0,0 +1,38 @@ + + + + Leaflet debug page + + + + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-simple.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-simple.html new file mode 100644 index 000000000..6bb4280f2 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector-simple.html @@ -0,0 +1,43 @@ + + + + Leaflet debug page + + + + + + + + + + +
+ + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector.html new file mode 100644 index 000000000..5b953c14c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector.html @@ -0,0 +1,37 @@ + + + + Leaflet debug page + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector2.html b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector2.html new file mode 100644 index 000000000..2050f2a2a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/debug/vector/vector2.html @@ -0,0 +1,60 @@ + + + + Leaflet debug page + + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/layers-2x.png b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/layers-2x.png new file mode 100644 index 000000000..200c333dc Binary files /dev/null and b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/layers-2x.png differ diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/layers.png b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/layers.png new file mode 100644 index 000000000..1a72e5784 Binary files /dev/null and b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/layers.png differ diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-icon-2x.png b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-icon-2x.png new file mode 100644 index 000000000..88f9e5018 Binary files /dev/null and b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-icon-2x.png differ diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-icon.png b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-icon.png new file mode 100644 index 000000000..950edf246 Binary files /dev/null and b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-icon.png differ diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-shadow.png b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-shadow.png new file mode 100644 index 000000000..9fd297953 Binary files /dev/null and b/vendor/assets/javascripts/Leaflet-1.4.0/dist/images/marker-shadow.png differ diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/dist/leaflet.css b/vendor/assets/javascripts/Leaflet-1.4.0/dist/leaflet.css new file mode 100644 index 000000000..a0932d57a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/dist/leaflet.css @@ -0,0 +1,635 @@ +/* required styles */ + +.leaflet-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-container, +.leaflet-pane > svg, +.leaflet-pane > canvas, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ +.leaflet-safari .leaflet-tile { + image-rendering: -webkit-optimize-contrast; + } +/* hack that prevents hw layers "stretching" when loading new tiles */ +.leaflet-safari .leaflet-tile-container { + width: 1600px; + height: 1600px; + -webkit-transform-origin: 0 0; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container .leaflet-overlay-pane svg, +.leaflet-container .leaflet-marker-pane img, +.leaflet-container .leaflet-shadow-pane img, +.leaflet-container .leaflet-tile-pane img, +.leaflet-container img.leaflet-image-layer, +.leaflet-container .leaflet-tile { + max-width: none !important; + max-height: none !important; + } + +.leaflet-container.leaflet-touch-zoom { + -ms-touch-action: pan-x pan-y; + touch-action: pan-x pan-y; + } +.leaflet-container.leaflet-touch-drag { + -ms-touch-action: pinch-zoom; + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} +.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { + -ms-touch-action: none; + touch-action: none; +} +.leaflet-container { + -webkit-tap-highlight-color: transparent; +} +.leaflet-container a { + -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); +} +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 800; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-pane { z-index: 400; } + +.leaflet-tile-pane { z-index: 200; } +.leaflet-overlay-pane { z-index: 400; } +.leaflet-shadow-pane { z-index: 500; } +.leaflet-marker-pane { z-index: 600; } +.leaflet-tooltip-pane { z-index: 650; } +.leaflet-popup-pane { z-index: 700; } + +.leaflet-map-pane canvas { z-index: 100; } +.leaflet-map-pane svg { z-index: 200; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 800; + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile { + will-change: opacity; + } +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } +.leaflet-zoom-animated { + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + will-change: transform; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile { + -webkit-transition: none; + -moz-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-interactive { + cursor: pointer; + } +.leaflet-grab { + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; + } +.leaflet-crosshair, +.leaflet-crosshair .leaflet-interactive { + cursor: crosshair; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-grab, +.leaflet-dragging .leaflet-grab .leaflet-interactive, +.leaflet-dragging .leaflet-marker-draggable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing; + } + +/* marker & overlays interactivity */ +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-image-layer, +.leaflet-pane > svg path, +.leaflet-tile-container { + pointer-events: none; + } + +.leaflet-marker-icon.leaflet-interactive, +.leaflet-image-layer.leaflet-interactive, +.leaflet-pane > svg path.leaflet-interactive { + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; + } +.leaflet-container a { + color: #0078A8; + } +.leaflet-container a.leaflet-active { + outline: 2px solid orange; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } +.leaflet-touch .leaflet-bar a:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } +.leaflet-touch .leaflet-bar a:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } + +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { + font-size: 22px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-scrollbar { + overflow-y: scroll; + overflow-x: hidden; + padding-right: 5px; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + +/* Default icon URLs */ +.leaflet-default-icon-path { + background-image: url(images/marker-icon.png); + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover { + text-decoration: underline; + } +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: border-box; + box-sizing: border-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + margin-bottom: 20px; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; + } +.leaflet-popup-content p { + margin: 18px 0; + } +.leaflet-popup-tip-container { + width: 40px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -20px; + overflow: hidden; + pointer-events: none; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + color: #333; + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + border: none; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #c3c3c3; + text-decoration: none; + font-weight: bold; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover { + color: #999; + } +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } + + +/* Tooltip */ +/* Base styles for the element that has a tooltip */ +.leaflet-tooltip { + position: absolute; + padding: 6px; + background-color: #fff; + border: 1px solid #fff; + border-radius: 3px; + color: #222; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); + } +.leaflet-tooltip.leaflet-clickable { + cursor: pointer; + pointer-events: auto; + } +.leaflet-tooltip-top:before, +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + position: absolute; + pointer-events: none; + border: 6px solid transparent; + background: transparent; + content: ""; + } + +/* Directions */ + +.leaflet-tooltip-bottom { + margin-top: 6px; +} +.leaflet-tooltip-top { + margin-top: -6px; +} +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-top:before { + left: 50%; + margin-left: -6px; + } +.leaflet-tooltip-top:before { + bottom: 0; + margin-bottom: -12px; + border-top-color: #fff; + } +.leaflet-tooltip-bottom:before { + top: 0; + margin-top: -12px; + margin-left: -6px; + border-bottom-color: #fff; + } +.leaflet-tooltip-left { + margin-left: -6px; +} +.leaflet-tooltip-right { + margin-left: 6px; +} +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + top: 50%; + margin-top: -6px; + } +.leaflet-tooltip-left:before { + right: 0; + margin-right: -12px; + border-left-color: #fff; + } +.leaflet-tooltip-right:before { + left: 0; + margin-left: -12px; + border-right-color: #fff; + } diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/CNAME b/vendor/assets/javascripts/Leaflet-1.4.0/docs/CNAME new file mode 100644 index 000000000..7dd1131fb --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/CNAME @@ -0,0 +1 @@ +leafletjs.com \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/Gemfile b/vendor/assets/javascripts/Leaflet-1.4.0/docs/Gemfile new file mode 100644 index 000000000..97355ea72 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/Gemfile @@ -0,0 +1,3 @@ +source 'https://rubygems.org' + +gem 'github-pages' diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_config.yml b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_config.yml new file mode 100644 index 000000000..f081bc53e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_config.yml @@ -0,0 +1,15 @@ +exclude: [build, debug, node_modules, spec, src, CNAME, reference-tpl.html, CHANGELOG.md, README.md, LICENSE, DOCS-TODO.md] + +markdown: kramdown + +kramdown: + entity_output: as_input + +latest_leaflet_version: 1.3.4 + +# Integrity hashes for both leaflet.js and leaflet-src.js +# These will be shown in the downloads page +# See https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity +integrity_hash_css: "sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" +integrity_hash_source: "sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" +integrity_hash_uglified: "sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_includes/frame.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_includes/frame.html new file mode 100644 index 000000000..c3e595c0c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_includes/frame.html @@ -0,0 +1,9 @@ + + +
+ +
+See this example stand-alone. +
diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_includes/tutorial_link.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_includes/tutorial_link.html new file mode 100644 index 000000000..c002ba4cb --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_includes/tutorial_link.html @@ -0,0 +1,8 @@ + +*** + + + +### {{ include.title }} + +{{ include.description }} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/post.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/post.html new file mode 100644 index 000000000..54dcea10f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/post.html @@ -0,0 +1,30 @@ +--- +root: "../../../" +layout: v2 +post: true +bodyclass: post-page +--- + +

← Back to the list of blog posts

+ +

{{ page.title }}

+ + + +{{ content }} + +
+ + + +comments powered by Disqus + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/redirected.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/redirected.html new file mode 100644 index 000000000..fb02bd4b1 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/redirected.html @@ -0,0 +1,20 @@ + + + + + + + + + +

Redirecting...

+ Click here if you are not redirected. + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial.html new file mode 100644 index 000000000..5e9bf15a6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial.html @@ -0,0 +1,9 @@ +--- +root: "../" +layout: v2 +tutorial: true +--- + +

← Tutorials

+ +{{ content }} \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial_frame.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial_frame.html new file mode 100644 index 000000000..1a609dbe9 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial_frame.html @@ -0,0 +1,36 @@ + + + + {% capture title %}{% if page.title %}{{ page.title }} - {% elsif post.title %}{{ post.title }} - {% endif %}{% endcapture %} + {{ title }}Leaflet + + + + {% capture root %}{% if page.root %}{{ page.root }}{% else %}{{ layout.root }}{% endif %}{% endcapture %} + + + + + +{% unless page.customMapContainer == "true" %} + +{% endunless %} + {% if page.css %}{% endif %} + + + +{% unless page.customMapContainer == "true" %}
{% endunless %} + +{{ content }} + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial_v2.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial_v2.html new file mode 100644 index 000000000..37a6d0062 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/tutorial_v2.html @@ -0,0 +1,9 @@ +--- +root: "../../" +layout: v2 +tutorial: true +--- + +

← Tutorials

+ +{{ content }} \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/v2.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/v2.html new file mode 100644 index 000000000..4b56fb6a5 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_layouts/v2.html @@ -0,0 +1,159 @@ + + + + {% capture title %}{% if page.title %}{{ page.title }} - {% elsif post.title %}{{ post.title }} - {% endif %}{% endcapture %} + + {{ title }}Leaflet - a JavaScript library for interactive maps + + + + {% if title == '' %} + + + + + + + + {% endif %} + + + + {% capture root %}{% if page.root %}{{ page.root }}{% else %}{{ layout.root }}{% endif %}{% endcapture %} + + + + + + + + + + + + + + + + + + {% if page.css %}{% endif %} + + + + + +

Leaflet

+

an open-source JavaScript library
for mobile-friendly interactive maps

+ + + +
+ + +{{ content }} + + + +
+ + + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-07-30-leaflet-0-4-released.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-07-30-leaflet-0-4-released.md new file mode 100644 index 000000000..18ab66e1d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-07-30-leaflet-0-4-released.md @@ -0,0 +1,240 @@ +--- +layout: post +title: Leaflet 0.4 Released +description: After 5.5 months of development with 33 contributors involved, I'm proud to announce the release of Leaflet 0.4! It comes with a simpler API and lots of great improvements, along with a major update to documentation, a plugins page and the launch of the developer blog. +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +After 5.5 months of development with [33 contributors](https://github.com/Leaflet/Leaflet/graphs/contributors?from=2012-02-15&to=2012-07-30&type=c) involved since the previous stable release, I'm proud to announce the release of Leaflet 0.4! It comes with a simpler API and *lots* of great improvements and important bugfixes, along with a major update to documentation, an official plugins page and the launch of this developer blog. Lets take a look at the improvements one by one. + +### Simpler API + +Leaflet 0.4 contains several API improvements that allow you to write simpler, terser code ([jQuery](http://jquery.com)-like), while being backwards compatible with the previous approach (so that you can use both styles). + + L.marker([51.5, -0.09]) + .addTo(map) + .bindPopup('Hello world!') + .openPopup(); + +First, Leaflet methods now accept [LatLng][], [LatLngBounds][], [Point][] and [Bounds][] objects in a simple array form, so you don't need to always create them explicitly: + + map.panTo([50, 30]); // the same as: + map.panTo(new L.LatLng(50, 30)); + +Second, Map methods like [addLayer][], [addControl][], [openPopup][] got their counterparts from the other side: + + marker.addTo(map); // same as map.addLayer(marker) + control.addTo(map); // map.addControl(control) + popup.openOn(map); // map.openPopup(popup) + +Along with the fact that all Leaflet methods that don't explicitly return a value return the object itself, this allows for convenient method chaining. + +Third, Leaflet classes now come with lowercase shortcuts (class factories) that allow you to create objects without the new keyword, which makes chained code look nicer: + + L.map('map').fitWorld(); // same as + (new L.Map('map')).fitWorld(); + +### Notable New Features + +
+ +#### Improved Zoom Animation + +Markers, popups, vector layers and image overlays were hidden during zoom in the previous version, but now (thanks to [Dave Leaver][]) they all have beautiful, smooth zoom animation unlike any other existing mapping libraries. Try zooming on the map above to see how it looks! If you have thousands of markers on a map though, you can turn off the marker animation if it gets slow with the Map's `markerZoomAnimation` option. + +In addition, now tiles won't disappear if you zoom in or out more than once quickly. + +#### Keyboard Navigation + +Leaflet maps got a nice accessibility boost in 0.4 with the new keyboard handler (contributed by [Eric Martinez](https://github.com/ericmmartinez)), enabled by default. It allows users to navigate the map by using arrow keys for panning and +/- keys for zooming (after making the map focused either by tabbing to it or clicking on it). Try it on the map above, it feels very nice! + +#### Panning Inertia + +Another nice improvement comes to the panning experience --- now it has an inertial movement effect, where the map smoothly continues to move after a quick pan. Feels especially natural on touch devices --- and it's enabled by default too, try it now! It's also highly configurable, allowing you to set the maximum speed of the effect, decceleration, and time threshold under which it triggers. + +#### Pinch-Zoom on Android 4 + +In the previous Leaflet version, pinch-zoom only worked on iOS devices, but now it finally comes to Android! Works for Android 4+ not only in the stock browser, but also on Chrome and Firefox for Android. + +#### Scale Control + +A simple, lightweight control that indicates the scale of the current map view in metric and/or imperial systems. As usual, you can customize its appearance with CSS. Take a look at the bottom left corner of the map above! + + L.control.scale().addTo(map); + +#### Polyline and Polygon Editing + +Allows users to edit polylines and polygons with a simple, intuitive interface. Note that this feature will eventually be merged into [Leaflet.draw][] --- an awesome plugin for drawing shapes by Jacob Toye. + + polygon.editing.enable(); + +#### Div-based Icons + +In addition to the image-based [Icon][] class, Leaflet 0.4 gets a [DivIcon][] class for creating lightweight div-based markers (that can contain custom HTML and can be styled with CSS). For example, you can see them in action when editing polylines (the square handles), or in the [Leaflet.markercluster][] plugin I'll talk about later (the colored clusters). + + L.marker([50.505, 30.57], { + icon: L.divIcon({className: 'my-div-icon'}) + }).addTo(map); + +#### Rectangle Layer + +Rectangle is a convenient shortcut for creating rectangular area layers. You could do this earlier with polygons, but this is easier: + + L.rectangle([[51.505, -0.03], [51.5, -0.045]]).addTo(map); + +### API improvements + +#### GeoJSON API + +[GeoJSON][] API was improved to be simpler and much more flexible. [Jason Sanford][] wrote a [great tutorial](../../../examples/geojson.html) that showcases the new API. The changes are not backwards-compatible though, so be sure to update your old code. + +#### Icon API + +[Icon][] API was improved to be simpler and more flexible, and the changes are not backwards-compatible too (the old code can be updated very quickly though). Check out the updated [Custom Icons tutorial](../../../examples/custom-icons.html), or head straigt to the [API docs](../../../reference.html#icon). + +#### Control API + +Custom Controls are much easier to create now --- checkout the [API docs](../../../reference.html#icontrol) that also have a simple example. + +#### Better Events API + +[Aaron King][] brough some improvements to [event methods](../../../reference.html#events). `on` and `off` methods can now accept multiple event types at once as a string space-separated types: + + map.on('click dblclick moveend', doStuff); + +Also, they can accept an object with types and listener functions as key/value pairs, like this: + + marker.on({ + click: onMarkerClick, + dragend: onMarkerDragEnd + }); + +Moreover, now if you only specify an event type to the `off` method, it will remove all listeners tied to this event. + + map.off('click'); + +#### Other API Improvements + +Leaflet 0.4 features more than 30 new methods, options and events across different Leaflet classes that make the API more complete and powerful. Check out the [full changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md#other-api-improvements) for the complete list. + +### Performance and Usability Improvements + +You may think that Leaflet is unbelievably fast already, but this version brings several performance improvements that make it even faster. + + * Panning, map resizing and pinch-zoom performance was improved (some tricks behind this will be explained in a future blog post). + * Updating and removing vector layers on the canvas backend (e.g. on Android 2) works many times faster. + * Box shadows on controls were replaced with simple borders on mobile devices to improve performance. + * Vector layers won't flicker after each panning on iOS now. + +In addition, there are several usability improvents not already mentioned: + + * Panning now works even if there are markers under the cursor (helps on crowded maps). + * Popup appearance is slightly improved. + * Tile layer now has detectRetina option that, when enabled, doubles the tile resolution for retina displays (contributed by [Mithgol][]) . + +### Bugfixes + +Leaflet 0.4 brings around 45 bugfixes that make it more stable and reliable across all browsers and platforms. Notable bugfixes include the dreaded iOS bug that caused the map to completely disappear after pinch-zooming in some rare cases, broken zooming on IE10 beta, broken Leaflet maps on pages served with an XHTML content type, and incorrect zooming on maps inside a fixed-position element. + +Here's [a full list of bugfixes](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md#bug-fixes) in the changelog. + +### Upgrading from older versions + +Besides the GeoJSON and Icon changes mentioned above, here's a [list of potentially breaking changes](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md#other-breaking-api-changes) --- read it carefully when updating your code (shouldn't take much time though). + +Download options for Leaflet 0.4 (including the actual download, the CDN-hosted version, and intructions for building manually) are listed on the [download page](../../../download.html). + +### Code Stats + +I'm still commited to keeping Leaflet as small and lightweight as possible. Here's a breakdown of the current size of the library: + + * JavaScript: **27 KB** minified and gzipped (102 KB minified, 176 KB in source, 7578 lines of code) + * CSS: **1.8 KB** gzipped (8 KB, 377 lines of code) + * Images: **10 KB** (5 PNG images) + +### Documentation Update + +Until now, Leaflet API reference was incomplete. But for this release, enourmous effort was put into making it 100% complete, up-to-date and generally the best API reference page you've ever seen. All remaining classes, methods, options, events and properties were carefully documented and more code examples added, and the docs will always be kept up-to-date from now on. + +Besides, the design of the page was significantly improved --- with better colors, font, spacing, hyphenation, manually adjusted column widths, etc. --- lots of detail to make it beautiful and easy to read. + +### Plugins Page + +Leaflet website now has an official [plugins page](../../../plugins.html) that lists many Leaflet plugins created by the awesome Leaflet community, adding lots of great features and helping with service integration. + +One plugin I'd like to mention is [Leaflet.markercluster][] by [Dave Leaver], currently the best marker clustering plugin I've ever seen among any mapping libraries --- it's fast, beautiful, provides smooth animations for clusters, includes a smart Google Earth-style solution for crowded markers on the last zoom level (by [George MacKerron][]), can highlight the area covered by a cluster on hover, works well on mobile devices, and can be customized easily. I think we'll cover this plugin in more detail in one of the next posts. + +Another plugin to note is [Leaflet.draw][] by [Jacob Toye][], inspired by a similar plugin by [Bruno B](https://github.com/brunob). It enables drawing features like polylines, polygons, rectangles, circles and markers through a very nice user-friendly interface with icons and hints. Other editing-related code will probably move into this plugin in future. + +Also, thanks to [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin by [Kartena](http://www.kartena.se/), GIS enthusiasts can now enjoy Leaflet for maps with some quirky and rare projections. + +One more Leaflet-based creation everyone needs to check out is [OSM Buildings](http://flyjs.com/buildings/) by [Jan Marsch](http://flyjs.com/buildings/about.php), an amazing JS library for visualizing 3D OSM building data on top of Leaflet maps. Incredibly cool stuff. + +### Developer Blog + +This is the first post of the official Leaflet developer blog, that will become the main place for all important Leaflet-related news, tutorials, tips and development notes. + +### Big Players Using Leaflet + +Since the previous release, Leaflet got adopted by many great companies, including [Flickr](http://flickr.com/map), [foursquare](http://foursquare.com) and [Wikimedia Foundation](http://blog.wikimedia.org/2012/04/05/new-wikipedia-app-for-ios-and-an-update-for-our-android-app/) (featured on [frontpage](../../../index.html) now). This is a really exciting time for Leaflet and open source maps, and I look forward to see many other companies follow this awesome trend in future. + +### Thank You + +I'd like to thank all the awesome people that helped Leaflet becoming what it is now --- contributed code, reported bugs, used Leaflet on their websites, told collegues about it, talked about it on conferences, etc. Keep up the great work! + +Special thanks go to [Dave Leaver][] for his inspiring contributions including improved zoom animation and the state-of-the-art clustering plugin, and [Jason Sanford][] for his friendly support (and setting up the Leaflet CDN among other things). + +And, of course, thanks to my amazing company, [CloudMade](http://cloudmade.com), for embracing open source and supporting this development. + +Sincerely,
+Vladimir Agafonkin, Leaflet maintainer. + + [LatLng]: ../../../reference.html#latlng + [LatLngBounds]: ../../../reference.html#latlngbounds + [Point]: ../../../reference.html#point + [Bounds]: ../../../reference.html#bounds + [Icon]: ../../../reference.html#icon + [DivIcon]: ../../../reference.html#divicon + [GeoJSON]: ../../../reference.html#geojson + + [addControl]: ../../../reference.html#map-addcontrol + [addLayer]: ../../../reference.html#map-addlayer + [openPopup]: ../../../reference.html#map-openpopup + + [Leaflet.draw]: https://github.com/jacobtoye/Leaflet.draw + [Leaflet.markercluster]: https://github.com/danzel/Leaflet.markercluster + + [Dave Leaver]: https://github.com/danzel + [Jason Sanford]: https://github.com/JasonSanford + [Aaron King]: https://github.com/Guiswa + [Mithgol]: https://github.com/Mithgol + [George MacKerron]: https://github.com/jawj/ + [Jacob Toye]: https://github.com/jacobtoye + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-08-07-leaflet-0-4-3-and-a-new-tutorial.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-08-07-leaflet-0-4-3-and-a-new-tutorial.md new file mode 100644 index 000000000..2a2271547 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-08-07-leaflet-0-4-3-and-a-new-tutorial.md @@ -0,0 +1,47 @@ +--- +layout: post +title: Leaflet 0.4.3 and a New Tutorial +description: Leaflet 0.4.3 released with several bugfixes and improvements, and comes with a new tutorial on creating a colorful interactive choropleth map. +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +Following the [Leaflet 0.4 release](leaflet-0-4-released.html), there were several minor bugfix releases over the past week, with Leaflet 0.4.3 released today. They contain fixes for some bugs that were discovered and also bring some improvements to the new GeoJSON API to make it even more flexible --- see the changelog below. + +I've also written [a new tutorial](../../../examples/choropleth.html), inspired by the [Texas Tribune US Senate Runoff Results map](http://www.texastribune.org/library/data/us-senate-runoff-results-map/) by [Ryan Murphy](http://www.texastribune.org/about/staff/ryan-murphy/) (also powered by Leaflet). It will show you step-by-step how to create a beautiful interactive [choropleth map](http://en.wikipedia.org/wiki/Choropleth_map) of US States Population Density with the help of GeoJSON and custom controls, and hopefully convince more major news and government websites to switch to Leaflet. :) + +Grab the new Leaflet 0.4.3 at the [download page](../../../download.html). Enjoy! + +**update**: IE9 regression was discovered in 0.4.3, so I had to release 0.4.4 with a fix. Sorry! + +### 0.4.3 (August 7, 2012) + +#### Improvements + + * Improved `GeoJSON` `setStyle` to also accept function (like the corresponding option). + * Added `GeoJSON` `resetStyle(layer)`, useful for resetting hover state. + * Added `feature` property to layers created with `GeoJSON` (containing the GeoJSON feature data). + * Added `FeatureGroup` `bringToFront` and `bringToBack` methods (so that they would work for multipolys). + * Added optional `animate` argument to `Map` `invalidateSize` (by [@ajbeaven](https://github.com/ajbeaven)). [#857](https://github.com/Leaflet/Leaflet/pull/857) + +#### Bugfixes + + * Fixed a bug where tiles sometimes disappeared on initial map load on Android 2/3 (by [@danzel](https://github.com/danzel)). [#868](https://github.com/Leaflet/Leaflet/pull/868) + * Fixed a bug where map would occasionally flicker near the border on zoom or pan on Chrome. + * Fixed a bug where `Path` `bringToFront` and `bringToBack` didn't return `this`. + * Removed zoom out on Win/Meta key binding (since it interferes with global keyboard shortcuts). [#869](https://github.com/Leaflet/Leaflet/issues/869) + +### 0.4.2 (August 1, 2012) + + * Fixed a bug where layers control radio buttons would not work correctly in IE7 (by [@danzel](https://github.com/danzel)). [#862](https://github.com/Leaflet/Leaflet/pull/862) + * Fixed a bug where `FeatureGroup` `removeLayer` would unbind popups of removed layers even if the popups were not put by the group (affected [Leaflet.markercluster](https://github.com/danzel/Leaflet.markercluster) plugin) (by [@danzel](https://github.com/danzel)). [#861](https://github.com/Leaflet/Leaflet/pull/861) + +### 0.4.1 (July 31, 2012) + + * Fixed a bug that caused marker shadows appear as opaque black in IE6-8. [#850](https://github.com/Leaflet/Leaflet/issues/850) + * Fixed a bug with incorrect calculation of scale by the scale control. [#852](https://github.com/Leaflet/Leaflet/issues/852) + * Fixed broken L.tileLayer.wms class factory (by [@mattcurrie](https://github.com/mattcurrie)). [#856](https://github.com/Leaflet/Leaflet/issues/856) + * Improved retina detection for `TileLayer` `detectRetina` option (by [@sxua](https://github.com/sxua)). [#854](https://github.com/Leaflet/Leaflet/issues/854) + +Sincerely,
+Vladimir Agafonkin, Leaflet maintainer. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-08-20-guest-post-markerclusterer-0-1-released.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-08-20-guest-post-markerclusterer-0-1-released.md new file mode 100644 index 000000000..2390b5af8 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-08-20-guest-post-markerclusterer-0-1-released.md @@ -0,0 +1,112 @@ +--- +layout: post +title: Leaflet.MarkerCluster 0.1 Released +description: Introducing Leaflet.MarkerCluster, a beautiful, fast, customizable plugin to reduce the visual clutter on crowded maps. +author: Dave Leaver +authorsite: https://github.com/danzel/ +--- + +_This is a guest post from Dave Leaver, an active Leaflet contributor (particularly, he implemented 0.4 zoom animation improvements) and also the author of the best marker clustering plugin out there, which is presented in this post._ + +Almost anyone who has a map with markers on it will eventually end up having those markers overlap. At my day job at Smartrak we regularly have customers with thousands of points on the map. When you zoom it out, these markers all overlap and make the map look messy and crowded. There are also cases where the markers overlap even on the maximum zoom level, which makes interacting with them impossible. Also, having a large amount of markers on the map usually ends up lowering performance to an unacceptable level. + +To improve this, many sites use marker clustering, a technique of grouping markers that are close to each other together on each zom level. One good example of this is Redfin. We needed something like this, but in Leaflet. In the spirit of open source we developed and released our solution so that everyone can take advantage of it. So we proudly present Leaflet.MarkerCluster. + +
+ +{:#plugin-features} +### Features + +The clusterer has all sorts of great built in behaviour: + + * Everything is brilliantly animated. As you zoom in and out you can logically see which clusters have become which markers. + * It is very fast, so for example [clustering 50,000 points](https://leaflet.github.com/Leaflet.markercluster/example/marker-clustering-realworld.50000.html) isn't a problem. Also, all the heavy calculation happens on initial page load, and after this the map works smoothly. + * Markers that don't need clustering aren't and will be visible at the relevant zoom levels. + * When you mouse over a cluster the bounds of the marker within that cluster are shown. + * Clicking a cluster will zoom you in to the bounds of its children. + * At the bottom zoom level if there are still clusters you can click on them to "spiderfy" them, which makes interaction with individual markers within the cluster possible (based on jawj's Overlapping MarkerSpidifer). + * Cluster and markers that are further than a screen width from the view port are removed from the map to increase performance. + * As with core Leaflet, everything works on both mobile and desktop browsers and is tested all the way back to IE6. + * Supports adding and removing markers after being added to the map (see Best Practices below!). + * It is highly customizable, allowing you to easily change the appearance of clusters, disable certain features and add custom behavior on cluster interaction. + +### Usage + +Using the Marker Clusterer is easy, just replace your existing [LayerGroup](../../../examples/layers-control.html) usage with an `L.MarkerClusterGroup`: + + var markers = new L.MarkerClusterGroup(); + + markers.addLayer(L.marker([175.3107, -37.7784])); + // add more markers here... + + map.addLayer(markers); + +You can also use all of the [FeatureGroup events](../../../reference.html#featuregroup) (and additionally `clusterclick`) for both individual markers and clusters. + + markers.on('clusterclick', function (a) { alert('Cluster Clicked'); }); + markers.on('click', function (a) { alert('Marker Clicked'); }); + +### Best Practices + + * To get the best performance from the clusterer, you should add all of your markers to it before adding it to the map (like we did in the example). + * If you are going to move a marker that is in a L.MarkerClusterGroup you must remove it first, then move it, then re-add it. If you move it while it is in the MarkerClusterGroup we can't track it and that marker will become lost. + * Although the clusterer supports having markers added and removed from it while it is on the map it does not perform as well as when they are added while it is not on the map. If you need to do a large update to the markers in a `MarkerClusterGroup` you may want to remove it from the map, change the markers then re-add it. + +### Get It + +You can download the latest release on the github download page. + +### The Technical Bits + +The underlying clustering algorithm (`MarkerClusterGroup._cluster`) is plain greedy clustering. + +{: .no-highlight} + foreach marker + if there is a cluster within the clustering distance, join it. + else if there is an unclustered marker within the clustering distance, form a cluster with it. + +The first clustering step we do for the maximum (bottom most) zoom level, we then cluster all of the resulting markers and clusters to generate the next zoom level up and so on until we have reached the top. +These clusters are stored in a tree (A cluster contains its child clusters) with good geospatial qualities. We use this tree to optimise identifying what markers and clusters are on screen at any particular zoom level. + +#### L.DistanceGrid + +`L.DistanceGrid` provides some nice optimization when clustering (contributed by [Vladimir](http://agafonkin.com/en/), Leaflet maintainer). + +To cluster the markers, we need to compare every marker with every other marker to try form a cluster. +To make this quicker, we need reduce the set of markers we need to compare with. `DistanceGrid` does this by putting all markers on a grid sized the same as the distance we need to search. Then, when looking for a marker to cluster with, we only need to look at markers in the grid square we are in and its immediate neighbours. This can be quite a big performance win as we only look at markers that we are likely to form a cluster with. (check out the initial PR for numbers) + +### Closing Words + +I hope you enjoy using the clusterer and get everything you want out of it. If you do use it in a public site please throw me an email so I can check it out and potentially link it on the github site. + +If you have any issues also please log a bug on the github page. + +Enjoy!
+Dave Leaver. + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-10-25-leaflet-0-4-5-bugfix-release-and-plans-for-0.5.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-10-25-leaflet-0-4-5-bugfix-release-and-plans-for-0.5.md new file mode 100644 index 000000000..d5ea237ed --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2012-10-25-leaflet-0-4-5-bugfix-release-and-plans-for-0.5.md @@ -0,0 +1,36 @@ +--- +layout: post +title: Leaflet 0.4.5 Bugfix Release and Plans for 0.5 +description: Leaflet 0.4.5 released, containing a small but important zoom animation bugfix for upcoming Chrome 23+ (currently beta) and IE10. Work on future 0.5 release goes on! +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +### 0.4.5 release + +While we contrinue working on the next major release (0.5), today we decided to release **Leaflet 0.4.5**. It contains only one small but important bugfix for **wonky zoom animation** on upcoming **Chrome 23** (currently in beta and to be released in a couple of weeks) and **Internet Explorer 10** (that will eventually hit Windows 7 in addition to Windows 8). + +Everyone is encouraged to upgrade (before Chrome 23 turns stable). As always, you can find CDN links and downloads for the new release on the [download page](../../../download.html). + +### Plans for 0.5 + +As Leaflet approaches feature-complete state and API stabilization, we naturally shift our focus from new features towards performance and usability improvements, better browser and device support, bugfixes and internal refactoring to make certain parts of Leaflet (like projections and vector rendering) easier to extend and customize for plugin developers and advanced users. + +Highlights of things already implemented in the `master` branch include touch interaction support for **IE10 touch devices and Metro apps** and a more smooth and responsive panning inertia. Follow the [full changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md) for more details. + +We're also in the process of a major refactoring of vector rendering code to allow much simpler extension of base functionality with custom shapes, additional rendering systems (like WebGL in addition to existing SVG/VML and Canvas renderers), easy switching between renderers, also making the code simpler and easier to understand. + +The same goes for projection-related code to make using Leaflet with non-standard projections easier, inluding plain projections for game and indoor maps. Thanks to these changes, in addition to making advanced GIS folks happier, we'll see much more awesome Leaflet projects like [interactive Skyrim map on IGN](http://www.ign.com/wikis/the-elder-scrolls-5-skyrim/interactive-maps/Skyrim) or [World of Warcraft map on Wowhead](http://www.wowhead.com/map). + +Another important task for upcoming weeks is working more closely with plugin developers. In particular, one of the areas of focus will be the [Leaflet.draw](https://github.com/jacobtoye/Leaflet.draw) plugin that will soon become a state-of-the-art map vector drawing/editing solution, just as Dave's [Leaflet.markercluster](https://github.com/danzel/Leaflet.markercluster) became the best marker clustering solution among all mapping platforms out there. + +The current plan is to release 0.5 stable sometime in mid-November. Stay tuned! + +### Contributing to Leaflet + +Leaflet is a true open source project, so we're always happy to meet new contributors, accept patches and bugreports. To help others become involved with Leaflet development and make managing contributions easier, I've put up a [Contributing to Leaflet](https://github.com/Leaflet/Leaflet/blob/master/CONTRIBUTING.md) guide with best practices and advices — check it out! + +Thanks to everyone! Leaflet has got quite an amazing community which makes me really proud. Keep it up! + +Cheers,
+Vladimir, Leaflet author and maintainer. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-01-17-leaflet-0-5-released.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-01-17-leaflet-0-5-released.md new file mode 100644 index 000000000..c9630db29 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-01-17-leaflet-0-5-released.md @@ -0,0 +1,24 @@ +--- +layout: post +title: Leaflet 0.5 Released +description: Leaflet 0.5 released — with IE10 touch support, retina-enabled markers, better panning inertia, new zoom control and about a hundred of other improvements and bugfixes! +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +Rejoice, everyone — after 4.5 months of development with [26 contributors involved](https://github.com/Leaflet/Leaflet/graphs/contributors?from=2012-08-30&to=2013-01-17&type=c) since the previous major release, I'm happy to announce the release of Leaflet 0.5 stable, hooray! + +0.5 highlights include IE10 touch devices and Metro apps support, retina-enabled markers, a much better panning inertia implementation, hand cursors for dragging and a new zoom control design. But the real power of this release comes with about a hundred of subtle improvements and bugfixes, improving usability, performance and overall "feel" of browsing the map even further. + +As always, you can find CDN links and downloads for the new release on the [download page](../../../download.html). + +The huge detailed list of changes is documented in the [changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md). Be sure to read the "Breaking Changes" part of it before upgrading to avoid any issues! The [API reference](../../../reference.html) was updated to accomodate all the changes too. + +In other news, [Leaflet repository](https://github.com/Leaflet/Leaflet) has moved to [its own GitHub organization](https://github.com/Leaflet), along with the two of the most important plugins — [Leaflet.markercluster](https://github.com/Leaflet/Leaflet.markercluster) and [Leaflet.draw](https://github.com/Leaflet/Leaflet.draw). As some of you have noticed, this is one of the clues to a really nice upcoming announcement about Leaflet future — stay tuned. :) + +Thanks to everyone! It's absolutely breathtaking to see what the Leaflet community has achieved over the last months with all the contributions, amazing projects and demos, and I'm honestly proud to be a part of it. + +P.S. I also heard in a dream that everyone who tweets about the new Leaflet release will get an incredible luck boost for the next month. Sounds like true to me. + +Cheers,
+Vladimir, Leaflet creator and maintainer. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-02-20-guest-post-draw.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-02-20-guest-post-draw.md new file mode 100644 index 000000000..75c50787a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-02-20-guest-post-draw.md @@ -0,0 +1,146 @@ +--- +layout: post +title: Leaflet.draw 0.2 Released +description: Leaflet.draw 0.2 released — brings vector drawing and editing tools to your Leaflet map. +author: Jacob Toye +authorsite: https://github.com/jacobtoye/ +--- + +_This is a guest post from Jacob Toye, an active Leaflet contributor and also the author of the most sophisticated vector drawing and editing plugin out there, which is presented in this post._ + +[Leaflet.draw](https://github.com/Leaflet/Leaflet.draw/) was born from the need to provide users with the ability draw polygons on the map. Leaflet already provided a very nice way of editing existing polylines and polygons. The logical next step was to expand on this functionality to allow the creation of these layers, and ultimately the other vector layers. + +Upon release the immediate response from the Leaflet community was very positive. It became clear that the next step would be progressing this tool to a state where users could edit and delete shapes in addition to creating them. This is ultimately what Leaflet.draw 0.2 set out to do. + +After a few months of off and on development, with most of this spare time kindy sponsored by my employer Smartrak, we proudly present Leaflet.draw 0.2 -- your one stop plugin for drawing, editing and deleting vectors and markers on Leaflet maps. :) + +_Note from Vladimir: the polyline/polygon editing functionality from Leaflet core has been moved into this plugin where it fits much better. The plugin in turn has moved into [Leaflet organization on GitHub](https://github.com/Leaflet) and is now officially supported by the Leaflet development team. Note that version 0.2 currently depends on Leaflet master (in-progress development version) to work._ + +You can download the latest version from the github repo. Please report any bugs you come across on the issues page. + +
+ +{:#plugin-features} +### Features + +Leaflet.draw is designed to not only be easy for end users to use, but also for developers to integrate. + + * Draw shapes on your map with easy to use drawing tools. + * Edit and delete vectors and markers. + * Super customizable: + * Customize the styles of each shape to fit in with your maps theme. + * Pick and choose the which tools you want to use. + * Roll your own by simply using the drawing and editing handlers. + * Event based system allows you to perform any necessary actions when shapes are created, edited or deleted. + +### How to use + +Leaflet.draw is very simple to drop into you Leaflet application. The following example will add both the draw and edit toolbars to a map: + + // create a map in the "map" div, set the view to a given place and zoom + var map = L.map('map').setView([175.30867, -37.77914], 13); + + // add an OpenStreetMap tile layer + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' + }).addTo(map); + + // Initialize the FeatureGroup to store editable layers + var drawnItems = new L.FeatureGroup(); + map.addLayer(drawnItems); + + // Initialize the draw control and pass it the FeatureGroup of editable layers + var drawControl = new L.Control.Draw({ + edit: { + featureGroup: drawnItems + } + }); + map.addControl(drawControl); + +#### Handling newly created layers + +Once you have successfully added the Leaflet.draw plugin your map you will want to respond to the different actions users can trigger. + + map.on('draw:created', function (e) { + var type = e.layerType, + layer = e.layer; + + if (type === 'marker') { + // Do marker specific actions + } + + // Do whatever else you need to. (save to db, add to map etc) + drawnItems.addLayer(layer); + }); + + map.on('draw:edited', function () { + // Update db to save latest changes. + }); + + map.on('draw:deleted', function () { + // Update db to save latest changes. + }); + +See the Leaflet.draw README for more details on how to configure the plugin. + +### Thanks + +First and foremost I would like to thank my employer Smartrak. Without their attitude to open source software I would not have had the time to complete this plugin. + +The Leaflet developer community have been great in supporting this plugin through inspiration, pull requests and issue reports. Special thanks to: @mourner, @danzel, @brunob, @tnightingale, @Starefossen, and @shramov. + +### Closing + +I've had a great time implementing this plugin. I hope you enjoy using it. If you have a question or just want to say hi, send me an email at jacob.toye@gmail.com. + +Cheers, +Jacob Toye + + + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-06-26-leaflet-0-6-released-dc-code-sprint-mapbox.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-06-26-leaflet-0-6-released-dc-code-sprint-mapbox.md new file mode 100644 index 000000000..152588df0 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-06-26-leaflet-0-6-released-dc-code-sprint-mapbox.md @@ -0,0 +1,31 @@ +--- +layout: post +title: Leaflet 0.6 Released, Code Sprint in DC with MapBox +description: Leaflet 0.6 released — with nicer controls, better usability and tons of API improvements and various bugfixes — more than 120 changes! The first ever Leaflet Code Sprint happening in Washington, DC with the MapBox team +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +_Leaflet 0.6 released — with nicer controls, better usability and tons of API improvements and various bugfixes — more than 120 changes! The first ever Leaflet Code Sprint happening in Washington, DC with the MapBox team..._ + +After 5 months of active development with [36 contributors involved](https://github.com/Leaflet/Leaflet/graphs/contributors?from=2013-01-18&to=2013-06-26&type=c) since the previous major version, today I'm excited to finally announce the **release of Leaflet 0.6** stable. + +0.6 highlights include nicer controls, lots of interaction usability improvements, many new API methods, events and options, ability to save layers as [GeoJSON](http://en.wikipedia.org/wiki/GeoJSON), much better test infrastructure and TONS of bugfixes that made Leaflet significantly more reliable. Checkout the huge detailed list of changes (**120+ total**!) [in the changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md). The [API reference](../../../reference.html) was also updated to reflect all these changes. + +The final push for the release (last 2 days) was a part of the first ever **Leaflet Code Sprint**, organized in Washington DC by the amazing [MapBox](http://mapbox.com), a company responsible for perhaps the greatest innovations and awesome tools in the geospatial world of recent years, now [using Leaflet for its JS API](mapbox.com/blog/mapbox-js-with-leaflet/) too. The sprint will go on for a week and there are many more awesome improvements to come in upcoming days (and lots of partying as well). + +On a related note, even GitHub itself is now [using Leaflet for GeoJSON visualizations](https://github.com/blog/1541-geojson-rendering-improvements), along with [Leaflet.markercluster](github.com/Leaflet/Leaflet.markercluster) & MapBox tiles! How cool is that? + +Special thanks go to [Universal Mind](http://universalmind.com/), my awesome employer and sponsor of Leaflet development for the past 5 months, to the most active contributors — [John Firebaugh](https://github.com/jfirebaugh) and [Tom MacWright](https://github.com/tmcw) of [MapBox](http://mapbox.com), [Dave Leaver](https://github.com/danzel) and [Jacob Toye](https://github.com/jacobtoye) of [Smartrak](http://www.smartrak.co.nz/), [Steve Kashishian](https://github.com/snkashis) of [First Mile Geo](http://www.firstmilegeo.com/), and to everyone else involved in contributions, bug reports, mailing list, Twitter, making awesome apps, etc. You're such an amazing community! I'm really happy to be a part of it. + +Grab the CDN links or downloads for the new release on the [download page](../../../download.html) as always. Enjoy! And be sure try it out and report any regressions in your apps so that we can patch them up immediately. + +**update** (June 27): 0.6.1 hotfix released with a couple of regressions fixed (particularly the one with FF scroll-zooming too fast).
+**update** (June 28): 0.6.2 hotfix released with a couple more minor issues fixed.
+**update** (July 17): 0.6.3 released with lots of regressions and bugs fixed.
+**update** (July 25): 0.6.4 released with a fix to 0.6.3 regression. + +P.S. Everyone who tweets/posts about the new Leaflet release or why he loves Leaflet over the next few days will get a karma boost of over 9000 points. I heard that from a passing monk in Georgetown yesterday, true story! + +Cheers,
+Vladimir, Leaflet creator and maintainer. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-06-28-leaflet-plugin-authoring-guide.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-06-28-leaflet-plugin-authoring-guide.md new file mode 100644 index 000000000..a798d746a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-06-28-leaflet-plugin-authoring-guide.md @@ -0,0 +1,111 @@ +--- +layout: post +title: Leaflet Plugin Authoring Guide +description: A number of best practices and tips for publishing your own perfect Leaflet plugin +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +One of the greatest things about Leaflet is its powerful plugin ecosystem. +The [Leaflet plugins page](https://leafletjs.com/plugins.html) lists dozens of awesome plugins, and more are being added every week. + +This guide lists a number of best practices for publishing a Leaflet plugin that meets the quality standards of Leaflet itself. Also available [in the repo](https://github.com/Leaflet/Leaflet/blob/master/PLUGIN-GUIDE.md). + +### Presentation + +#### Repository + +The best place to put your Leaflet plugin to is a separate [GitHub](http://github.com) repository. +If you create a collection of plugins for different uses, +don't put them in one repo — +it's usually easier to work with small, self-contained plugins in individual repositories. + +#### Demo + +The most essential thing to do when publishing a plugin is to include a demo that showcases what the plugin does — +it's usually the first thing people will look for. + +The easiest way to put up a demo is using [GitHub Pages](http://pages.github.com/). +A good [starting point](https://help.github.com/articles/creating-project-pages-manually) is creating a `gh-pages` branch in your repo and adding an `index.html` page to it — +after pushing, it'll be published as `http://.github.io/`. + +#### Readme + +The next thing you need to have is a descriptive `README.md` in the root of the repo (or a link to a website with a similar content). +At a minimum it should contain the following items: + +- name of the plugin +- a simple, concise description of what it does +- requirements + - Leaflet version + - other external dependencies (if any) + - browser / device compatibility +- links to demos +- instructions for including the plugin +- simple usage code example +- API reference (methods, options, events) + +#### License + +Every open source repository should include a license. +If you don't know what open source license to choose for your code, +[MIT License](http://opensource.org/licenses/MIT) and [BSD 2-Clause License](http://opensource.org/licenses/BSD-2-Clause) are both good choices. +You can either put it in the repo as a `LICENSE` file or just link to the license from the Readme. + +### Code + +#### File Structure + +Keep the file structure clean and simple, +don't pile up lots of files in one place — +make it easy for a new person to find their way in your repo. + +A barebones repo for a simple plugin would look like this: + + my-plugin.js + README.md + +An example of a file structure for a more sophisticated plugin: + + /src JS source files + /dist minified plugin JS, CSS, images + /spec test files + /examples HTML examples of plugin usage + README.md + LICENSE + package.json + +#### Code Conventions + +Everyone's tastes are different, but it's important to be consistent with whatever conventions you choose for your plugin. + +For a good starting point, check out [Airbnb JavaScript Guide](https://github.com/airbnb/javascript). +Leaflet follows pretty much the same conventions +except for using smart tabs (hard tabs for indentation, spaces for alignment) +and putting a space after the `function` keyword. + +#### Plugin API + +Never expose global variables in your plugin.
+If you have a new class, put it directly in the `L` namespace (`L.MyPlugin`).
+If you inherit one of the existing classes, make it a sub-property (`L.TileLayer.Banana`).
+If you want to add new methods to existing Leaflet classes, you can do it like this: `L.Marker.include({myPlugin: …})`. + +Function, method and property names should be in `camelCase`.
+Class names should be in `CapitalizedCamelCase`. + +If you have a lot of arguments in your function, consider accepting an options object instead (putting default values where possible so that users don't need specify all of them): + + // bad + marker.myPlugin('bla', 'foo', null, {}, 5, 0); + + // good + marker.myPlugin('bla', { + optionOne: 'foo', + optionThree: 5 + }); + +And most importantly, keep it simple. Leaflet is all about *simplicity*. + +Cheers,
+Vladimir. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-11-18-leaflet-0-7-released-plans-for-future.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-11-18-leaflet-0-7-released-plans-for-future.md new file mode 100644 index 000000000..96b5d2a4d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2013-11-18-leaflet-0-7-released-plans-for-future.md @@ -0,0 +1,56 @@ +--- +layout: post +title: Leaflet 0.7 Release, MapBox and Plans for Future +description: Leaflet 0.7 Released — with IE11 touch support, upscaling tiles and tons of other improvements and bugfixes! Meanwhile, I've joined the MapBox team full-time. +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +_Leaflet 0.7 Released — with IE11 touch support, upscaling tiles and tons of other improvements and bugfixes! Meanwhile, I've joined the MapBox team full-time..._ + +After another 5 months of active development with [lots of contributors involved](https://github.com/Leaflet/Leaflet/graphs/contributors?from=2013-06-27&to=2013-11-18&type=c), I'm happy to announce the **release of Leaflet 0.7** stable. + +This is a bugfix-heavy release — as Leaflet becomes more and more stable feature-wise, the focus shifts towards stability, usability and API improvements over new features. I've also been holding back some of the planned deep refactorings (which I'll talk about later in the post) until 0.7 is released, so that the heavy risky stuff is done at the beginning of the release cycle, leaving plenty of room to catch bugs and incompatible changes that can unintentionally break existing apps. + +### Joining MapBox + +In other news, I [joined the MapBox team full-time](https://www.mapbox.com/blog/vladimir-agafonkin-joins-mapbox/). This is extremely exciting for me, as this was my dream job for quite a while — [MapBox](https://www.mapbox.com) have changed the world of interactive mapping forever with all their amazing work, having some of the greatest geomapping engineers and designers of the world working together, pushing the boundaries of what's possible and inspiring others every day. + +For Leaflet, this can only mean very good things — much more time on Leaflet development, more enthusiasm, more play, more crazy experiments with maps (like [this one](https://www.mapbox.com/blog/dynamic-hill-shading/)), and lots of learning. I'm now one of the happiest map geeks ever. Stay tuned for tons of awesome! + +### 0.7 changes + +You can check out the [detailed changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md#07-dev-master) of what's already done over the recent months for 0.7 (about 90 improvements and bugfixes), but I'd like to mention some highlights: + +* Added the ability to **upscale tiles** to higher zoom levels (e.g. have zoom 19-20 when the source has 18 max). +* Added support for **IE11 touch devices**. MS unexpectedly broke their pointer API compatibility between Developer Preview and final IE11 release, and we eventually rewrote quite a bit of code to make everything work smoothly across all IE versions (both dekstop & mobile), fixing a bunch of IE10 bugs along the way as well. +* Officially **dropped IE6 support** (nobody cares anyway) and cleaned up/fixed IE7-8 styles. +* Dropped the need for **IE conditional comment** when including Leaflet, making the snippet much simpler — all IE7/8-specific styles got simplified and moved to the main `leaflet.css` file. +* Fixed an **obscure iOS7 memory leak** that crashed Safari when you tried to create several thousands of layers (e.g. markers for clustering). I still don't understand why it happens, but we managed to fix it with a bit of trickery. +* Fixed a critical **Chrome for Android** bug that made the tiles disappear after zooming on some devices. +* Removed some **Earth-related hardcode** in TileLayer implementation to make it easier for plugins like Proj4Leaflet to handle complex projections without horrible hacks. Some other work in this direction to follow in 0.8. +* Improved **panning performance** on complex pages with significant number of elements — we found out that simple things like setting a different cursor to `document` (for a "grabbing" hand) caused noticeable performance hit on some browsers (Chrome in particular). +* **Changed the way maxBounds works**, not enforcing a derived `minZoom` from it but restricting panning across lower zoom levels, along with some tricks to make it play better with panning inertia or offset zooming, etc. + +### Plans for 0.8 + +There are several big undertakings in refactoring Leaflet that I'd want to switch to immediately after releasing 0.7 — I've been holding them off for too long, and they'll be extremely beneficial for plugin and Leaflet-based API authors. Some of them are already in progress. + +* Refactoring the **layers** architecture. Currently there's a lot of duplication of logic across implementation of different layers (map, markers, vector layers, etc.), specifically event handling, zoom animation logic, zIndex and pane handling (what appears on top of what etc.). Making the code consistent, more universal and shared across different layers will make it much easier to customize layers and make your own (e.g. integrate d3, etc.) +* Splitting the huge TileLayer implementation into **GridLayer and TileLayer**, separating image tiles-related logic and grid-logic that will make other grid-like layer implementations (e.g. UTFGrid interaction or tiled GeoJSON) much simpler. +* Refactoring **zoom animation logic** to make the long-awaited Easey-style animations (zoom-panning between points) possible. +* Refactoring **projections** code to make it easier to set up flat maps and weird projections and customize how Leaflet handles them. +* Refactoring the **vector layers** code to make it possible to use different rendering backends (Canvas, SVG, etc.) for different layers on the same map and switch between them easily. This will also open it up for interesting extensions, like indexing layers with [RBush](https://github.com/mourner/rbush) for fast interaction features. + +While it's an ambitious plan and it may take more than one stable release, finishing all those refactorings will mean that Leaflet is getting ready for a 1.0 release. + +Another direction I'd like to focus on after releasing 0.7 is **website and documentation improvements**. First, Leaflet is begging for **more step-by-step tutorials** (with more advanced features like custom layers, custom controls, etc.), and I'd love to do a docs/tutorials sprint some time in future. Second, the presentation could be significantly improved — adding a prominent visual **showcase** or app gallery, making Leaflet users more prominent with some logos and quotes/testimonials, and updating the layout/design for a more stylish, clean look, etc. + +Hope that gives a good glimpse of the stuff to expect from Leafet in near future, and don't hesitate to ask any questions in comments — I'll be happy to answer! + +Grab the CDN links or downloads for the new release on the [download page](../../../download.html) as always. Be sure to try it out on your apps and report any regressions so that we can patch them up immediately. And lets make some nice Twitter buzz about the release as usual! + +To all the people wo've been involved in Leaflet contributions, bug reports, mailing list, Twitter buzz, making awesome apps and spreading the word about Leaflet — thank you! You are the most awesome community ever. + +Cheers,
+Vladimir. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-07-01-leaflet-is-alive-and-kicking.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-07-01-leaflet-is-alive-and-kicking.md new file mode 100644 index 000000000..ab6fb526d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-07-01-leaflet-is-alive-and-kicking.md @@ -0,0 +1,21 @@ +--- +layout: post +title: Leaflet is Alive and Kicking, Stay Tuned for 1.0! +description: We're on the finishing line of releasing Leaflet 1.0 — the biggest and greatest Leaflet release ever. Meanwhile, I'm happy to present you the new redesigned Leaflet website! +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +I know this blog hasn't been updated for a long time — 1.5 years actually! But that's just because I'm a lazy blogger, and there has been _a lot_ going on with Leaflet during this time despite the lack of blog posts and major releases. + +We're on the finishing line of releasing Leaflet 1.0 — the biggest and greatest Leaflet release _ever_. The latest stable version, 0.7.3, is already perfect, so you won't believe how much awesome stuff we've managed to pack into the upcoming release — 914 commits later! But I'll leave that for a separate `1.0-beta1` blog post after we fix [that one last issue](https://github.com/Leaflet/Leaflet/pull/3307). + +Meanwhile, I'm happy to present you the new redesigned [Leaflet website](https://leafletjs.com/)! Now finally mobile-friendly, simple, clean, minimal and modern, just like the library itself. Also notice the floating menu when scrolling down the [Docs](/reference.html) and [Plugins](/plugins.html) pages, a highly requested feature that'll make navigation much easier. Big thanks to [Rowan Hogan](https://github.com/rowanhogan) for the help with the new design! + +P.S. I recently made a quirky 13-minute video for the [Geospatial World Forum](http://www.geospatialworldforum.org/), sharing the fun story behind Leaflet and how it became what it is today. Watch it and share it with your geofriends so that we can make the GIS world fun again! + +Love,
+Vladimir. + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-07-15-leaflet-1.0-beta1-released.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-07-15-leaflet-1.0-beta1-released.md new file mode 100644 index 000000000..2c730606d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-07-15-leaflet-1.0-beta1-released.md @@ -0,0 +1,60 @@ +--- +layout: post +title: Announcing Leaflet 1.0 beta 1 +description: Leaflet 1.0 beta 1 released. It's the biggest Leaflet release ever, with tons of improvements and bugfixes. We're starting a short beta release cycle, and need your help testing the release. +author: Vladimir Agafonkin +authorsite: http://agafonkin.com/en +--- + +Over the past year, we set out on an ambitious quest to implement pretty much all the features Leaflet users have been asking for years, while heavily focusing on performance, code cleanup and stabilizing the API. It was an extremely challenging road with many bumps, but now we're finally approaching the finish line. + +Today, I'm happy and proud to announce the release of *Leaflet 1.0 beta 1*, our first formal release after more than a year of work and a thousand commits by 36 contributors. + +### What's new + +1.0 will be the best Leaflet release ever, bringing a _huge_ amount of improvements and bugfixes. Highlights of the release include: + +- _huge_ performance improvements, especially for vector layers +- flyover animations (zooming and panning in a curve with `map.flyTo`) +- fractional zoom level support (`map.setZoom(12.34)`) +- much nicer tile loading with less flickering +- custom pane management (including multiple vector layer panes) +- better support for non-standard projections +- more accessibility features +- lots of bugfixes and stability improvements + +A much more detailed list of changes can be found [in the changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md) (beware, it's a long read). + +![](https://camo.githubusercontent.com/07c492b230f1a3762118eaf457f0cc182fb0a98d/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f32353339352f313936353934392f32613934343166342d383263312d313165332d393836372d6230343033663266643966372e676966) + +### Beta cycle and upgrading + +The release sports a number of minor breaking API changes, and some of the plugins will have to be updated. To make the upgrade less painful, we're doing a short beta cycle before the final 1.0 to allow users and plugin developers to catch up to the changes while we find and fix remaining issues. + +A lot of effort since the last stable release has been put into refactoring. Many changes that we made are not visible to users, but make the source code much simpler and easier to understand and also open up many new possibilities for our wonderful community of plugin developers. Basically, half of Leaflet code was fully rewritten under the hood, and now the codebase is ready for some pretty extreme extensions (who just said "rotation" and "WebGL"?). + +We plan to write a comprehensive 1.0 upgrade guide before the release. Meanwhile, if something breaks after you upgrade to 1.0-beta, please look through the changelog. If you can't find the corresponding breaking change, please file a GitHub issue. + +The API reference for 1.0 is temporarily [available here](http://mourner.github.io/Leaflet/reference.html). It's built from Leaflet `gh-pages-master` branch — fixes and additions are welcome! + +### Get the new release + +Test out the new release on your app, and help us catch remaining issues to bring the final 1.0 close to perfection! + +You can use our CDN: + + + + +The release is also available through NPM, Bower, and [GitHub download](https://github.com/Leaflet/Leaflet/archive/v1.0.0-beta.1.zip). + +### Thank you + +I'm incredibly thankful to everyone who made this release possible — by using the library, spreading the word about it, reporting issues and sending your contributions. Your help is invaluable! + +Special thanks to [Iván Sánchez](https://github.com/IvanSanchez), [Yohan Boniface](https://github.com/yohanboniface), [John Firebaugh](https://github.com/jfirebaugh), [Dave Leaver](https://github.com/danzel), [Patrick Arlt](https://github.com/patrickarlt), [Per Liedman](https://github.com/perliedman), [Jake Wilson](https://github.com/Jakobud) and [Steve Kashishian](https://github.com/snkashis) for lots of amazing contributions and support throughout the last year. All these people are now a part of the core Leaflet team. Keep'em coming! + +![](https://www.reactiongifs.com/r/msy.gif) + +Love,
+Vladimir. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-09-01-leaflet-0.7.4-released.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-09-01-leaflet-0.7.4-released.md new file mode 100644 index 000000000..874037018 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-09-01-leaflet-0.7.4-released.md @@ -0,0 +1,29 @@ +--- +layout: post +title: Leaflet 0.7.5 Release +description: Leaflet 0.7.5 released, containing bugfixes and backports. +author: Iván Sánchez Ortega +--- + +While the Leaflet development team is busy with the 1.0 betas, there have been a few bugs affecting 0.7.3, important enough to spend some effort in porting a fix back. They are not much, though: + +- Workarounds for issues derived from new browsers (touch-capable browsers, tile loading in recent Chrome) +- Backport fixes for styling and events for canvas-based vector layers +- Fix edge cases involving `maxZoom`, `minZoom`, `maxNativeZoom` on tile layers and popup events +- Revert a regression bug in 0.7.4 which conflicted with marker clusters + +The detailed list of changes can be found [in the changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md#074-sep-01-2015) + +The fact that it has been over *a year and half* since the last stable release should be a testament of the quality and stability of the Leaflet API. If you think that development of Leaflet 1.0 is taking a long time, remember that we want to keep the same level of quality for the final 1.0 release. + +The 0.7.x releases will not implement new features. Stay tuned for more news on the 1.0 beta releases instead! + + +### Get the update + +Developers using Leaflet 0.7.3 are advised to upgrade to 0.7.5 to prevent problems arising from modern browers. + +The release is also available through NPM, Bower, [direct download](http://cdn.leafletjs.com/downloads/leaflet-0.7.5.zip), or through our CDN: + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-10-14-leaflet-1.0-beta2-released.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-10-14-leaflet-1.0-beta2-released.md new file mode 100644 index 000000000..aaf46c609 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2015-10-14-leaflet-1.0-beta2-released.md @@ -0,0 +1,35 @@ +--- +layout: post +title: Announcing Leaflet 1.0 beta 2 +description: Leaflet 1.0 beta 2 released, fixing over 50 bugs over the previous beta. +author: Iván Sánchez +authorsite: http://ivan.sanchezortega.es +--- + +Since the 1.0.0-beta1 release a couple months ago, the Leaflet team has been busy fixing bugs reported by users of beta1, plus a few small changes to the API that were overlooked previously. You can find the complete list of fixes and changes in the [1.0.0-beta2 changelog](https://github.com/Leaflet/Leaflet/blob/master/CHANGELOG.md#10-beta2-october-14-2015). + +### Get the new release + +As with previous releases, you can use our CDN: + + + + +The release is also available through NPM (`npm install leaflet@beta`), Bower, and [GitHub download](https://github.com/Leaflet/Leaflet/archive/v1.0.0-beta.2.zip). + +The API reference for 1.0 is still temporarily [available here](http://mourner.github.io/Leaflet/reference.html). + +### The future + +Work is not yet done, though. There will probably be a beta3, sporting bugfixes in the tile loading algorithm, API methods for fractional zoom and documentation improvements, among other pending items. + +We hope to have fixed the most problematic bugs in the previous beta, but maybe there is a bug that we are not aware of. We encourage users of 1.0.0-beta1 to upgrade to beta2 and keep reporting problems. + +Help us help you by taking a minute to learn [how to write a good bug report](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html), and check if a [similar issue](https://github.com/Leaflet/Leaflet/issues) has already been reported. Or better even, dive into the Leaflet code if you can! + +Last but not least, huge thanks to everybody using Leaflet. Keep creating great maps! + +**Note to plugin developers**: we encourage you to upgrade your plugins to be compatible with the latest beta release. The 1.0 API is pretty stable at this point and many users are starting to use the beta version in production. Additionally, as 1.0 final release approaches, we want to get more serious about the quality of plugins that get [on the official list](https://leafletjs.com/plugins.html), making sure they're maintained and compatible with recent Leaflet releases. + +Best, +Iván & Vladimir & Yohan. diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2016-03-20-debugging-touch-interactions.md b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2016-03-20-debugging-touch-interactions.md new file mode 100644 index 000000000..4d7a300c3 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/_posts/2016-03-20-debugging-touch-interactions.md @@ -0,0 +1,101 @@ +--- +layout: post +title: Debugging touch interactions +description: To debug Leaflet, sometimes you need to create a new tool. +author: Iván Sánchez +authorsite: http://ivan.sanchezortega.es +--- + + +Most of the time, fixing bugs in the Leaflet code is a breeze. The code is simple, easy to read (for the most part) and well structured. Code conventions and unit tests make it easy for newcomers to try some modifications to the core code. During the past few months we've sent a few simple bug reports to the folks at [Your First PR](https://yourfirstpr.github.io/) - we love to see first-timers contributing fixes to Leaflet! + + +Some of the difficulties of maintaining/developing a javascript library like Leaflet is making sure that everything works on every major browser out there. A technique that works on Firefox on a Ubuntu desktop might result in glitches in Safari on a Macbook; something that works in Edge on Windows 10 might break completely in Chrome on Android. + +Fortunately, all of the browser-specific hacks in Leaflet can be easily seen by looking at the [references to `L.Browser`](https://github.com/search?q=Browser+repo%3ALeaflet%2FLeaflet+language%3AJavaScript+extension%3Ajs+path%3A%2Fsrc&ref=searchresults&type=Code&utf8=%E2%9C%93) in the code. + +This can lead to somewhat [undesirable code](https://github.com/Leaflet/Leaflet/blob/master/src/dom/DomEvent.DoubleTap.js#L65) sometimes: + +
    // On some platforms (notably, chrome on win10 + touchscreen + mouse),
+    // the browser doesn't fire touchend/pointerup events but does fire
+    // native dblclicks. See #4127.
+    if (!L.Browser.edge) {
+    	obj.addEventListener('dblclick', handler, false);
+    }
+
+ +I've been told more than a few times by browser developers that browser sniffing is wrong, and that feature detection is right. I mean, detecting 3D CSS transforms and HTML5 `
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.2.0.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.2.0.html new file mode 100644 index 000000000..6d0811afc --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.2.0.html @@ -0,0 +1,23652 @@ +--- +layout: v2 +title: Documentation +bodyclass: api-page +--- + +

Leaflet API reference

+ +

This reference reflects Leaflet 1.2.0. Check this list if you are using a different version of Leaflet.

+ +
+ +
+

UI Layers

+ +

Raster Layers

+ +

Vector Layers

+ +
+
+

Other Layers

+ +

Basic Types

+ +

Controls

+ +
+
+ + + + + + +

Utility

+ +

DOM Utility

+ +
+
+

Base Classes

+ + +

Misc

+ +
+
+ +

Map

The central class of the API — it is used to create a map on a page and manipulate it.

+ +
+

Usage example

+ +
+ + + + + +
// initialize the map on the "map" div with a given center and zoom
+var map = L.map('map', {
+    center: [51.505, -0.09],
+    zoom: 13
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.map(<String> id, <Map options> options?)Instantiates a map object given the DOM ID of a <div> element +and optionally an object literal with Map options.
L.map(<HTMLElement> el, <Map options> options?)Instantiates a map object given an instance of a <div> HTML element +and optionally an object literal with Map options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
preferCanvasBoolean + falseWhether Paths should be rendered on a Canvas renderer. +By default, all Paths are rendered in a SVG renderer.
+ +
+ +

Control options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionControlBoolean + trueWhether a attribution control is added to the map by default.
zoomControlBoolean + trueWhether a zoom control is added to the map by default.
+ +
+ +

Interaction Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
closePopupOnClickBoolean + trueSet it to false if you don't want popups to close when user clicks the map.
zoomSnapNumber + 1Forces the map's zoom level to always be a multiple of this, particularly +right after a fitBounds() or a pinch-zoom. +By default, the zoom level snaps to the nearest integer; lower values +(e.g. 0.5 or 0.1) allow for greater granularity. A value of 0 +means the zoom level will not be snapped after fitBounds or a pinch-zoom.
zoomDeltaNumber + 1Controls how much the map's zoom level will change after a +zoomIn(), zoomOut(), pressing + +or - on the keyboard, or using the zoom controls. +Values smaller than 1 (e.g. 0.5) allow for greater granularity.
trackResizeBoolean + trueWhether the map automatically handles browser window resize to update itself.
boxZoomBoolean + trueWhether the map can be zoomed to a rectangular area specified by +dragging the mouse while pressing the shift key.
doubleClickZoomBoolean|String + trueWhether the map can be zoomed in by double clicking on it and +zoomed out by double clicking while holding shift. If passed +'center', double-click zoom will zoom to the center of the + view regardless of where the mouse was.
draggingBoolean + trueWhether the map be draggable with mouse/touch or not.
+ +
+ +

Map State Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
crsCRS + L.CRS.EPSG3857The Coordinate Reference System to use. Don't change this if you're not +sure what it means.
centerLatLng + undefinedInitial geographic center of the map
zoomNumber + undefinedInitial map zoom level
minZoomNumber + *Minimum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the lowest of their minZoom options will be used instead.
maxZoomNumber + *Maximum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the highest of their maxZoom options will be used instead.
layersLayer[] + []Array of layers that will be added to the map initially
maxBoundsLatLngBounds + nullWhen this option is set, the map restricts the view to the given +geographical bounds, bouncing the user back if the user tries to pan +outside the view. To set the restriction dynamically, use +setMaxBounds method.
rendererRenderer + *The default method for drawing vector layers on the map. L.SVG +or L.Canvas by default depending on browser support.
+ +
+ +

Animation Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomAnimationBoolean + trueWhether the map zoom animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
zoomAnimationThresholdNumber + 4Won't animate zoom if the zoom difference exceeds this value.
fadeAnimationBoolean + trueWhether the tile fade animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
markerZoomAnimationBoolean + trueWhether markers animate their zoom with the zoom animation, if disabled +they will disappear for the length of the animation. By default it's +enabled in all browsers that support CSS3 Transitions except Android.
transform3DLimitNumber + 2^23Defines the maximum size of a CSS translation transform. The default +value should not be changed unless a web browser positions layers in +the wrong place after doing a large panBy.
+ +
+ +

Panning Inertia Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
inertiaBoolean + *If enabled, panning of the map will have an inertia effect where +the map builds momentum while dragging and continues moving in +the same direction for some time. Feels especially nice on touch +devices. Enabled by default unless running on old Android devices.
inertiaDecelerationNumber + 3000The rate with which the inertial movement slows down, in pixels/second².
inertiaMaxSpeedNumber + InfinityMax speed of the inertial movement, in pixels/second.
easeLinearityNumber + 0.2
worldCopyJumpBoolean + falseWith this option enabled, the map tracks when you pan to another "copy" +of the world and seamlessly jumps to the original one so that all overlays +like markers and vector layers are still visible.
maxBoundsViscosityNumber + 0.0If maxBounds is set, this option will control how solid the bounds +are when dragging the map around. The default value of 0.0 allows the +user to drag outside the bounds at normal speed, higher values will +slow down map dragging outside bounds, and 1.0 makes the bounds fully +solid, preventing the user from dragging outside the bounds.
+ +
+ +

Keyboard Navigation Options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
keyboardBoolean + trueMakes the map focusable and allows users to navigate the map with keyboard +arrows and +/- keys.
keyboardPanDeltaNumber + 80Amount of pixels to pan when pressing an arrow key.
+ +
+ +

Mousewheel options

+ + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
scrollWheelZoomBoolean|String + trueWhether the map can be zoomed by using the mouse wheel. If passed 'center', +it will zoom to the center of the view regardless of where the mouse was.
wheelDebounceTimeNumber + 40Limits the rate at which a wheel can fire (in milliseconds). By default +user can't zoom via wheel more often than once per 40 ms.
wheelPxPerZoomLevelNumber + 60How many scroll pixels (as reported by L.DomEvent.getWheelDelta) +mean a change of one full zoom level. Smaller values will make wheel-zooming +faster (and vice versa).
+ +
+ +

Touch interaction options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tapBoolean + trueEnables mobile hacks for supporting instant taps (fixing 200ms click +delay on iOS/Android) and touch holds (fired as contextmenu events).
tapToleranceNumber + 15The max number of pixels a user can shift his finger during touch +for it to be considered a valid tap.
touchZoomBoolean|String + *Whether the map can be zoomed by touch-dragging with two fingers. If +passed 'center', it will zoom to the center of the view regardless of +where the touch events (fingers) were. Enabled for touch-capable web +browsers except for old Androids.
bounceAtZoomLimitsBoolean + trueSet it to false if you don't want the map to zoom beyond min/max zoom +and then bounce back when pinch-zooming.
+ +
+ + +
+

Events

+ +
+ +

Layer events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
baselayerchange + LayersControlEventFired when the base layer is changed through the layer control.
overlayadd + LayersControlEventFired when an overlay is selected through the layer control.
overlayremove + LayersControlEventFired when an overlay is deselected through the layer control.
layeradd + LayerEventFired when a new layer is added to the map.
layerremove + LayerEventFired when some layer is removed from the map
+ +
+ +

Map state change events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
zoomlevelschange + EventFired when the number of zoomlevels on the map is changed due +to adding or removing a layer.
resize + ResizeEventFired when the map is resized.
unload + EventFired when the map is destroyed with remove method.
viewreset + EventFired when the map needs to redraw its content (this usually happens +on map zoom or load). Very useful for creating custom overlays.
load + EventFired when the map is initialized (when its center and zoom are set +for the first time).
zoomstart + EventFired when the map zoom is about to change (e.g. before zoom animation).
movestart + EventFired when the view of the map starts changing (e.g. user starts dragging the map).
zoom + EventFired repeatedly during any change in zoom level, including zoom +and fly animations.
move + EventFired repeatedly during any movement of the map, including pan and +fly animations.
zoomend + EventFired when the map has changed, after any animations.
moveend + EventFired when the center of the map stops changing (e.g. user stopped +dragging the map).
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup is opened in the map
popupclose + PopupEventFired when a popup in the map is closed
autopanstart + EventFired when the map starts autopanning when opening a popup.
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip is opened in the map.
tooltipclose + TooltipEventFired when a tooltip in the map is closed.
+ +
+ +

Location events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
locationerror + ErrorEventFired when geolocation (using the locate method) failed.
locationfound + LocationEventFired when geolocation (using the locate method) +went successfully.
+ +
+ +

Interaction events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the map.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the map.
mousedown + MouseEventFired when the user pushes the mouse button on the map.
mouseup + MouseEventFired when the user releases the mouse button on the map.
mouseover + MouseEventFired when the mouse enters the map.
mouseout + MouseEventFired when the mouse leaves the map.
mousemove + MouseEventFired while the mouse moves over the map.
contextmenu + MouseEventFired when the user pushes the right mouse button on the map, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
keypress + KeyboardEventFired when the user presses a key from the keyboard while the map is focused.
preclick + MouseEventFired before mouse click on the map (sometimes useful when you +want something to happen on click before any existing click +handlers start running).
+ +
+ +

Other Methods

+ + + + + + + + + + + + + +
EventDataDescription
zoomanim + ZoomAnimEventFired on every frame of a zoom animation
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getRenderer(<Path> layer)Renderer

Returns the instance of Renderer that should be used to render the given +Path. It will ensure that the renderer options of the map and paths +are respected, and that the renderers do exist on the map.

+
+ +
+ +

Methods for Layers and Controls

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addControl(<Control> control)this

Adds the given control to the map

+
removeControl(<Control> control)this

Removes the given control from the map

+
addLayer(<Layer> layer)this

Adds the given layer to the map

+
removeLayer(<Layer> layer)this

Removes the given layer from the map.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the map

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the map, optionally specifying context of the iterator function.

+
map.eachLayer(function(layer){
+    layer.bindPopup('Hello');
+});
+
openPopup(<Popup> popup)this

Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).

+
openPopup(<String|HTMLElement> content, <LatLng> latlng, <Popup options> options?)this

Creates a popup with the specified content and options and opens it in the given point on a map.

+
closePopup(<Popup> popup?)this

Closes the popup previously opened with openPopup (or the given one).

+
openTooltip(<Tooltip> tooltip)this

Opens the specified tooltip.

+
openTooltip(<String|HTMLElement> content, <LatLng> latlng, <Tooltip options> options?)this

Creates a tooltip with the specified content and options and open it.

+
closeTooltip(<Tooltip> tooltip?)this

Closes the tooltip given as parameter.

+
+ +
+ +

Methods for modifying map state

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setView(<LatLng> center, <Number> zoom, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) with the given +animation options.

+
setZoom(<Number> zoom, <Zoom/pan options> options?)this

Sets the zoom of the map.

+
zoomIn(<Number> delta?, <Zoom options> options?)this

Increases the zoom of the map by delta (zoomDelta by default).

+
zoomOut(<Number> delta?, <Zoom options> options?)this

Decreases the zoom of the map by delta (zoomDelta by default).

+
setZoomAround(<LatLng> latlng, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified geographical point on the map +stationary (e.g. used internally for scroll zoom and double-click zoom).

+
setZoomAround(<Point> offset, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.

+
fitBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets a map view that contains the given geographical bounds with the +maximum zoom level possible.

+
fitWorld(<fitBounds options> options?)this

Sets a map view that mostly contains the whole world with the maximum +zoom level possible.

+
panTo(<LatLng> latlng, <Pan options> options?)this

Pans the map to a given center.

+
panBy(<Point> offset, <Pan options> options?)this

Pans the map by a given number of pixels (animated).

+
flyTo(<LatLng> latlng, <Number> zoom?, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) performing a smooth +pan-zoom animation.

+
flyToBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets the view of the map with a smooth animation like flyTo, +but takes a bounds parameter like fitBounds.

+
setMaxBounds(<Bounds> bounds)this

Restricts the map view to the given bounds (see the maxBounds option).

+
setMinZoom(<Number> zoom)this

Sets the lower limit for the available zoom levels (see the minZoom option).

+
setMaxZoom(<Number> zoom)this

Sets the upper limit for the available zoom levels (see the maxZoom option).

+
panInsideBounds(<LatLngBounds> bounds, <Pan options> options?)this

Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.

+
invalidateSize(<Zoom/Pan options> options)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default. If options.pan is false, panning will not occur. +If options.debounceMoveend is true, it will delay moveend event so +that it doesn't happen often even if the method is called many +times in a row.

+
invalidateSize(<Boolean> animate)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default.

+
stop()this

Stops the currently running panTo or flyTo animation, if any.

+
+ +
+ +

Geolocation methods

+ + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
locate(<Locate options> options?)this

Tries to locate the user using the Geolocation API, firing a locationfound +event with location data on success or a locationerror event on failure, +and optionally sets the map view to the user's location with respect to +detection accuracy (or to the world view if geolocation failed). +Note that, if your page doesn't use HTTPS, this method will fail in +modern browsers (Chrome 50 and newer) +See Locate options for more details.

+
stopLocate()this

Stops watching location previously initiated by map.locate({watch: true}) +and aborts resetting the map view if map.locate was called with +{setView: true}.

+
+ +
+ +

Other Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHandler(<String> name, <Function> HandlerClass)this

Adds a new Handler to the map, given its name and constructor function.

+
remove()this

Destroys the map and clears all related event listeners.

+
createPane(<String> name, <HTMLElement> container?)HTMLElement

Creates a new map pane with the given name if it doesn't exist already, +then returns it. The pane is created as a child of container, or +as a child of the main map pane if not set.

+
getPane(<String|HTMLElement> pane)HTMLElement

Returns a map pane, given its name or its HTML element (its identity).

+
getPanes()Object

Returns a plain object containing the names of all panes as keys and +the panes as values.

+
getContainer()HTMLElement

Returns the HTML element that contains the map.

+
whenReady(<Function> fn, <Object> context?)this

Runs the given function fn when the map gets initialized with +a view (center and zoom) and at least one layer, or immediately +if it's already initialized, optionally passing a function context.

+
+ +
+ +

Methods for Getting Map State

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getCenter()LatLng

Returns the geographical center of the map view

+
getZoom()Number

Returns the current zoom level of the map view

+
getBounds()LatLngBounds

Returns the geographical bounds visible in the current map view

+
getMinZoom()Number

Returns the minimum zoom level of the map (if set in the minZoom option of the map or of any layers), or 0 by default.

+
getMaxZoom()Number

Returns the maximum zoom level of the map (if set in the maxZoom option of the map or of any layers).

+
getBoundsZoom(<LatLngBounds> bounds, <Boolean> inside?)Number

Returns the maximum zoom level on which the given bounds fit to the map +view in its entirety. If inside (optional) is set to true, the method +instead returns the minimum zoom level on which the map view fits into +the given bounds in its entirety.

+
getSize()Point

Returns the current size of the map container (in pixels).

+
getPixelBounds()Bounds

Returns the bounds of the current map view in projected pixel +coordinates (sometimes useful in layer and overlay implementations).

+
getPixelOrigin()Point

Returns the projected pixel coordinates of the top left point of +the map layer (useful in custom layer and overlay implementations).

+
getPixelWorldBounds(<Number> zoom?)Bounds

Returns the world's bounds in pixel coordinates for zoom level zoom. +If zoom is omitted, the map's current zoom level is used.

+
+ +
+ +

Conversion Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getZoomScale(<Number> toZoom, <Number> fromZoom)Number

Returns the scale factor to be applied to a map transition from zoom level +fromZoom to toZoom. Used internally to help with zoom animations.

+
getScaleZoom(<Number> scale, <Number> fromZoom)Number

Returns the zoom level that the map would end up at, if it is at fromZoom +level and everything is scaled by a factor of scale. Inverse of +getZoomScale.

+
project(<LatLng> latlng, <Number> zoom)Point

Projects a geographical coordinate LatLng according to the projection +of the map's CRS, then scales it according to zoom and the CRS's +Transformation. The result is pixel coordinate relative to +the CRS origin.

+
unproject(<Point> point, <Number> zoom)LatLng

Inverse of project.

+
layerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the origin pixel, +returns the corresponding geographical coordinate (for the current zoom level).

+
latLngToLayerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the origin pixel.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +map's CRS's wrapLat and wrapLng properties, if they are outside the +CRS's bounds. +By default this means longitude is wrapped around the dateline so its +value is between -180 and +180 degrees.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring that +its center is within the CRS's bounds. +By default this means the center longitude is wrapped around the dateline so its +value is between -180 and +180 degrees, and the majority of the bounds +overlaps the CRS's bounds.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates according to +the map's CRS. By default this measures distance in meters.

+
containerPointToLayerPoint(<Point> point)Point

Given a pixel coordinate relative to the map container, returns the corresponding +pixel coordinate relative to the origin pixel.

+
layerPointToContainerPoint(<Point> point)Point

Given a pixel coordinate relative to the origin pixel, +returns the corresponding pixel coordinate relative to the map container.

+
containerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the map container, returns +the corresponding geographical coordinate (for the current zoom level).

+
latLngToContainerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the map container.

+
mouseEventToContainerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to the +map container where the event took place.

+
mouseEventToLayerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to +the origin pixel where the event took place.

+
mouseEventToLatLng(<MouseEvent> ev)LatLng

Given a MouseEvent object, returns geographical coordinate where the +event took place.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Handlers

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
boxZoom + HandlerBox (shift-drag with mouse) zoom handler.
doubleClickZoom + HandlerDouble click zoom handler.
dragging + HandlerMap dragging handler (by both mouse and touch).
keyboard + HandlerKeyboard navigation handler.
scrollWheelZoom + HandlerScroll wheel zoom handler.
tap + HandlerMobile touch hacks (quick tap and touch hold) handler.
touchZoom + HandlerTouch zoom handler.
+ +
+ + +
+

Map panes

+ +
+ + + +
Panes are DOM elements used to control the ordering of layers on the map. You +can access panes with map.getPane or +map.getPanes methods. New panes can be created with the +map.createPane method. +Every map has the following default panes that differ only in zIndex.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PaneTypeZ-indexDescription
mapPaneHTMLElement + 'auto'Pane that contains all other map panes
tilePaneHTMLElement + 200Pane for GridLayers and TileLayers
overlayPaneHTMLElement + 400Pane for vector overlays (Paths), like Polylines and Polygons
shadowPaneHTMLElement + 500Pane for overlay shadows (e.g. Marker shadows)
markerPaneHTMLElement + 600Pane for Icons of Markers
tooltipPaneHTMLElement + 650Pane for tooltip.
popupPaneHTMLElement + 700Pane for Popups.
+ +
+ + +
+ +
+

Locate options

+ +
+ + + +
Some of the geolocation methods for Map take in an options parameter. This +is a plain javascript object with the following optional components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
watchBoolean + falseIf true, starts continous watching of location changes (instead of detecting it +once) using W3C watchPosition method. You can later stop watching using +map.stopLocate() method.
setViewBoolean + falseIf true, automatically sets the map view to the user location with respect to +detection accuracy, or to world view if geolocation failed.
maxZoomNumber + InfinityThe maximum zoom for automatic view setting when using setView option.
timeoutNumber + 10000Number of milliseconds to wait for a response from geolocation before firing a +locationerror event.
maximumAgeNumber + 0Maximum age of detected location. If less than this amount of milliseconds +passed since last geolocation response, locate will return a cached location.
enableHighAccuracyBoolean + falseEnables high accuracy, see description in the W3C spec.
+ +
+ + +
+ +
+

Zoom options

+ +
+ + + +
Some of the Map methods which modify the zoom level take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+ + +
+ +
+

Pan options

+ +
+ + + +
Some of the Map methods which modify the center of the map take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If true, panning will always be animated if possible. If false, it will +not animate panning, either resetting the map view if panning more than a +screen away, or just setting a new offset for the map pane (except for panBy +which always does the latter).
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+ + +
+ +
+

Zoom/pan options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +
+ +
+

FitBounds options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingTopLeftPoint + [0, 0]Sets the amount of padding in the top left corner of a map container that +shouldn't be accounted for when setting the view to fit bounds. Useful if you +have some control overlays on the map like a sidebar and you don't want them +to obscure objects you're zooming to.
paddingBottomRightPoint + [0, 0]The same for the bottom right corner of the map.
paddingPoint + [0, 0]Equivalent of setting both top left and bottom right padding to the same value.
maxZoomNumber + nullThe maximum possible zoom to use.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +

Marker

L.Marker is used to display clickable/draggable icons on the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.marker([50.5, 30.5]).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.marker(<LatLng> latlng, <Marker options> options?)Instantiates a Marker object given a geographical point and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconIcon + *Icon instance to use for rendering the marker. +See Icon documentation for details on how to customize the marker icon. +If not specified, a common instance of L.Icon.Default is used.
draggableBoolean + falseWhether the marker is draggable with mouse/touch or not.
keyboardBoolean + trueWhether the marker can be tabbed to with a keyboard and clicked by pressing enter.
titleString + ''Text for the browser tooltip that appear on marker hover (no tooltip by default).
altString + ''Text for the alt attribute of the icon image (useful for accessibility).
zIndexOffsetNumber + 0By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like 1000 (or high negative value, respectively).
opacityNumber + 1.0The opacity of the marker.
riseOnHoverBoolean + falseIf true, the marker will get on top of others when you hover the mouse over it.
riseOffsetNumber + 250The z-index offset used for the riseOnHover feature.
paneString + 'markerPane'Map pane where the markers icon will be added.
bubblingMouseEventsBoolean + falseWhen true, a mouse event on this marker will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + +
In addition to shared layer methods like addTo() and remove() and popup methods like bindPopup() you can also use the following methods:
+ + + + + + + + + + + + +
EventDataDescription
move + EventFired when the marker is moved via setLatLng or by dragging. Old and new coordinates are included in event arguments as oldLatLng, latlng.
+ +
+ +

Dragging events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
dragstart + EventFired when the user starts dragging the marker.
movestart + EventFired when the marker starts moving (because of dragging).
drag + EventFired repeatedly while the user drags the marker.
dragend + DragEndEventFired when the user stops dragging the marker.
moveend + EventFired when the marker stops moving (because of dragging).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the marker (as a GeoJSON Point Feature).

+
getLatLng()LatLng

Returns the current geographical position of the marker.

+
setLatLng(<LatLng> latlng)this

Changes the marker position to the given point.

+
setZIndexOffset(<Number> offset)this

Changes the zIndex offset of the marker.

+
setIcon(<Icon> icon)this

Changes the marker icon.

+
setOpacity(<Number> opacity)this

Changes the opacity of the marker.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Interaction handlers

+ +
Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see Handler methods). Example: +
marker.dragging.disable();
+
+ + + + + + + + + + + + +
PropertyTypeDescription
dragging + HandlerMarker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set marker.options.draggable).
+ +
+ + +

Used to open popups in certain places of the map. Use Map.openPopup to +open popups while making sure that only one popup is open at one time +(recommended for usability), or use Map.addLayer to open as many as you want.

+ +
+ + +
+ + + + + +

If you want to just bind a popup to marker click and then open it, it's really easy:

+
marker.bindPopup(popupContent).openPopup();
+
+

Path overlays like polylines also have a bindPopup method. +Here's a more complicated way to open a popup on a map:

+
var popup = L.popup()
+    .setLatLng(latlng)
+    .setContent('<p>Hello world!<br />This is a nice popup.</p>')
+    .openOn(map);
+
+ + + +
+ + +
+ + +
+ + + + + + + + + + + + + + +
FactoryDescription
+ +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +

Tooltip

Used to display small texts on top of map layers.

+ +
+

Usage example

+ +
+ + + + + +
marker.bindTooltip("my tooltip text").openTooltip();
+
+

Note about tooltip offset. Leaflet takes two options in consideration +for computing tooltip offseting:

+
    +
  • the offset Tooltip option: it defaults to [0, 0], and it's specific to one tooltip. +Add a positive x offset to move the tooltip to the right, and a positive y offset to +move it to the bottom. Negatives will move to the left and top.
  • +
  • the tooltipAnchor Icon option: this will only be considered for Marker. You +should adapt this value if you use a custom icon.
  • +
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tooltip(<Tooltip options> options?, <Layer> source?)Instantiates a Tooltip object given an optional options object that describes its appearance and location and an optional source object that is used to tag the tooltip with a reference to the Layer to which it refers.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'tooltipPane'Map pane where the tooltip will be added.
offsetPoint + Point(0, 0)Optional offset of the tooltip position.
directionString + 'auto'Direction where to open the tooltip. Possible values are: right, left, +top, bottom, center, auto. +auto will dynamicaly switch between right and left according to the tooltip +position on the map.
permanentBoolean + falseWhether to open the tooltip permanently or only on mouseover.
stickyBoolean + falseIf true, the tooltip will follow the mouse instead of being fixed at the feature center.
interactiveBoolean + falseIf true, the tooltip will listen to the feature events.
opacityNumber + 0.9Tooltip container opacity.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
classNameString + ''A custom CSS class name to assign to the popup.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer

Used to load and display tile layers on the map. Extends GridLayer.

+ +
+

Usage example

+ +
+ + + + + +
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
+
+ + + +
+ +

URL template

+ + + +

A string of the following form:

+
'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
+

{s} means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; a, b or c by default, can be omitted), {z} — zoom level, {x} and {y} — tile coordinates. {r} can be used to add "@2x" to the URL to load retina tiles. +You can use custom keys in the template, which will be evaluated from TileLayer options, like this:

+
L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
+
+ + +
+ + +
+

Creation

+ +
+ +

Extension methods

+ + + + + + + + + + + + +
FactoryDescription
L.tilelayer(<String> urlTemplate, <TileLayer options> options?)Instantiates a tile layer object given a URL template and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean + falseIf true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropiate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+ +

Extension methods

+ +
Layers extending TileLayer might reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
getTileUrl(<Object> coords)String

Called only internally, returns the URL for a tile given its coordinates. +Classes extending TileLayer can override this function to provide custom tile URL naming schemes.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer.WMS

Used to display WMS services as tile layers on the map. Extends TileLayer.

+ +
+

Usage example

+ +
+ + + + + +
var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
+    layers: 'nexrad-n0r-900913',
+    format: 'image/png',
+    transparent: true,
+    attribution: "Weather data © 2012 IEM Nexrad"
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tileLayer.wms(<String> baseUrl, <TileLayer.WMS options> options)Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.
+ +
+ + +
+

Options

+ +
+ + + +
If any custom options not documented here are used, they will be sent to the +WMS server as extra parameters in each request URL. This can be useful for +non-standard vendor WMS parameters.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
layersString + ''(required) Comma-separated list of WMS layers to show.
stylesString + ''Comma-separated list of WMS styles.
formatString + 'image/jpeg'WMS image format (use 'image/png' for layers with transparency).
transparentBoolean + falseIf true, the WMS service will return images with transparency.
versionString + '1.1.1'Version of the WMS service to use
crsCRS + nullCoordinate Reference System to use for the WMS requests, defaults to +map CRS. Don't change this if you're not sure what it means.
uppercaseBoolean + falseIf true, WMS request parameter keys will be uppercase.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean + falseIf true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setParams(<Object> params, <Boolean> noRedraw?)this

Merges an object with the new parameters and re-requests tiles on the current screen (unless noRedraw was set to true).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropiate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

ImageOverlay

Used to load and display a single image over specific bounds of the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
+    imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
+L.imageOverlay(imageUrl, imageBounds).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.imageOverlay(<String> imageUrl, <LatLngBounds> bounds, <ImageOverlay options> options?)Instantiates an image overlay object given the URL of the image and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean + falseIf true, the image will have its crossOrigin attribute set to ''. This is needed if you want to access image pixel data.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the tile layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the ImageOverlay layer has loaded its image
error + EventFired when the ImageOverlay layer has loaded its image
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers +Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
getElement()HTMLElement

Returns the instance of HTMLImageElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

VideoOverlay

Used to load and display a video player over specific bounds of the map. Extends ImageOverlay. +A video overlay uses the <video> +HTML5 element.

+ +
+

Usage example

+ +
+ + + + + +
var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
+    videoBounds = [[ 32, -130], [ 13, -100]];
+L.VideoOverlay(videoUrl, videoBounds ).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.videoOverlay(<String|Array|HTMLVideoElement> video, <LatLngBounds> bounds, <VideoOverlay options> options?)Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
autoplayBoolean + trueWhether the video starts playing automatically when loaded.
loopBoolean + trueWhether the video will loop back to the beginning when played.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean + falseIf true, the image will have its crossOrigin attribute set to ''. This is needed if you want to access image pixel data.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the tile layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the video has finished loading the first frame
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
error + EventFired when the ImageOverlay layer has loaded its image
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getElement()HTMLVideoElement

Returns the instance of HTMLVideoElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers +Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Path

An abstract class that contains options and constants shared between vector +overlays (Polygon, Polyline, Circle). Do not use it directly. Extends Layer.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.svg(<Renderer options> options?)Creates a SVG renderer with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polyline

A class for drawing polyline overlays on a map. Extends Path.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polyline from an array of LatLng points
+var latlngs = [
+    [45.51, -122.68],
+    [37.77, -122.43],
+    [34.04, -118.2]
+];
+var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polyline
+map.fitBounds(polyline.getBounds());
+
+

You can also pass a multi-dimensional array to represent a MultiPolyline shape:

+
// create a red polyline from an array of arrays of LatLng points
+var latlngs = [
+    [[45.51, -122.68],
+     [37.77, -122.43],
+     [34.04, -118.2]],
+    [[40.78, -73.91],
+     [41.83, -87.62],
+     [32.76, -96.72]]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polyline(<LatLng[]> latlngs, <Polyline options> options?)Instantiates a polyline object given an array of geographical points and +optionally an options object. You can create a Polyline object with +multiple separate lines (MultiPolyline) by passing an array of arrays +of geographic points.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polyline (as a GeoJSON LineString or MultiLineString Feature).

+
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polygon

A class for drawing polygon overlays on a map. Extends Polyline. +Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polygon from an array of LatLng points
+var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
+var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polygon
+map.fitBounds(polygon.getBounds());
+
+

You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:

+
var latlngs = [
+  [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+  [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+];
+
+

Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.

+
var latlngs = [
+  [ // first polygon
+    [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+    [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+  ],
+  [ // second polygon
+    [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
+  ]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polygon(<LatLng[]> latlngs, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Rectangle

A class for drawing rectangle overlays on a map. Extends Polygon.

+ +
+

Usage example

+ +
+ + + + + +
// define rectangle geographical bounds
+var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
+// create an orange rectangle
+L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
+// zoom the map to the rectangle bounds
+map.fitBounds(bounds);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.rectangle(<LatLngBounds> latLngBounds, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setBounds(<LatLngBounds> latLngBounds)this

Redraws the rectangle with the passed bounds.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Circle

A class for drawing circle overlays on a map. Extends CircleMarker. +It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).

+ +
+

Usage example

+ +
+ + + + + +
L.circle([50.5, 30.5], {radius: 200}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.circle(<LatLng> latlng, <Circle options> options?)Instantiates a circle object given a geographical point, and an options object +which contains the circle radius.
L.circle(<LatLng> latlng, <Number> radius, <Circle options> options?)Obsolete way of instantiating a circle, for compatibility with 0.7.x code. +Do not use in new applications or plugins.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + Radius of the circle, in meters.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setRadius(<Number> radius)this

Sets the radius of a circle. Units are in meters.

+
getRadius()Number

Returns the current radius of a circle. Units are in meters.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

CircleMarker

A circle of a fixed size with radius specified in pixels. Extends Path.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.circleMarker(<LatLng> latlng, <CircleMarker options> options?)Instantiates a circle marker object given a geographical point, and an optional options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + 10Radius of the circle marker, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
setRadius(<Number> radius)this

Sets the radius of a circle marker. Units are in pixels.

+
getRadius()Number

Returns the current radius of the circle

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

SVG

Although SVG is not available on IE7 and IE8, these browsers support VML, and the SVG renderer will fall back to VML in this case. +VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility +with old versions of Internet Explorer.

+

Allows vector layers to be displayed with SVG. +Inherits Renderer. +Due to technical limitations, SVG is not +available in all web browsers, notably Android 2.x and 3.x. +Although SVG is not available on IE7 and IE8, these browsers support +VML +(a now deprecated technology), and the SVG renderer will fall back to VML in +this case.

+ +
+

Usage example

+ +
+ + + + + +

Use SVG by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.svg()
+});
+
+

Use a SVG renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.svg({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.SVG:
+ + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
create(<String> name)SVGElementReturns a instance of SVGElement, +corresponding to the class name passed. For example, using 'line' will return +an instance of SVGLineElement.
pointsToPath(<Point[]> rings, <Boolean> closed)StringGenerates a SVG path string for multiple rings, with each ring turning +into "M..L..L.." instructions
+ +
+ + +

Canvas

Allows vector layers to be displayed with <canvas>. +Inherits Renderer. +Due to technical limitations, Canvas is not +available in all web browsers, notably IE8, and overlapping geometries might +not display properly in some edge cases.

+ +
+

Usage example

+ +
+ + + + + +

Use Canvas by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.canvas()
+});
+
+

Use a Canvas renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.canvas({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.canvas(<Renderer options> options?)Creates a Canvas renderer with the given options.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LayerGroup

Used to group several layers and handle them as one. If you add it to the map, +any layers added or removed from the group will be added/removed on the map as +well. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.layerGroup([marker1, marker2])
+    .addLayer(polyline)
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.layerGroup(<Layer[]> layers?)Create a layer group, optionally given an initial set of layers.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

FeatureGroup

Extended LayerGroup that makes it easier to do the same thing to all its member layers:

+
    +
  • bindPopup binds a popup to all of the layers at once (likewise with bindTooltip)
  • +
  • Events are propagated to the FeatureGroup, so if the group has an event +handler, it will handle events from any of the layers. This includes mouse events +and custom events.
  • +
  • Has layeradd and layerremove events
  • +
+ +
+

Usage example

+ +
+ + + + + +
L.featureGroup([marker1, marker2, polyline])
+    .bindPopup('Hello world!')
+    .on('click', function() { alert('Clicked on a member of the group!'); })
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.featureGroup(<Layer[]> layers)Create a feature group, optionally given an initial set of layers.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setStyle(<Path options> style)this

Sets the given path options to each layer of the group that has a setStyle method.

+
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

GeoJSON

Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse +GeoJSON data and display it on the map. Extends FeatureGroup.

+ +
+

Usage example

+ +
+ + + + + +
L.geoJSON(data, {
+    style: function (feature) {
+        return {color: feature.properties.color};
+    }
+}).bindPopup(function (layer) {
+    return layer.feature.properties.description;
+}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.geoJSON(<Object> geojson?, <GeoJSON options> options?)Creates a GeoJSON layer. Optionally accepts an object in +GeoJSON format to display on the map +(you can alternatively add it later with addData method) and an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
pointToLayerFunction + *A Function defining how GeoJSON points spawn Leaflet layers. It is internally +called when data is added, passing the GeoJSON point feature and its LatLng. +The default is to spawn a default Marker: +
function(geoJsonPoint, latlng) {
+    return L.marker(latlng);
+}
+
styleFunction + *A Function defining the Path options for styling GeoJSON lines and polygons, +called internally when data is added. +The default value is to not override any defaults: +
function (geoJsonFeature) {
+    return {}
+}
+
onEachFeatureFunction + *A Function that will be called once for each created Feature, after it has +been created and styled. Useful for attaching events and popups to features. +The default is to do nothing with the newly created layers: +
function (feature, layer) {}
+
filterFunction + *A Function that will be used to decide whether to include a feature or not. +The default is to include all features: +
function (geoJsonFeature) {
+    return true;
+}
+
+

Note: dynamically changing the filter option will have effect only on newly +added data. It will not re-evaluate already included features.

coordsToLatLngFunction + *A Function that will be used for converting GeoJSON coordinates to LatLngs. +The default is the coordsToLatLng static method.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addData(data)this

Adds a GeoJSON object to the layer.

+
resetStyle(layer)this

Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.

+
setStyle(style)this

Changes styles of GeoJSON vector layers with the given style function.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.GeoJSON:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
geometryToLayer(<Object> featureData, <GeoJSON options> options?)LayerCreates a Layer from a given GeoJSON feature. Can use a custom +pointToLayer and/or coordsToLatLng +functions if provided as options.
coordsToLatLng(<Array> coords)LatLngCreates a LatLng object from an array of 2 numbers (longitude, latitude) +or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
coordsToLatLngs(<Array> coords, <Number> levelsDeep?, <Function> coordsToLatLng?)ArrayCreates a multidimensional array of LatLngs from a GeoJSON coordinates array. +levelsDeep specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default). +Can use a custom coordsToLatLng function.
latLngToCoords(<LatLng> latlng, <Number> precision?)ArrayReverse of coordsToLatLng
latLngsToCoords(<Array> latlngs, <Number> levelsDeep?, <Boolean> closed?)ArrayReverse of coordsToLatLngs +closed determines whether the first point should be appended to the end of the array to close the feature, only used when levelsDeep is 0. False by default.
asFeature(<Object> geojson)ObjectNormalize GeoJSON geometries/features into GeoJSON features.
+ +
+ + +

GridLayer

Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces TileLayer.Canvas. +GridLayer can be extended to create a tiled grid of HTML elements like <canvas>, <img> or <div>. GridLayer will handle creating and animating these DOM elements for you.

+ +
+

Usage example

+ +
+ +

Synchronous usage

+ + + +

To create a custom layer, extend GridLayer and implement the createTile() method, which will be passed a Point object with the x, y, and z (zoom level) coordinates to draw your tile.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords){
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // get a canvas context and draw something on it using coords.x, coords.y and coords.z
+        var ctx = tile.getContext('2d');
+        // return the tile so it can be rendered on screen
+        return tile;
+    }
+});
+
+ + + +
+ +

Asynchronous usage

+ + + +

Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the done() callback.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords, done){
+        var error;
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // draw something asynchronously and pass the tile to the done() callback
+        setTimeout(function() {
+            done(error, tile);
+        }, 1000);
+        return tile;
+    }
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.gridLayer(<GridLayer options> options?)Creates a new instance of GridLayer with the supplied options.
+ +
+ + +
+

Options

+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + undefinedThe maximum zoom level up to which this layer will be displayed (inclusive).
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+ +

Extension methods

+ +
Layers extending GridLayer shall reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, must be overriden by classes extending GridLayer. +Returns the HTMLElement corresponding to the given coords. If the done callback +is specified, it must be called when the tile has finished loading and drawing.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LatLng

Represents a geographical point with a certain latitude and longitude.

+ +
+

Usage example

+ +
+ + + + + +
var latlng = L.latLng(50.5, 30.5);
+

All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:

+
map.panTo([50, 30]);
+map.panTo({lon: 30, lat: 50});
+map.panTo({lat: 50, lng: 30});
+map.panTo(L.latLng(50, 30));
+
+ + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLng(<Number> latitude, <Number> longitude, <Number> altitude?)Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).
L.latLng(<Array> coords)Expects an array of the form [Number, Number] or [Number, Number, Number] instead.
L.latLng(<Object> coords)Expects an plain object of the form {lat: Number, lng: Number} or {lat: Number, lng: Number, alt: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
equals(<LatLng> otherLatLng, <Number> maxMargin?)Boolean

Returns true if the given LatLng point is at the same position (within a small margin of error). The margin of error can be overriden by setting maxMargin to a small number.

+
toString()String

Returns a string representation of the point (for debugging purposes).

+
distanceTo(<LatLng> otherLatLng)Number

Returns the distance (in meters) to the given LatLng calculated using the Haversine formula.

+
wrap()LatLng

Returns a new LatLng object with the longitude wrapped so it's always between -180 and +180 degrees.

+
toBounds(<Number> sizeInMeters)LatLngBounds

Returns a new LatLngBounds object in which each boundary is sizeInMeters/2 meters apart from the LatLng.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lat + NumberLatitude in degrees
lng + NumberLongitude in degrees
alt + NumberAltitude in meters (optional)
+ +
+ + +

LatLngBounds

Represents a rectangular geographical area on a map.

+ +
+

Usage example

+ +
+ + + + + +
var corner1 = L.latLng(40.712, -74.227),
+corner2 = L.latLng(40.774, -74.125),
+bounds = L.latLngBounds(corner1, corner2);
+
+

All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
map.fitBounds([
+    [40.712, -74.227],
+    [40.774, -74.125]
+]);
+
+

Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners outside the [-180, 180] degrees longitude range.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLngBounds(<LatLng> corner1, <LatLng> corner2)Creates a LatLngBounds object by defining two diagonally opposite corners of the rectangle.
L.latLngBounds(<LatLng[]> latlngs)Creates a LatLngBounds object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with fitBounds.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<LatLng> latlng)this

Extend the bounds to contain the given point

+
extend(<LatLngBounds> otherBounds)this

Extend the bounds to contain the given bounds

+
pad(<Number> bufferRatio)LatLngBounds

Returns bigger bounds created by extending the current bounds by a given percentage in each direction.

+
getCenter()LatLng

Returns the center point of the bounds.

+
getSouthWest()LatLng

Returns the south-west point of the bounds.

+
getNorthEast()LatLng

Returns the north-east point of the bounds.

+
getNorthWest()LatLng

Returns the north-west point of the bounds.

+
getSouthEast()LatLng

Returns the south-east point of the bounds.

+
getWest()Number

Returns the west longitude of the bounds

+
getSouth()Number

Returns the south latitude of the bounds

+
getEast()Number

Returns the east longitude of the bounds

+
getNorth()Number

Returns the north latitude of the bounds

+
contains(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<LatLng> latlng)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.

+
toBBoxString()String

Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.

+
equals(<LatLngBounds> otherBounds, <Number> maxMargin?)Boolean

Returns true if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overriden by setting maxMargin to a small number.

+
isValid()Boolean

Returns true if the bounds are properly initialized.

+
+ +
+ + +

Point

Represents a point with x and y coordinates in pixels.

+ +
+

Usage example

+ +
+ + + + + +
var point = L.point(200, 300);
+
+

All Leaflet methods and options that accept Point objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:

+
map.panBy([200, 300]);
+map.panBy(L.point(200, 300));
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.point(<Number> x, <Number> y, <Boolean> round?)Creates a Point object with the given x and y coordinates. If optional round is set to true, rounds the x and y values.
L.point(<Number[]> coords)Expects an array of the form [x, y] instead.
L.point(<Object> coords)Expects a plain object of the form {x: Number, y: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
clone()Point

Returns a copy of the current point.

+
add(<Point> otherPoint)Point

Returns the result of addition of the current and the given points.

+
subtract(<Point> otherPoint)Point

Returns the result of subtraction of the given point from the current.

+
divideBy(<Number> num)Point

Returns the result of division of the current point by the given number.

+
multiplyBy(<Number> num)Point

Returns the result of multiplication of the current point by the given number.

+
scaleBy(<Point> scale)Point

Multiply each coordinate of the current point by each coordinate of +scale. In linear algebra terms, multiply the point by the +scaling matrix +defined by scale.

+
unscaleBy(<Point> scale)Point

Inverse of scaleBy. Divide each coordinate of the current point by +each coordinate of scale.

+
round()Point

Returns a copy of the current point with rounded coordinates.

+
floor()Point

Returns a copy of the current point with floored coordinates (rounded down).

+
ceil()Point

Returns a copy of the current point with ceiled coordinates (rounded up).

+
distanceTo(<Point> otherPoint)Number

Returns the cartesian distance between the current and the given points.

+
equals(<Point> otherPoint)Boolean

Returns true if the given point has the same coordinates.

+
contains(<Point> otherPoint)Boolean

Returns true if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).

+
toString()String

Returns a string representation of the point for debugging purposes.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
x + NumberThe x coordinate of the point
y + NumberThe y coordinate of the point
+ +
+ + +

Bounds

Represents a rectangular area in pixel coordinates.

+ +
+

Usage example

+ +
+ + + + + +
var p1 = L.point(10, 10),
+p2 = L.point(40, 60),
+bounds = L.bounds(p1, p2);
+
+

All Leaflet methods that accept Bounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
otherBounds.intersects([[10, 10], [40, 60]]);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.bounds(<Point> corner1, <Point> corner2)Creates a Bounds object from two corners coordinate pairs.
L.bounds(<Point[]> points)Creates a Bounds object from the given array of points.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<Point> point)this

Extends the bounds to contain the given point.

+
getCenter(<Boolean> round?)Point

Returns the center point of the bounds.

+
getBottomLeft()Point

Returns the bottom-left point of the bounds.

+
getTopRight()Point

Returns the top-right point of the bounds.

+
getTopLeft()Point

Returns the top-left point of the bounds (i.e. this.min).

+
getBottomRight()Point

Returns the bottom-right point of the bounds (i.e. this.max).

+
getSize()Point

Returns the size of the given bounds

+
contains(<Bounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<Point> point)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<Bounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds +intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds +overlap if their intersection is an area.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
min + PointThe top left corner of the rectangle.
max + PointThe bottom right corner of the rectangle.
+ +
+ + +

Icon

Represents an icon to provide when creating a marker.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.icon({
+    iconUrl: 'my-icon.png',
+    iconSize: [38, 95],
+    iconAnchor: [22, 94],
+    popupAnchor: [-3, -76],
+    shadowUrl: 'my-icon-shadow.png',
+    shadowSize: [68, 95],
+    shadowAnchor: [22, 94]
+});
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

L.Icon.Default extends L.Icon and is the blue icon Leaflet uses for markers by default.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.icon(<Icon options> options)Creates an icon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + nullThe coordinates of the point from which popups will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+ + +
+ +
+

Icon.Default

+ +
+ + + +
A trivial subclass of Icon, represents the icon to use in Markers when +no icon is specified. Points to the blue marker image distributed with Leaflet +releases. +In order to customize the default icon, just change the properties of L.Icon.Default.prototype.options +(which is a set of Icon options). +If you want to completely replace the default icon, override the +L.Marker.prototype.options.icon with your own icon instead.
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
imagePathString + Icon.Default will try to auto-detect the absolute location of the +blue icon images. If you are placing these images in a non-standard +way, set this option to point to the right absolute path.
+ +
+ + +

DivIcon

Represents a lightweight icon for markers that uses a simple <div> +element instead of an image. Inherits from Icon but ignores the iconUrl and shadow options.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.divIcon({className: 'my-div-icon'});
+// you can set .my-div-icon styles in CSS
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.divIcon(<DivIcon options> options)Creates a DivIcon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
htmlString + ''Custom HTML code to put inside the div element, empty by default.
bgPosPoint + [0, 0]Optional relative position of the background, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + nullThe coordinates of the point from which popups will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+
+
+ +

Control.Zoom

A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its zoomControl option to false. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.zoom(<Control.Zoom options> options)Creates a zoom control
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomInTextString + '+'The text set on the 'zoom in' button.
zoomInTitleString + 'Zoom in'The title set on the 'zoom in' button.
zoomOutTextString + '&#x2212' +The text set on the 'zoom out' button.
zoomOutTitleString + 'Zoom out'The title set on the 'zoom out' button.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Attribution

The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its attributionControl option to false, and it fetches attribution texts from layers with the getAttribution method automatically. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.attribution(<Control.Attribution options> options)Creates an attribution control.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
prefixString + 'Leaflet'The HTML text shown before the attributions. Pass false to disable.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setPrefix(<String> prefix)this

Sets the text before the attributions.

+
addAttribution(<String> text)this

Adds an attribution text (e.g. 'Vector data &copy; Mapbox').

+
removeAttribution(<String> text)this

Removes an attribution text.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Layers

The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the detailed example). Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
var baseLayers = {
+    "Mapbox": mapbox,
+    "OpenStreetMap": osm
+};
+var overlays = {
+    "Marker": marker,
+    "Roads": roadsLayer
+};
+L.control.layers(baseLayers, overlays).addTo(map);
+
+

The baseLayers and overlays parameters are object literals with layer names as keys and Layer objects as values:

+
{
+    "<someName1>": layer1,
+    "<someName2>": layer2
+}
+
+

The layer names can contain HTML, which allows you to add additional styling to the items:

+
{"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>": myLayer}
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.layers(<Object> baselayers?, <Object> overlays?, <Control.Layers options> options?)Creates an attribution control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
collapsedBoolean + trueIf true, the control will be collapsed into an icon and expanded on mouse hover or touch.
autoZIndexBoolean + trueIf true, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
hideSingleBaseBoolean + falseIf true, the base layers in the control will be hidden when there is only one.
sortLayersBoolean + falseWhether to sort the layers. When false, layers will keep the order +in which they were added to the control.
sortFunctionFunction + *A compare function +that will be used for sorting the layers, when sortLayers is true. +The function receives both the L.Layer instances and their names, as in +sortFunction(layerA, layerB, nameA, nameB). +By default, it sorts layers alphabetically by their name.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addBaseLayer(<Layer> layer, <String> name)this

Adds a base layer (radio button entry) with the given name to the control.

+
addOverlay(<Layer> layer, <String> name)this

Adds an overlay (checkbox entry) with the given name to the control.

+
removeLayer(<Layer> layer)this

Remove the given layer from the control.

+
expand()this

Expand the control container if collapsed.

+
collapse()this

Collapse the control container if expanded.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Scale

A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
L.control.scale().addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.scale(<Control.Scale options> options?)Creates an scale control with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
maxWidthNumber + 100Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
metricBoolean + TrueWhether to show the metric scale line (m/km).
imperialBoolean + TrueWhether to show the imperial scale line (mi/ft).
updateWhenIdleBoolean + falseIf true, the control is updated on moveend, otherwise it's always up-to-date (updated on move).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Browser

A namespace with static properties for browser/feature detection used by Leaflet internally.

+ +
+

Usage example

+ +
+ + + + + +
if (L.Browser.ielt9) {
+  alert('Upgrade your browser, dude!');
+}
+
+ + + +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
ie + Booleantrue for all Internet Explorer versions (not Edge).
ielt9 + Booleantrue for Internet Explorer versions less than 9.
edge + Booleantrue for the Edge web browser.
webkit + Booleantrue for webkit-based browsers like Chrome and Safari (including mobile versions).
android + Booleantrue for any browser running on an Android platform.
android23 + Booleantrue for browsers running on Android 2 or Android 3.
opera + Booleantrue for the Opera browser
chrome + Booleantrue for the Chrome browser.
gecko + Booleantrue for gecko-based browsers like Firefox.
safari + Booleantrue for the Safari browser.
opera12 + Booleantrue for the Opera browser supporting CSS transforms (version 12 or later).
win + Booleantrue when the browser is running in a Windows platform
ie3d + Booleantrue for all Internet Explorer versions supporting CSS transforms.
webkit3d + Booleantrue for webkit-based browsers supporting CSS transforms.
gecko3d + Booleantrue for gecko-based browsers supporting CSS transforms.
any3d + Booleantrue for all browsers supporting CSS transforms.
mobile + Booleantrue for all browsers running in a mobile device.
mobileWebkit + Booleantrue for all webkit-based browsers in a mobile device.
mobileWebkit3d + Booleantrue for all webkit-based browsers in a mobile device supporting CSS transforms.
msPointer + Booleantrue for browsers implementing the Microsoft touch events model (notably IE10).
pointer + Booleantrue for all browsers supporting pointer events.
touch + Booleantrue for all browsers supporting touch events. +This does not necessarily mean that the browser is running in a computer with +a touchscreen, it only means that the browser is capable of understanding +touch events.
mobileOpera + Booleantrue for the Opera browser in a mobile device.
mobileGecko + Booleantrue for gecko-based browsers running in a mobile device.
retina + Booleantrue for browsers on a high-resolution "retina" screen.
canvas + Booleantrue when the browser supports <canvas>.
svg + Booleantrue when the browser supports SVG.
vml + Booleantrue if the browser supports VML.
+ +
+ + +

Util

Various utility functions, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> dest, <Object> src?)ObjectMerges the properties of the src object (or multiple objects) into dest object and returns the latter. Has an L.extend shortcut.
create(<Object> proto, <Object> properties?)ObjectCompatibility polyfill for Object.create
bind(<Function> fn, )FunctionReturns a new function bound to the arguments passed, like Function.prototype.bind. +Has a L.bind() shortcut.
stamp(<Object> obj)NumberReturns the unique ID of an object, assiging it one if it doesn't have it.
throttle(<Function> fn, <Number> time, <Object> context)FunctionReturns a function which executes function fn with the given scope context +(so that the this keyword refers to context inside fn's code). The function +fn will be called no more than one time per given amount of time. The arguments +received by the bound function will be any arguments passed when binding the +function, followed by any arguments passed when invoking the bound function. +Has an L.throttle shortcut.
wrapNum(<Number> num, <Number[]> range, <Boolean> includeMax?)NumberReturns the number num modulo range in such a way so it lies within +range[0] and range[1]. The returned value will be always smaller than +range[1] unless includeMax is set to true.
falseFn()FunctionReturns a function which always returns false.
formatNum(<Number> num, <Number> digits?)NumberReturns the number num rounded to digits decimals, or to 5 decimals by default.
trim(<String> str)StringCompatibility polyfill for String.prototype.trim
splitWords(<String> str)String[]Trims and splits the string on whitespace and returns the array of parts.
setOptions(<Object> obj, <Object> options)ObjectMerges the given properties to the options of the obj object, returning the resulting options. See Class options. Has an L.setOptions shortcut.
getParamString(<Object> obj, <String> existingUrl?, <Boolean> uppercase?)StringConverts an object into a parameter URL string, e.g. {a: "foo", b: "bar"} +translates to '?a=foo&b=bar'. If existingUrl is set, the parameters will +be appended at the end. If uppercase is true, the parameter names will +be uppercased (e.g. '?A=foo&B=bar')
template(<String> str, <Object> data)StringSimple templating facility, accepts a template string of the form 'Hello {a}, {b}' +and a data object like {a: 'foo', b: 'bar'}, returns evaluated string +('Hello foo, bar'). You can also specify functions instead of strings for +data values — they will be evaluated passing data as an argument.
isArray(obj)BooleanCompatibility polyfill for Array.isArray
indexOf(<Array> array, <Object> el)NumberCompatibility polyfill for Array.prototype.indexOf
requestAnimFrame(<Function> fn, <Object> context?, <Boolean> immediate?)NumberSchedules fn to be executed when the browser repaints. fn is bound to +context if given. When immediate is set, fn is called immediately if +the browser doesn't have native support for +window.requestAnimationFrame, +otherwise it's delayed. Returns a request ID that can be used to cancel the request.
cancelAnimFrame(<Number> id)undefinedCancels a previous requestAnimFrame. See also window.cancelAnimationFrame.
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lastId + NumberLast unique ID used by stamp()
emptyImageUrl + StringData URI string containing a base64-encoded empty GIF image. +Used as a hack to free memory from unused images on WebKit-powered +mobile devices (by setting image src to this string).
+ +
+ + +

Transformation

Represents an affine transformation: a set of coefficients a, b, c, d +for transforming a point of a form (x, y) into (a*x + b, c*y + d) and doing +the reverse. Used by Leaflet in its projections code.

+ +
+

Usage example

+ +
+ + + + + +
var transformation = L.transformation(2, 5, -1, 10),
+    p = L.point(1, 2),
+    p2 = transformation.transform(p), //  L.point(7, 8)
+    p3 = transformation.untransform(p2); //  L.point(1, 2)
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.transformation(<Number> a, <Number> b, <Number> c, <Number> d)Instantiates a Transformation object with the given coefficients.
L.transformation(<Array> coefficients)Expects an coeficients array of the form +[a: Number, b: Number, c: Number, d: Number].
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
transform(<Point> point, <Number> scale?)Point

Returns a transformed point, optionally multiplied by the given scale. +Only accepts actual L.Point instances, not arrays.

+
untransform(<Point> point, <Number> scale?)Point

Returns the reverse transformation of the given point, optionally divided +by the given scale. Only accepts actual L.Point instances, not arrays.

+
+ +
+ + +

LineUtil

Various utility functions for polyine points processing, used by Leaflet internally to make polylines lightning-fast.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
simplify(<Point[]> points, <Number> tolerance)Point[]Dramatically reduces the number of points in a polyline while retaining +its shape and returns a new array of simplified points, using the +Douglas-Peucker algorithm. +Used for a huge performance boost when processing/displaying Leaflet polylines for +each zoom level and also reducing visual noise. tolerance affects the amount of +simplification (lesser value means higher quality but slower and with more points). +Also released as a separated micro-library Simplify.js.
pointToSegmentDistance(<Point> p, <Point> p1, <Point> p2)NumberReturns the distance between point p and segment p1 to p2.
closestPointOnSegment(<Point> p, <Point> p1, <Point> p2)NumberReturns the closest point from a point p on a segment p1 to p2.
clipSegment(<Point> a, <Point> b, <Bounds> bounds, <Boolean> useLastCode?, <Boolean> round?)Point[]|BooleanClips the segment a to b by rectangular bounds with the +Cohen-Sutherland algorithm +(modifying the segment points directly!). Used by Leaflet to only show polyline +points that are on the screen or near, increasing performance.
isFlat(<LatLng[]> latlngs)BooleanReturns true if latlngs is a flat array, false is nested.
+ +
+ + +

PolyUtil

Various utility functions for polygon geometries.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + +
FunctionReturnsDescription
clipPolygon(<Point[]> points, <Bounds> bounds, <Boolean> round?)Point[]Clips the polygon geometry defined by the given points by the given bounds (using the Sutherland-Hodgeman algorithm). +Used by Leaflet to only show polygon points that are on the screen or near, increasing +performance. Note that polygon points needs different algorithm for clipping +than polyline, so there's a seperate method for it.
+ +
+ + +

DomEvent

Utility functions to work with the DOM events, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
on(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisAdds a listener function (fn) to a particular DOM event type of the +element el. You can optionally specify the context of the listener +(object the this keyword will point to). You can also pass several +space-separated types (e.g. 'click dblclick').
on(<HTMLElement> el, <Object> eventMap, <Object> context?)thisAdds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
off(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisRemoves a previously added listener function. If no function is specified, +it will remove all the listeners of that particular DOM event from the element. +Note that if you passed a custom context to on, you must pass the same +context to off in order to remove the listener.
off(<HTMLElement> el, <Object> eventMap, <Object> context?)thisRemoves a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
off(<HTMLElement> el)thisRemoves all known event listeners
stopPropagation(<DOMEvent> ev)thisStop the given event from propagation to parent elements. Used inside the listener functions: +
L.DomEvent.on(div, 'click', function (ev) {
+    L.DomEvent.stopPropagation(ev);
+});
+
disableScrollPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'mousewheel' events (plus browser variants).
disableClickPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'click', 'doubleclick', +'mousedown' and 'touchstart' events (plus browser variants).
preventDefault(<DOMEvent> ev)thisPrevents the default action of the DOM Event ev from happening (such as +following a link in the href of the a element, or doing a POST request +with page reload when a <form> is submitted). +Use it inside listener functions.
stop(ev)thisDoes stopPropagation and preventDefault at the same time.
getMousePosition(<DOMEvent> ev, <HTMLElement> container?)PointGets normalized mouse position from a DOM event relative to the +container or to the whole page if not specified.
getWheelDelta(<DOMEvent> ev)NumberGets normalized wheel delta from a mousewheel DOM event, in vertical +pixels scrolled (negative if scrolling down). +Events from pointing devices without precise scrolling are mapped to +a best guess of 60 pixels.
addListener()thisAlias to L.DomEvent.on
removeListener()thisAlias to L.DomEvent.off
+ +
+ + +

DomUtil

Utility functions to work with the DOM +tree, used by Leaflet internally. +Most functions expecting or returning a HTMLElement also work for +SVG elements. The only difference is that classes refer to CSS classes +in HTML and SVG classes in SVG.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
get(<String|HTMLElement> id)HTMLElementReturns an element given its DOM id, or returns the element itself +if it was passed directly.
getStyle(<HTMLElement> el, <String> styleAttrib)StringReturns the value for a certain style attribute on an element, +including computed values or values set through CSS.
create(<String> tagName, <String> className?, <HTMLElement> container?)HTMLElementCreates an HTML element with tagName, sets its class to className, and optionally appends it to container element.
remove(<HTMLElement> el)Removes el from its parent element
empty(<HTMLElement> el)Removes all of el's children elements from el
toFront(<HTMLElement> el)Makes el the last child of its parent, so it renders in front of the other children.
toBack(<HTMLElement> el)Makes el the first child of its parent, so it renders behind the other children.
hasClass(<HTMLElement> el, <String> name)BooleanReturns true if the element's class attribute contains name.
addClass(<HTMLElement> el, <String> name)Adds name to the element's class attribute.
removeClass(<HTMLElement> el, <String> name)Removes name from the element's class attribute.
setClass(<HTMLElement> el, <String> name)Sets the element's class.
getClass(<HTMLElement> el)StringReturns the element's class.
setOpacity(<HTMLElement> el, <Number> opacity)Set the opacity of an element (including old IE support). +opacity must be a number from 0 to 1.
testProp(<String[]> props)String|falseGoes through the array of style names and returns the first name +that is a valid style name for an element. If no such name is found, +it returns false. Useful for vendor-prefixed styles like transform.
setTransform(<HTMLElement> el, <Point> offset, <Number> scale?)Resets the 3D CSS transform of el so it is translated by offset pixels +and optionally scaled by scale. Does not have an effect if the +browser doesn't support 3D CSS transforms.
setPosition(<HTMLElement> el, <Point> position)Sets the position of el to coordinates specified by position, +using CSS translate or top/left positioning depending on the browser +(used by Leaflet internally to position its layers).
getPosition(<HTMLElement> el)PointReturns the coordinates of an element previously positioned with setPosition.
disableTextSelection()Prevents the user from generating selectstart DOM events, usually generated +when the user drags the mouse through a page with text. Used internally +by Leaflet to override the behaviour of any click-and-drag interaction on +the map. Affects drag interactions on the whole document.
enableTextSelection()Cancels the effects of a previous L.DomUtil.disableTextSelection.
disableImageDrag()As L.DomUtil.disableTextSelection, but +for dragstart DOM events, usually generated when the user drags an image.
enableImageDrag()Cancels the effects of a previous L.DomUtil.disableImageDrag.
preventOutline(<HTMLElement> el)Makes the outline +of the element el invisible. Used internally by Leaflet to prevent +focusable elements from displaying an outline when the user performs a +drag interaction on them.
restoreOutline()Cancels the effects of a previous L.DomUtil.preventOutline.
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
TRANSFORM + StringVendor-prefixed transform style name (e.g. 'webkitTransform' for WebKit).
TRANSITION + StringVendor-prefixed transition style name.
TRANSITION_END + StringVendor-prefixed transitionend event name.
+ +
+ + +

PosAnimation

Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.

+ +
+

Usage example

+ +
+ + + + + +
var fx = new L.PosAnimation();
+fx.run(el, [300, 500], 0.5);
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.PosAnimation()Creates a PosAnimation object.
+ + +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
start + EventFired when the animation starts
step + EventFired continuously during the animation.
end + EventFired when the animation ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
run(<HTMLElement> el, <Point> newPos, <Number> duration?, <Number> easeLinearity?)

Run an animation of a given element to a new position, optionally setting +duration in seconds (0.25 by default) and easing linearity factor (3rd +argument of the cubic bezier curve, +0.5 by default).

+
stop()

Stops the animation (if currently running).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Draggable

A class for making DOM elements draggable (including touch support). +Used internally for map and marker dragging. Only works for elements +that were positioned with L.DomUtil.setPosition.

+ +
+

Usage example

+ +
+ + + + + +
var draggable = new L.Draggable(elementToDrag);
+draggable.enable();
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.Draggable(<HTMLElement> el, <HTMLElement> dragHandle?, <Boolean> preventOutline?, <Draggable options> options?)Creates a Draggable object for moving el when you start dragging the dragHandle element (equals el itself by default).
+ + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
clickToleranceNumber + 3The max number of pixels a user can shift the mouse pointer during a click +for it to be considered a valid click (as opposed to a mouse drag).
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
down + EventFired when a drag is about to start.
dragstart + EventFired when a drag starts
predrag + EventFired continuously during dragging before each corresponding +update of the element's position.
drag + EventFired continuously during dragging.
dragend + DragEndEventFired when the drag ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()

Enables the dragging ability

+
disable()

Disables the dragging ability

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Class

L.Class powers the OOP facilities of Leaflet and is used to create almost all of the Leaflet classes documented here. +In addition to implementing a simple classical inheritance model, it introduces several special properties for convenient code organization — options, includes and statics.

+ +
+

Usage example

+ +
+ + + + + +
var MyClass = L.Class.extend({
+initialize: function (greeter) {
+    this.greeter = greeter;
+    // class constructor
+},
+greet: function (name) {
+    alert(this.greeter + ', ' + name)
+    }
+});
+// create instance of MyClass, passing "Hello" to the constructor
+var a = new MyClass("Hello");
+// call greet method, alerting "Hello, World"
+a.greet("World");
+
+ + + +
+ +

Class Factories

+ + + +

You may have noticed that Leaflet objects are created without using +the new keyword. This is achieved by complementing each class with a +lowercase factory method:

+
new L.Map('map'); // becomes:
+L.map('map');
+
+

The factories are implemented very easily, and you can do this for your own classes:

+
L.map = function (id, options) {
+    return new L.Map(id, options);
+};
+
+ + + +
+ +

Inheritance

+ + + +

You use L.Class.extend to define new classes, but you can use the same method on any class to inherit from it:

+
var MyChildClass = MyClass.extend({
+    // ... new properties and methods
+});
+
+

This will create a class that inherits all methods and properties of the parent class (through a proper prototype chain), adding or overriding the ones you pass to extend. It will also properly react to instanceof:

+
var a = new MyChildClass();
+a instanceof MyChildClass; // true
+a instanceof MyClass; // true
+
+

You can call parent methods (including constructor) from corresponding child ones (as you do with super calls in other languages) by accessing parent class prototype and using JavaScript's call or apply:

+
var MyChildClass = MyClass.extend({
+    initialize: function () {
+        MyClass.prototype.initialize.call(this, "Yo");
+    },
+    greet: function (name) {
+        MyClass.prototype.greet.call(this, 'bro ' + name + '!');
+    }
+});
+var a = new MyChildClass();
+a.greet('Jason'); // alerts "Yo, bro Jason!"
+
+ + +
+ +

Options

+ + + +

options is a special property that unlike other objects that you pass +to extend will be merged with the parent one instead of overriding it +completely, which makes managing configuration of objects and default +values convenient:

+
var MyClass = L.Class.extend({
+    options: {
+        myOption1: 'foo',
+        myOption2: 'bar'
+    }
+});
+var MyChildClass = MyClass.extend({
+    options: {
+        myOption1: 'baz',
+        myOption3: 5
+    }
+});
+var a = new MyChildClass();
+a.options.myOption1; // 'baz'
+a.options.myOption2; // 'bar'
+a.options.myOption3; // 5
+
+

There's also L.Util.setOptions, a method for +conveniently merging options passed to constructor with the defaults +defines in the class:

+
var MyClass = L.Class.extend({
+    options: {
+        foo: 'bar',
+        bla: 5
+    },
+    initialize: function (options) {
+        L.Util.setOptions(this, options);
+        ...
+    }
+});
+var a = new MyClass({bla: 10});
+a.options; // {foo: 'bar', bla: 10}
+
+ + + +
+ +

Includes

+ + + +

includes is a special class property that merges all specified objects into the class (such objects are called mixins).

+
 var MyMixin = {
+    foo: function () { ... },
+    bar: 5
+};
+var MyClass = L.Class.extend({
+    includes: MyMixin
+});
+var a = new MyClass();
+a.foo();
+
+

You can also do such includes in runtime with the include method:

+
MyClass.include(MyMixin);
+
+

statics is just a convenience property that injects specified object properties as the static properties of the class, useful for defining constants:

+
var MyClass = L.Class.extend({
+    statics: {
+        FOO: 'bar',
+        BLA: 5
+    }
+});
+MyClass.FOO; // 'bar'
+
+ + + +
+ +

Constructor hooks

+ + + +

If you're a plugin developer, you often need to add additional initialization code to existing classes (e.g. editing hooks for L.Polyline). Leaflet comes with a way to do it easily using the addInitHook method:

+
MyClass.addInitHook(function () {
+    // ... do something in constructor additionally
+    // e.g. add event listeners, set custom properties etc.
+});
+
+

You can also use the following shortcut when you just need to make one additional method call:

+
MyClass.addInitHook('methodName', arg1, arg2, …);
+
+ + + +
+ + +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> props)FunctionExtends the current class given the properties to be included. +Returns a Javascript function that is a class constructor (to be called with new).
include(<Object> properties)thisIncludes a mixin into the current class.
mergeOptions(<Object> options)thisMerges options into the defaults of the class.
addInitHook(<Function> fn)thisAdds a constructor hook to the class.
+ +
+ + +

Evented

A set of methods shared between event-powered classes (like Map and Marker). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire 'click' event).

+ +
+

Usage example

+ +
+ + + + + +
map.on('click', function(e) {
+    alert(e.latlng);
+} );
+
+

Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:

+
function onClick(e) { ... }
+map.on('click', onClick);
+map.off('click', onClick);
+
+ + + +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+ + +

Layer

A set of methods from the Layer base class that all Leaflet layers use. +Inherits all methods, options and events from L.Evented.

+ +
+

Usage example

+ +
+ + + + + +
var layer = L.Marker(latlng).addTo(map);
+layer.addTo(map);
+layer.remove();
+
+ + + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Layer will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+ +

Extension methods

+ +
Every layer should extend from L.Layer and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)this

Should contain code that creates DOM elements for the layer, adds them to map panes where they should belong and puts listeners on relevant map events. Called on map.addLayer(layer).

+
onRemove(<Map> map)this

Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in onAdd. Called on map.removeLayer(layer).

+
getEvents()Object

This optional method should return an object like { viewreset: this._reset } for addEventListener. The event handlers in this object will be automatically added and removed from the map with your layer.

+
getAttribution()String

This optional method should return a string containing HTML to be shown on the Attribution control whenever the layer is visible.

+
beforeAdd(<Map> map)this

Optional method. Called on map.addLayer(layer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.

+
+ +
+ +

Popup methods

+ +
All layers share a set of methods convenient for binding popups to it. +
var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
+layer.openPopup();
+layer.closePopup();
+
+

Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+ +

Tooltip methods

+ +
All layers share a set of methods convenient for binding tooltips to it. +
var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
+layer.openTooltip();
+layer.closeTooltip();
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Interactive layer

Some Layers can be made interactive - when the user interacts +with such a layer, mouse events like click and mouseover can be handled. +Use the event handling methods to handle these events.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ +

Mouse events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Control

L.Control is a base class for implementing map controls. Handles positioning. +All other controls extend from this class.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Control will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+ +

Extension methods

+ +
Every control should extend from L.Control and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)HTMLElement

Should return the container DOM element for the control and add listeners on relevant map events. Called on control.addTo(map).

+
onRemove(<Map> map)

Optional method. Should contain all clean up code that removes the listeners previously added in onAdd. Called on control.remove().

+
+ +
+ + +

Handler

Abstract class for map interaction handlers

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()this

Enables the handler

+
disable()this

Disables the handler

+
enabled()Boolean

Returns true if the handler is enabled

+
+ +
+ +

Extension methods

+ +
Classes inheriting from Handler must implement the two following methods:
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHooks()

Called when the handler is enabled, should add event hooks.

+
removeHooks()

Called when the handler is disabled, should remove the event hooks added previously.

+
+ +
+ + +

Projection

An object with methods for projecting geographical coordinates of the world onto +a flat surface (and back). See Map projection.

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
project(<LatLng> latlng)Point

Projects geographical coordinates into a 2D point. +Only accepts actual L.LatLng instances, not arrays.

+
unproject(<Point> point)LatLng

The inverse of project. Projects a 2D point into a geographical location. +Only accepts actual L.Point instances, not arrays.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
bounds + BoundsThe bounds (specified in CRS units) where the projection is valid
+ +
+ + +
+

Defined projections

+ +
+ + + +
Leaflet comes with a set of already defined Projections out of the box:
+ + + + + + + + + + + + + + + + + + + +
ProjectionDescription
L.Projection.LonLatEquirectangular, or Plate Carree projection — the most simple projection, +mostly used by GIS enthusiasts. Directly maps x as longitude, and y as +latitude. Also suitable for flat worlds, e.g. game maps. Used by the +EPSG:4326 and Simple CRS.
L.Projection.MercatorElliptical Mercator projection — more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS.
L.Projection.SphericalMercatorSpherical Mercator projection — the most common projection for online maps, +used by almost all free and commercial tile providers. Assumes that Earth is +a sphere. Used by the EPSG:3857 CRS.
+ +
+ + +

CRS

+
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
latLngToPoint(<LatLng> latlng, <Number> zoom)Point

Projects geographical coordinates into pixel coordinates for a given zoom.

+
pointToLatLng(<Point> point, <Number> zoom)LatLng

The inverse of latLngToPoint. Projects pixel coordinates on a given +zoom into geographical coordinates.

+
project(<LatLng> latlng)Point

Projects geographical coordinates into coordinates in units accepted for +this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).

+
unproject(<Point> point)LatLng

Given a projected coordinate returns the corresponding LatLng. +The inverse of project.

+
scale(<Number> zoom)Number

Returns the scale used when transforming projected coordinates into +pixel coordinates for a particular zoom. For example, it returns +256 * 2^zoom for Mercator-based CRS.

+
zoom(<Number> scale)Number

Inverse of scale(), returns the zoom level corresponding to a scale +factor of scale.

+
getProjectedBounds(<Number> zoom)Bounds

Returns the projection's bounds scaled and transformed for the provided zoom.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +CRS's wrapLat and wrapLng properties, if they are outside the CRS's bounds.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring +that its center is within the CRS's bounds. +Only accepts actual L.LatLngBounds instances, not arrays.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
code + StringStandard code name of the CRS passed into WMS services (e.g. 'EPSG:3857')
wrapLng + Number[]An array of two numbers defining whether the longitude (horizontal) coordinate +axis wraps around a given range and how. Defaults to [-180, 180] in most +geographical CRSs. If undefined, the longitude axis does not wrap around.
wrapLat + Number[]Like wrapLng, but for the latitude (vertical) axis.
infinite + BooleanIf true, the coordinate space will be unbounded (infinite in both axes)
+ +
+ + +
+

Defined CRSs

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CRSDescription
L.CRS.EPSG3395Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.
L.CRS.EPSG3857The most common CRS for online maps, used by almost all free and commercial +tile providers. Uses Spherical Mercator projection. Set in by default in +Map's crs option.
L.CRS.EPSG4326A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. +Leaflet 1.0.x complies with the TMS coordinate scheme for EPSG:4326, +which is a breaking change from 0.7.x behaviour. If you are using a TileLayer +with this CRS, ensure that there are two 256x256 pixel tiles covering the +whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), +or (-180,-90) for TileLayers with the tms option set.
L.CRS.EarthServes as the base for CRS that are global such that they cover the earth. +Can only be used as the base for other CRS and cannot be used directly, +since it does not have a code, projection or transformation. distance() returns +meters.
L.CRS.SimpleA simple CRS that maps longitude and latitude into x and y directly. +May be used for maps of flat surfaces (e.g. game maps). Note that the y +axis should still be inverted (going from bottom to top). distance() returns +simple euclidean distance.
L.CRS.BaseObject that defines coordinate reference systems for projecting +geographical points into pixel (screen) coordinates and back (and to +coordinates in other units for WMS services). See +spatial reference system. +Leaflet defines the most usual CRSs by default. If you want to use a +CRS not defined by default, take a look at the +Proj4Leaflet plugin.
+ +
+ + +

Renderer

Base class for vector renderer implementations (SVG, Canvas). Handles the +DOM container of the renderer, its bounds, and its zoom animation. +A Renderer works as an implicit layer group for all Paths - the renderer +itself can be added or removed to the map. All paths use a renderer, which can +be implicit (the map will decide the type of renderer and use it automatically) +or explicit (using the renderer option of the path). +Do not use this class directly, use SVG and Canvas instead.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Event objects

Whenever a class inheriting from Evented fires an event, a listener function +will be called with an event argument, which is a plain object containing +information about the event. For example:

+
map.on('click', function(ev) {
+    alert(ev.latlng); // ev is an event object (MouseEvent in this case)
+});
+
+

The information available depends on the event type:

+ + + +
+

Event

+ +
+ + + +
The base event object. All other event objects contain these properties too.
+ + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+ + +
+ +
+

KeyboardEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
originalEvent + DOMEventThe original DOM KeyboardEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

MouseEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngThe geographical point where the mouse event occured.
layerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map layer.
containerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map сontainer.
originalEvent + DOMEventThe original DOM MouseEvent or DOM TouchEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

LocationEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngDetected geographical location of the user.
bounds + LatLngBoundsGeographical bounds of the area user is located in (with respect to the accuracy of location).
accuracy + NumberAccuracy of location in meters.
altitude + NumberHeight of the position above the WGS84 ellipsoid in meters.
altitudeAccuracy + NumberAccuracy of altitude in meters.
heading + NumberThe direction of travel in degrees counting clockwise from true North.
speed + NumberCurrent velocity in meters per second.
timestamp + NumberThe time when the position was acquired.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

ErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
message + StringError message.
code + NumberError code (if applicable).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

LayerEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

LayersControlEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
name + StringThe name of the layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

TileEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

TileErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
error + *Error passed to the tile's done() callback.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

ResizeEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
oldSize + PointThe old size before resize event.
newSize + PointThe new size after the resize event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

GeoJSONEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer for the GeoJSON feature that is being added to the map.
properties + ObjectGeoJSON properties of the feature.
geometryType + StringGeoJSON geometry type of the feature.
id + StringGeoJSON ID of the feature (if present).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

PopupEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
popup + PopupThe popup that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

TooltipEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
tooltip + TooltipThe tooltip that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

DragEndEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
distance + NumberThe distance in pixels the draggable element was moved by.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +
+ +
+

ZoomAnimEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
center + LatLngThe current center of the map
zoom + NumberThe current zoom level of the map
noUpdate + BooleanWhether layers should update their contents due to this event
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event.
+ +
+
+
+ +

DivOverlay

Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
offsetPoint + Point(0, 7)The offset of the popup position. Useful to control the anchor +of the popup when opening it on some overlays.
classNameString + ''A custom CSS class name to assign to the popup.
paneString + 'popupPane'Map pane where the popup will be added.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specificed latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specificed latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Global Switches

Global switches are created for rare cases and generally make +Leaflet to not detect a particular browser feature even if it's +there. You need to set the switch as a global variable to true +before including Leaflet on the page, like this:

+
<script>L_NO_TOUCH = true;</script>
+<script src="leaflet.js"></script>
+
+ + + + + + + + + + + + + + + + + +
SwitchDescription
L_NO_TOUCHForces Leaflet to not use touch events even if it detects them.
L_DISABLE_3DForces Leaflet to not use hardware-accelerated CSS 3D transforms for positioning (which may cause glitches in some rare environments) even if they're supported.
+ +

noConflict

This method restores the L global variable to the original value +it had before Leaflet inclusion, and returns the real Leaflet +namespace so you can put it elsewhere, like this:

+
<script src='libs/l.js'>
+<!-- L points to some other library -->
+<script src='leaflet.js'>
+<!-- you include Leaflet, it replaces the L variable to Leaflet namespace -->
+<script>
+var Leaflet = L.noConflict();
+// now L points to that other library again, and you can use Leaflet.Map etc.
+</script>
+
+ +

version

A constant that represents the Leaflet version in use.

+
L.version; // contains "1.0.0" (or whatever version is currently in use)
+
+ + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.0.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.0.html new file mode 100644 index 000000000..16480c670 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.0.html @@ -0,0 +1,24085 @@ +--- +layout: v2 +title: Documentation +bodyclass: api-page +--- + +

Leaflet API reference

+ +

This reference reflects Leaflet 1.3.0 and Leaflet 1.3.1. Check this list if you are using a different version of Leaflet.

+ +
+ +
+

UI Layers

+ +

Raster Layers

+ +

Vector Layers

+ +
+
+

Other Layers

+ +

Basic Types

+ +

Controls

+ +
+
+ + + + + + +

Utility

+ +

DOM Utility

+ +
+
+

Base Classes

+ + +

Misc

+ +
+
+ +

Map

The central class of the API — it is used to create a map on a page and manipulate it.

+ +
+

Usage example

+ +
+ + + + + +
// initialize the map on the "map" div with a given center and zoom
+var map = L.map('map', {
+    center: [51.505, -0.09],
+    zoom: 13
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.map(<String> id, <Map options> options?)Instantiates a map object given the DOM ID of a <div> element +and optionally an object literal with Map options.
L.map(<HTMLElement> el, <Map options> options?)Instantiates a map object given an instance of a <div> HTML element +and optionally an object literal with Map options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
preferCanvasBoolean + falseWhether Paths should be rendered on a Canvas renderer. +By default, all Paths are rendered in a SVG renderer.
+ +
+ +

Control options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionControlBoolean + trueWhether a attribution control is added to the map by default.
zoomControlBoolean + trueWhether a zoom control is added to the map by default.
+ +
+ +

Interaction Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
closePopupOnClickBoolean + trueSet it to false if you don't want popups to close when user clicks the map.
zoomSnapNumber + 1Forces the map's zoom level to always be a multiple of this, particularly +right after a fitBounds() or a pinch-zoom. +By default, the zoom level snaps to the nearest integer; lower values +(e.g. 0.5 or 0.1) allow for greater granularity. A value of 0 +means the zoom level will not be snapped after fitBounds or a pinch-zoom.
zoomDeltaNumber + 1Controls how much the map's zoom level will change after a +zoomIn(), zoomOut(), pressing + +or - on the keyboard, or using the zoom controls. +Values smaller than 1 (e.g. 0.5) allow for greater granularity.
trackResizeBoolean + trueWhether the map automatically handles browser window resize to update itself.
boxZoomBoolean + trueWhether the map can be zoomed to a rectangular area specified by +dragging the mouse while pressing the shift key.
doubleClickZoomBoolean|String + trueWhether the map can be zoomed in by double clicking on it and +zoomed out by double clicking while holding shift. If passed +'center', double-click zoom will zoom to the center of the + view regardless of where the mouse was.
draggingBoolean + trueWhether the map be draggable with mouse/touch or not.
+ +
+ +

Map State Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
crsCRS + L.CRS.EPSG3857The Coordinate Reference System to use. Don't change this if you're not +sure what it means.
centerLatLng + undefinedInitial geographic center of the map
zoomNumber + undefinedInitial map zoom level
minZoomNumber + *Minimum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the lowest of their minZoom options will be used instead.
maxZoomNumber + *Maximum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the highest of their maxZoom options will be used instead.
layersLayer[] + []Array of layers that will be added to the map initially
maxBoundsLatLngBounds + nullWhen this option is set, the map restricts the view to the given +geographical bounds, bouncing the user back if the user tries to pan +outside the view. To set the restriction dynamically, use +setMaxBounds method.
rendererRenderer + *The default method for drawing vector layers on the map. L.SVG +or L.Canvas by default depending on browser support.
+ +
+ +

Animation Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomAnimationBoolean + trueWhether the map zoom animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
zoomAnimationThresholdNumber + 4Won't animate zoom if the zoom difference exceeds this value.
fadeAnimationBoolean + trueWhether the tile fade animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
markerZoomAnimationBoolean + trueWhether markers animate their zoom with the zoom animation, if disabled +they will disappear for the length of the animation. By default it's +enabled in all browsers that support CSS3 Transitions except Android.
transform3DLimitNumber + 2^23Defines the maximum size of a CSS translation transform. The default +value should not be changed unless a web browser positions layers in +the wrong place after doing a large panBy.
+ +
+ +

Panning Inertia Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
inertiaBoolean + *If enabled, panning of the map will have an inertia effect where +the map builds momentum while dragging and continues moving in +the same direction for some time. Feels especially nice on touch +devices. Enabled by default unless running on old Android devices.
inertiaDecelerationNumber + 3000The rate with which the inertial movement slows down, in pixels/second².
inertiaMaxSpeedNumber + InfinityMax speed of the inertial movement, in pixels/second.
easeLinearityNumber + 0.2
worldCopyJumpBoolean + falseWith this option enabled, the map tracks when you pan to another "copy" +of the world and seamlessly jumps to the original one so that all overlays +like markers and vector layers are still visible.
maxBoundsViscosityNumber + 0.0If maxBounds is set, this option will control how solid the bounds +are when dragging the map around. The default value of 0.0 allows the +user to drag outside the bounds at normal speed, higher values will +slow down map dragging outside bounds, and 1.0 makes the bounds fully +solid, preventing the user from dragging outside the bounds.
+ +
+ +

Keyboard Navigation Options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
keyboardBoolean + trueMakes the map focusable and allows users to navigate the map with keyboard +arrows and +/- keys.
keyboardPanDeltaNumber + 80Amount of pixels to pan when pressing an arrow key.
+ +
+ +

Mousewheel options

+ + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
scrollWheelZoomBoolean|String + trueWhether the map can be zoomed by using the mouse wheel. If passed 'center', +it will zoom to the center of the view regardless of where the mouse was.
wheelDebounceTimeNumber + 40Limits the rate at which a wheel can fire (in milliseconds). By default +user can't zoom via wheel more often than once per 40 ms.
wheelPxPerZoomLevelNumber + 60How many scroll pixels (as reported by L.DomEvent.getWheelDelta) +mean a change of one full zoom level. Smaller values will make wheel-zooming +faster (and vice versa).
+ +
+ +

Touch interaction options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tapBoolean + trueEnables mobile hacks for supporting instant taps (fixing 200ms click +delay on iOS/Android) and touch holds (fired as contextmenu events).
tapToleranceNumber + 15The max number of pixels a user can shift his finger during touch +for it to be considered a valid tap.
touchZoomBoolean|String + *Whether the map can be zoomed by touch-dragging with two fingers. If +passed 'center', it will zoom to the center of the view regardless of +where the touch events (fingers) were. Enabled for touch-capable web +browsers except for old Androids.
bounceAtZoomLimitsBoolean + trueSet it to false if you don't want the map to zoom beyond min/max zoom +and then bounce back when pinch-zooming.
+ +
+ + +
+

Events

+ +
+ +

Layer events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
baselayerchange + LayersControlEventFired when the base layer is changed through the layer control.
overlayadd + LayersControlEventFired when an overlay is selected through the layer control.
overlayremove + LayersControlEventFired when an overlay is deselected through the layer control.
layeradd + LayerEventFired when a new layer is added to the map.
layerremove + LayerEventFired when some layer is removed from the map
+ +
+ +

Map state change events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
zoomlevelschange + EventFired when the number of zoomlevels on the map is changed due +to adding or removing a layer.
resize + ResizeEventFired when the map is resized.
unload + EventFired when the map is destroyed with remove method.
viewreset + EventFired when the map needs to redraw its content (this usually happens +on map zoom or load). Very useful for creating custom overlays.
load + EventFired when the map is initialized (when its center and zoom are set +for the first time).
zoomstart + EventFired when the map zoom is about to change (e.g. before zoom animation).
movestart + EventFired when the view of the map starts changing (e.g. user starts dragging the map).
zoom + EventFired repeatedly during any change in zoom level, including zoom +and fly animations.
move + EventFired repeatedly during any movement of the map, including pan and +fly animations.
zoomend + EventFired when the map has changed, after any animations.
moveend + EventFired when the center of the map stops changing (e.g. user stopped +dragging the map).
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup is opened in the map
popupclose + PopupEventFired when a popup in the map is closed
autopanstart + EventFired when the map starts autopanning when opening a popup.
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip is opened in the map.
tooltipclose + TooltipEventFired when a tooltip in the map is closed.
+ +
+ +

Location events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
locationerror + ErrorEventFired when geolocation (using the locate method) failed.
locationfound + LocationEventFired when geolocation (using the locate method) +went successfully.
+ +
+ +

Interaction events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the map.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the map.
mousedown + MouseEventFired when the user pushes the mouse button on the map.
mouseup + MouseEventFired when the user releases the mouse button on the map.
mouseover + MouseEventFired when the mouse enters the map.
mouseout + MouseEventFired when the mouse leaves the map.
mousemove + MouseEventFired while the mouse moves over the map.
contextmenu + MouseEventFired when the user pushes the right mouse button on the map, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
keypress + KeyboardEventFired when the user presses a key from the keyboard while the map is focused.
preclick + MouseEventFired before mouse click on the map (sometimes useful when you +want something to happen on click before any existing click +handlers start running).
+ +
+ +

Other Methods

+ + + + + + + + + + + + + +
EventDataDescription
zoomanim + ZoomAnimEventFired on every frame of a zoom animation
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getRenderer(<Path> layer)Renderer

Returns the instance of Renderer that should be used to render the given +Path. It will ensure that the renderer options of the map and paths +are respected, and that the renderers do exist on the map.

+
+ +
+ +

Methods for Layers and Controls

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addControl(<Control> control)this

Adds the given control to the map

+
removeControl(<Control> control)this

Removes the given control from the map

+
addLayer(<Layer> layer)this

Adds the given layer to the map

+
removeLayer(<Layer> layer)this

Removes the given layer from the map.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the map

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the map, optionally specifying context of the iterator function.

+
map.eachLayer(function(layer){
+    layer.bindPopup('Hello');
+});
+
openPopup(<Popup> popup)this

Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).

+
openPopup(<String|HTMLElement> content, <LatLng> latlng, <Popup options> options?)this

Creates a popup with the specified content and options and opens it in the given point on a map.

+
closePopup(<Popup> popup?)this

Closes the popup previously opened with openPopup (or the given one).

+
openTooltip(<Tooltip> tooltip)this

Opens the specified tooltip.

+
openTooltip(<String|HTMLElement> content, <LatLng> latlng, <Tooltip options> options?)this

Creates a tooltip with the specified content and options and open it.

+
closeTooltip(<Tooltip> tooltip?)this

Closes the tooltip given as parameter.

+
+ +
+ +

Methods for modifying map state

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setView(<LatLng> center, <Number> zoom, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) with the given +animation options.

+
setZoom(<Number> zoom, <Zoom/pan options> options?)this

Sets the zoom of the map.

+
zoomIn(<Number> delta?, <Zoom options> options?)this

Increases the zoom of the map by delta (zoomDelta by default).

+
zoomOut(<Number> delta?, <Zoom options> options?)this

Decreases the zoom of the map by delta (zoomDelta by default).

+
setZoomAround(<LatLng> latlng, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified geographical point on the map +stationary (e.g. used internally for scroll zoom and double-click zoom).

+
setZoomAround(<Point> offset, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.

+
fitBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets a map view that contains the given geographical bounds with the +maximum zoom level possible.

+
fitWorld(<fitBounds options> options?)this

Sets a map view that mostly contains the whole world with the maximum +zoom level possible.

+
panTo(<LatLng> latlng, <Pan options> options?)this

Pans the map to a given center.

+
panBy(<Point> offset, <Pan options> options?)this

Pans the map by a given number of pixels (animated).

+
flyTo(<LatLng> latlng, <Number> zoom?, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) performing a smooth +pan-zoom animation.

+
flyToBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets the view of the map with a smooth animation like flyTo, +but takes a bounds parameter like fitBounds.

+
setMaxBounds(<Bounds> bounds)this

Restricts the map view to the given bounds (see the maxBounds option).

+
setMinZoom(<Number> zoom)this

Sets the lower limit for the available zoom levels (see the minZoom option).

+
setMaxZoom(<Number> zoom)this

Sets the upper limit for the available zoom levels (see the maxZoom option).

+
panInsideBounds(<LatLngBounds> bounds, <Pan options> options?)this

Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.

+
invalidateSize(<Zoom/pan options> options)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default. If options.pan is false, panning will not occur. +If options.debounceMoveend is true, it will delay moveend event so +that it doesn't happen often even if the method is called many +times in a row.

+
invalidateSize(<Boolean> animate)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default.

+
stop()this

Stops the currently running panTo or flyTo animation, if any.

+
+ +
+ +

Geolocation methods

+ + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
locate(<Locate options> options?)this

Tries to locate the user using the Geolocation API, firing a locationfound +event with location data on success or a locationerror event on failure, +and optionally sets the map view to the user's location with respect to +detection accuracy (or to the world view if geolocation failed). +Note that, if your page doesn't use HTTPS, this method will fail in +modern browsers (Chrome 50 and newer) +See Locate options for more details.

+
stopLocate()this

Stops watching location previously initiated by map.locate({watch: true}) +and aborts resetting the map view if map.locate was called with +{setView: true}.

+
+ +
+ +

Other Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHandler(<String> name, <Function> HandlerClass)this

Adds a new Handler to the map, given its name and constructor function.

+
remove()this

Destroys the map and clears all related event listeners.

+
createPane(<String> name, <HTMLElement> container?)HTMLElement

Creates a new map pane with the given name if it doesn't exist already, +then returns it. The pane is created as a child of container, or +as a child of the main map pane if not set.

+
getPane(<String|HTMLElement> pane)HTMLElement

Returns a map pane, given its name or its HTML element (its identity).

+
getPanes()Object

Returns a plain object containing the names of all panes as keys and +the panes as values.

+
getContainer()HTMLElement

Returns the HTML element that contains the map.

+
whenReady(<Function> fn, <Object> context?)this

Runs the given function fn when the map gets initialized with +a view (center and zoom) and at least one layer, or immediately +if it's already initialized, optionally passing a function context.

+
+ +
+ +

Methods for Getting Map State

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getCenter()LatLng

Returns the geographical center of the map view

+
getZoom()Number

Returns the current zoom level of the map view

+
getBounds()LatLngBounds

Returns the geographical bounds visible in the current map view

+
getMinZoom()Number

Returns the minimum zoom level of the map (if set in the minZoom option of the map or of any layers), or 0 by default.

+
getMaxZoom()Number

Returns the maximum zoom level of the map (if set in the maxZoom option of the map or of any layers).

+
getBoundsZoom(<LatLngBounds> bounds, <Boolean> inside?)Number

Returns the maximum zoom level on which the given bounds fit to the map +view in its entirety. If inside (optional) is set to true, the method +instead returns the minimum zoom level on which the map view fits into +the given bounds in its entirety.

+
getSize()Point

Returns the current size of the map container (in pixels).

+
getPixelBounds()Bounds

Returns the bounds of the current map view in projected pixel +coordinates (sometimes useful in layer and overlay implementations).

+
getPixelOrigin()Point

Returns the projected pixel coordinates of the top left point of +the map layer (useful in custom layer and overlay implementations).

+
getPixelWorldBounds(<Number> zoom?)Bounds

Returns the world's bounds in pixel coordinates for zoom level zoom. +If zoom is omitted, the map's current zoom level is used.

+
+ +
+ +

Conversion Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getZoomScale(<Number> toZoom, <Number> fromZoom)Number

Returns the scale factor to be applied to a map transition from zoom level +fromZoom to toZoom. Used internally to help with zoom animations.

+
getScaleZoom(<Number> scale, <Number> fromZoom)Number

Returns the zoom level that the map would end up at, if it is at fromZoom +level and everything is scaled by a factor of scale. Inverse of +getZoomScale.

+
project(<LatLng> latlng, <Number> zoom)Point

Projects a geographical coordinate LatLng according to the projection +of the map's CRS, then scales it according to zoom and the CRS's +Transformation. The result is pixel coordinate relative to +the CRS origin.

+
unproject(<Point> point, <Number> zoom)LatLng

Inverse of project.

+
layerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the origin pixel, +returns the corresponding geographical coordinate (for the current zoom level).

+
latLngToLayerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the origin pixel.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +map's CRS's wrapLat and wrapLng properties, if they are outside the +CRS's bounds. +By default this means longitude is wrapped around the dateline so its +value is between -180 and +180 degrees.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring that +its center is within the CRS's bounds. +By default this means the center longitude is wrapped around the dateline so its +value is between -180 and +180 degrees, and the majority of the bounds +overlaps the CRS's bounds.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates according to +the map's CRS. By default this measures distance in meters.

+
containerPointToLayerPoint(<Point> point)Point

Given a pixel coordinate relative to the map container, returns the corresponding +pixel coordinate relative to the origin pixel.

+
layerPointToContainerPoint(<Point> point)Point

Given a pixel coordinate relative to the origin pixel, +returns the corresponding pixel coordinate relative to the map container.

+
containerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the map container, returns +the corresponding geographical coordinate (for the current zoom level).

+
latLngToContainerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the map container.

+
mouseEventToContainerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to the +map container where the event took place.

+
mouseEventToLayerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to +the origin pixel where the event took place.

+
mouseEventToLatLng(<MouseEvent> ev)LatLng

Given a MouseEvent object, returns geographical coordinate where the +event took place.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Handlers

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
boxZoom + HandlerBox (shift-drag with mouse) zoom handler.
doubleClickZoom + HandlerDouble click zoom handler.
dragging + HandlerMap dragging handler (by both mouse and touch).
keyboard + HandlerKeyboard navigation handler.
scrollWheelZoom + HandlerScroll wheel zoom handler.
tap + HandlerMobile touch hacks (quick tap and touch hold) handler.
touchZoom + HandlerTouch zoom handler.
+ +
+ + +
+

Map panes

+ +
+ + + +
Panes are DOM elements used to control the ordering of layers on the map. You +can access panes with map.getPane or +map.getPanes methods. New panes can be created with the +map.createPane method. +Every map has the following default panes that differ only in zIndex.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PaneTypeZ-indexDescription
mapPaneHTMLElement + 'auto'Pane that contains all other map panes
tilePaneHTMLElement + 200Pane for GridLayers and TileLayers
overlayPaneHTMLElement + 400Pane for vectors (Paths, like Polylines and Polygons), ImageOverlays and VideoOverlays
shadowPaneHTMLElement + 500Pane for overlay shadows (e.g. Marker shadows)
markerPaneHTMLElement + 600Pane for Icons of Markers
tooltipPaneHTMLElement + 650Pane for Tooltips.
popupPaneHTMLElement + 700Pane for Popups.
+ +
+ + +
+ +
+

Locate options

+ +
+ + + +
Some of the geolocation methods for Map take in an options parameter. This +is a plain javascript object with the following optional components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
watchBoolean + falseIf true, starts continuous watching of location changes (instead of detecting it +once) using W3C watchPosition method. You can later stop watching using +map.stopLocate() method.
setViewBoolean + falseIf true, automatically sets the map view to the user location with respect to +detection accuracy, or to world view if geolocation failed.
maxZoomNumber + InfinityThe maximum zoom for automatic view setting when using setView option.
timeoutNumber + 10000Number of milliseconds to wait for a response from geolocation before firing a +locationerror event.
maximumAgeNumber + 0Maximum age of detected location. If less than this amount of milliseconds +passed since last geolocation response, locate will return a cached location.
enableHighAccuracyBoolean + falseEnables high accuracy, see description in the W3C spec.
+ +
+ + +
+ +
+

Zoom options

+ +
+ + + +
Some of the Map methods which modify the zoom level take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+ + +
+ +
+

Pan options

+ +
+ + + +
Some of the Map methods which modify the center of the map take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If true, panning will always be animated if possible. If false, it will +not animate panning, either resetting the map view if panning more than a +screen away, or just setting a new offset for the map pane (except for panBy +which always does the latter).
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+ + +
+ +
+

Zoom/pan options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +
+ +
+

FitBounds options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingTopLeftPoint + [0, 0]Sets the amount of padding in the top left corner of a map container that +shouldn't be accounted for when setting the view to fit bounds. Useful if you +have some control overlays on the map like a sidebar and you don't want them +to obscure objects you're zooming to.
paddingBottomRightPoint + [0, 0]The same for the bottom right corner of the map.
paddingPoint + [0, 0]Equivalent of setting both top left and bottom right padding to the same value.
maxZoomNumber + nullThe maximum possible zoom to use.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +

Marker

L.Marker is used to display clickable/draggable icons on the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.marker([50.5, 30.5]).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.marker(<LatLng> latlng, <Marker options> options?)Instantiates a Marker object given a geographical point and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconIcon + *Icon instance to use for rendering the marker. +See Icon documentation for details on how to customize the marker icon. +If not specified, a common instance of L.Icon.Default is used.
draggableBoolean + falseWhether the marker is draggable with mouse/touch or not.
autoPanBoolean + falseSet it to true if you want the map to do panning animation when marker hits the edges.
autoPanPaddingPoint + Point(50, 50)Equivalent of setting both top left and bottom right autopan padding to the same value.
autoPanSpeedNumber + 10Number of pixels the map should move by.
keyboardBoolean + trueWhether the marker can be tabbed to with a keyboard and clicked by pressing enter.
titleString + ''Text for the browser tooltip that appear on marker hover (no tooltip by default).
altString + ''Text for the alt attribute of the icon image (useful for accessibility).
zIndexOffsetNumber + 0By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like 1000 (or high negative value, respectively).
opacityNumber + 1.0The opacity of the marker.
riseOnHoverBoolean + falseIf true, the marker will get on top of others when you hover the mouse over it.
riseOffsetNumber + 250The z-index offset used for the riseOnHover feature.
paneString + 'markerPane'Map pane where the markers icon will be added.
bubblingMouseEventsBoolean + falseWhen true, a mouse event on this marker will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + +
In addition to shared layer methods like addTo() and remove() and popup methods like bindPopup() you can also use the following methods:
+ + + + + + + + + + + + +
EventDataDescription
move + EventFired when the marker is moved via setLatLng or by dragging. Old and new coordinates are included in event arguments as oldLatLng, latlng.
+ +
+ +

Dragging events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
dragstart + EventFired when the user starts dragging the marker.
movestart + EventFired when the marker starts moving (because of dragging).
drag + EventFired repeatedly while the user drags the marker.
dragend + DragEndEventFired when the user stops dragging the marker.
moveend + EventFired when the marker stops moving (because of dragging).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the marker (as a GeoJSON Point Feature).

+
getLatLng()LatLng

Returns the current geographical position of the marker.

+
setLatLng(<LatLng> latlng)this

Changes the marker position to the given point.

+
setZIndexOffset(<Number> offset)this

Changes the zIndex offset of the marker.

+
setIcon(<Icon> icon)this

Changes the marker icon.

+
setOpacity(<Number> opacity)this

Changes the opacity of the marker.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Interaction handlers

+ +
Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see Handler methods). Example: +
marker.dragging.disable();
+
+ + + + + + + + + + + + +
PropertyTypeDescription
dragging + HandlerMarker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set marker.options.draggable).
+ +
+ + +

Used to open popups in certain places of the map. Use Map.openPopup to +open popups while making sure that only one popup is open at one time +(recommended for usability), or use Map.addLayer to open as many as you want.

+ +
+ + +
+ + + + + +

If you want to just bind a popup to marker click and then open it, it's really easy:

+
marker.bindPopup(popupContent).openPopup();
+
+

Path overlays like polylines also have a bindPopup method. +Here's a more complicated way to open a popup on a map:

+
var popup = L.popup()
+    .setLatLng(latlng)
+    .setContent('<p>Hello world!<br />This is a nice popup.</p>')
+    .openOn(map);
+
+ + + +
+ + +
+ + +
+ + + + + + + + + + + + + + +
FactoryDescription
+ +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +

Tooltip

Used to display small texts on top of map layers.

+ +
+

Usage example

+ +
+ + + + + +
marker.bindTooltip("my tooltip text").openTooltip();
+
+

Note about tooltip offset. Leaflet takes two options in consideration +for computing tooltip offsetting:

+
    +
  • the offset Tooltip option: it defaults to [0, 0], and it's specific to one tooltip. +Add a positive x offset to move the tooltip to the right, and a positive y offset to +move it to the bottom. Negatives will move to the left and top.
  • +
  • the tooltipAnchor Icon option: this will only be considered for Marker. You +should adapt this value if you use a custom icon.
  • +
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tooltip(<Tooltip options> options?, <Layer> source?)Instantiates a Tooltip object given an optional options object that describes its appearance and location and an optional source object that is used to tag the tooltip with a reference to the Layer to which it refers.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'tooltipPane'Map pane where the tooltip will be added.
offsetPoint + Point(0, 0)Optional offset of the tooltip position.
directionString + 'auto'Direction where to open the tooltip. Possible values are: right, left, +top, bottom, center, auto. +auto will dynamically switch between right and left according to the tooltip +position on the map.
permanentBoolean + falseWhether to open the tooltip permanently or only on mouseover.
stickyBoolean + falseIf true, the tooltip will follow the mouse instead of being fixed at the feature center.
interactiveBoolean + falseIf true, the tooltip will listen to the feature events.
opacityNumber + 0.9Tooltip container opacity.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
classNameString + ''A custom CSS class name to assign to the popup.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer

Used to load and display tile layers on the map. Extends GridLayer.

+ +
+

Usage example

+ +
+ + + + + +
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
+
+ + + +
+ +

URL template

+ + + +

A string of the following form:

+
'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
+

{s} means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; a, b or c by default, can be omitted), {z} — zoom level, {x} and {y} — tile coordinates. {r} can be used to add "@2x" to the URL to load retina tiles. +You can use custom keys in the template, which will be evaluated from TileLayer options, like this:

+
L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
+
+ + +
+ + +
+

Creation

+ +
+ +

Extension methods

+ + + + + + + + + + + + +
FactoryDescription
L.tilelayer(<String> urlTemplate, <TileLayer options> options?)Instantiates a tile layer object given a URL template and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean + falseIf true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropriate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+ +

Extension methods

+ +
Layers extending TileLayer might reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
getTileUrl(<Object> coords)String

Called only internally, returns the URL for a tile given its coordinates. +Classes extending TileLayer can override this function to provide custom tile URL naming schemes.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer.WMS

Used to display WMS services as tile layers on the map. Extends TileLayer.

+ +
+

Usage example

+ +
+ + + + + +
var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
+    layers: 'nexrad-n0r-900913',
+    format: 'image/png',
+    transparent: true,
+    attribution: "Weather data © 2012 IEM Nexrad"
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tileLayer.wms(<String> baseUrl, <TileLayer.WMS options> options)Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.
+ +
+ + +
+

Options

+ +
+ + + +
If any custom options not documented here are used, they will be sent to the +WMS server as extra parameters in each request URL. This can be useful for +non-standard vendor WMS parameters.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
layersString + ''(required) Comma-separated list of WMS layers to show.
stylesString + ''Comma-separated list of WMS styles.
formatString + 'image/jpeg'WMS image format (use 'image/png' for layers with transparency).
transparentBoolean + falseIf true, the WMS service will return images with transparency.
versionString + '1.1.1'Version of the WMS service to use
crsCRS + nullCoordinate Reference System to use for the WMS requests, defaults to +map CRS. Don't change this if you're not sure what it means.
uppercaseBoolean + falseIf true, WMS request parameter keys will be uppercase.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean + falseIf true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setParams(<Object> params, <Boolean> noRedraw?)this

Merges an object with the new parameters and re-requests tiles on the current screen (unless noRedraw was set to true).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropriate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

ImageOverlay

Used to load and display a single image over specific bounds of the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
+    imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
+L.imageOverlay(imageUrl, imageBounds).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.imageOverlay(<String> imageUrl, <LatLngBounds> bounds, <ImageOverlay options> options?)Instantiates an image overlay object given the URL of the image and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean + falseIf true, the image will have its crossOrigin attribute set to ''. This is needed if you want to access image pixel data.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the tile layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the ImageOverlay layer has loaded its image
error + EventFired when the ImageOverlay layer has loaded its image
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers +Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
getElement()HTMLElement

Returns the instance of HTMLImageElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

VideoOverlay

Used to load and display a video player over specific bounds of the map. Extends ImageOverlay. +A video overlay uses the <video> +HTML5 element.

+ +
+

Usage example

+ +
+ + + + + +
var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
+    videoBounds = [[ 32, -130], [ 13, -100]];
+L.VideoOverlay(videoUrl, videoBounds ).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.videoOverlay(<String|Array|HTMLVideoElement> video, <LatLngBounds> bounds, <VideoOverlay options> options?)Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
autoplayBoolean + trueWhether the video starts playing automatically when loaded.
loopBoolean + trueWhether the video will loop back to the beginning when played.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean + falseIf true, the image will have its crossOrigin attribute set to ''. This is needed if you want to access image pixel data.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the tile layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the video has finished loading the first frame
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
error + EventFired when the ImageOverlay layer has loaded its image
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getElement()HTMLVideoElement

Returns the instance of HTMLVideoElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers +Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Path

An abstract class that contains options and constants shared between vector +overlays (Polygon, Polyline, Circle). Do not use it directly. Extends Layer.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polyline

A class for drawing polyline overlays on a map. Extends Path.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polyline from an array of LatLng points
+var latlngs = [
+    [45.51, -122.68],
+    [37.77, -122.43],
+    [34.04, -118.2]
+];
+var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polyline
+map.fitBounds(polyline.getBounds());
+
+

You can also pass a multi-dimensional array to represent a MultiPolyline shape:

+
// create a red polyline from an array of arrays of LatLng points
+var latlngs = [
+    [[45.51, -122.68],
+     [37.77, -122.43],
+     [34.04, -118.2]],
+    [[40.78, -73.91],
+     [41.83, -87.62],
+     [32.76, -96.72]]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polyline(<LatLng[]> latlngs, <Polyline options> options?)Instantiates a polyline object given an array of geographical points and +optionally an options object. You can create a Polyline object with +multiple separate lines (MultiPolyline) by passing an array of arrays +of geographic points.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polyline (as a GeoJSON LineString or MultiLineString Feature).

+
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint()Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polygon

A class for drawing polygon overlays on a map. Extends Polyline. +Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polygon from an array of LatLng points
+var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
+var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polygon
+map.fitBounds(polygon.getBounds());
+
+

You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:

+
var latlngs = [
+  [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+  [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+];
+
+

Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.

+
var latlngs = [
+  [ // first polygon
+    [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+    [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+  ],
+  [ // second polygon
+    [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
+  ]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polygon(<LatLng[]> latlngs, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint()Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Rectangle

A class for drawing rectangle overlays on a map. Extends Polygon.

+ +
+

Usage example

+ +
+ + + + + +
// define rectangle geographical bounds
+var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
+// create an orange rectangle
+L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
+// zoom the map to the rectangle bounds
+map.fitBounds(bounds);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.rectangle(<LatLngBounds> latLngBounds, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setBounds(<LatLngBounds> latLngBounds)this

Redraws the rectangle with the passed bounds.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint()Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Circle

A class for drawing circle overlays on a map. Extends CircleMarker. +It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).

+ +
+

Usage example

+ +
+ + + + + +
L.circle([50.5, 30.5], {radius: 200}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.circle(<LatLng> latlng, <Circle options> options?)Instantiates a circle object given a geographical point, and an options object +which contains the circle radius.
L.circle(<LatLng> latlng, <Number> radius, <Circle options> options?)Obsolete way of instantiating a circle, for compatibility with 0.7.x code. +Do not use in new applications or plugins.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + Radius of the circle, in meters.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setRadius(<Number> radius)this

Sets the radius of a circle. Units are in meters.

+
getRadius()Number

Returns the current radius of a circle. Units are in meters.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

CircleMarker

A circle of a fixed size with radius specified in pixels. Extends Path.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.circleMarker(<LatLng> latlng, <CircleMarker options> options?)Instantiates a circle marker object given a geographical point, and an optional options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + 10Radius of the circle marker, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
setRadius(<Number> radius)this

Sets the radius of a circle marker. Units are in pixels.

+
getRadius()Number

Returns the current radius of the circle

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

SVG

Although SVG is not available on IE7 and IE8, these browsers support VML, and the SVG renderer will fall back to VML in this case. +VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility +with old versions of Internet Explorer.

+

Allows vector layers to be displayed with SVG. +Inherits Renderer. +Due to technical limitations, SVG is not +available in all web browsers, notably Android 2.x and 3.x. +Although SVG is not available on IE7 and IE8, these browsers support +VML +(a now deprecated technology), and the SVG renderer will fall back to VML in +this case.

+ +
+

Usage example

+ +
+ + + + + +

Use SVG by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.svg()
+});
+
+

Use a SVG renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.svg({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.svg(<Renderer options> options?)Creates a SVG renderer with the given options.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.SVG:
+ + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
create(<String> name)SVGElementReturns a instance of SVGElement, +corresponding to the class name passed. For example, using 'line' will return +an instance of SVGLineElement.
pointsToPath(<Point[]> rings, <Boolean> closed)StringGenerates a SVG path string for multiple rings, with each ring turning +into "M..L..L.." instructions
+ +
+ + +

Canvas

Allows vector layers to be displayed with <canvas>. +Inherits Renderer. +Due to technical limitations, Canvas is not +available in all web browsers, notably IE8, and overlapping geometries might +not display properly in some edge cases.

+ +
+

Usage example

+ +
+ + + + + +

Use Canvas by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.canvas()
+});
+
+

Use a Canvas renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.canvas({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.canvas(<Renderer options> options?)Creates a Canvas renderer with the given options.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LayerGroup

Used to group several layers and handle them as one. If you add it to the map, +any layers added or removed from the group will be added/removed on the map as +well. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.layerGroup([marker1, marker2])
+    .addLayer(polyline)
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.layerGroup(<Layer[]> layers?, <Object> options?)Create a layer group, optionally given an initial set of layers and an options object.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

FeatureGroup

Extended LayerGroup that makes it easier to do the same thing to all its member layers:

+
    +
  • bindPopup binds a popup to all of the layers at once (likewise with bindTooltip)
  • +
  • Events are propagated to the FeatureGroup, so if the group has an event +handler, it will handle events from any of the layers. This includes mouse events +and custom events.
  • +
  • Has layeradd and layerremove events
  • +
+ +
+

Usage example

+ +
+ + + + + +
L.featureGroup([marker1, marker2, polyline])
+    .bindPopup('Hello world!')
+    .on('click', function() { alert('Clicked on a member of the group!'); })
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.featureGroup(<Layer[]> layers)Create a feature group, optionally given an initial set of layers.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setStyle(<Path options> style)this

Sets the given path options to each layer of the group that has a setStyle method.

+
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

GeoJSON

Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse +GeoJSON data and display it on the map. Extends FeatureGroup.

+ +
+

Usage example

+ +
+ + + + + +
L.geoJSON(data, {
+    style: function (feature) {
+        return {color: feature.properties.color};
+    }
+}).bindPopup(function (layer) {
+    return layer.feature.properties.description;
+}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.geoJSON(<Object> geojson?, <GeoJSON options> options?)Creates a GeoJSON layer. Optionally accepts an object in +GeoJSON format to display on the map +(you can alternatively add it later with addData method) and an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
pointToLayerFunction + *A Function defining how GeoJSON points spawn Leaflet layers. It is internally +called when data is added, passing the GeoJSON point feature and its LatLng. +The default is to spawn a default Marker: +
function(geoJsonPoint, latlng) {
+    return L.marker(latlng);
+}
+
styleFunction + *A Function defining the Path options for styling GeoJSON lines and polygons, +called internally when data is added. +The default value is to not override any defaults: +
function (geoJsonFeature) {
+    return {}
+}
+
onEachFeatureFunction + *A Function that will be called once for each created Feature, after it has +been created and styled. Useful for attaching events and popups to features. +The default is to do nothing with the newly created layers: +
function (feature, layer) {}
+
filterFunction + *A Function that will be used to decide whether to include a feature or not. +The default is to include all features: +
function (geoJsonFeature) {
+    return true;
+}
+
+

Note: dynamically changing the filter option will have effect only on newly +added data. It will not re-evaluate already included features.

coordsToLatLngFunction + *A Function that will be used for converting GeoJSON coordinates to LatLngs. +The default is the coordsToLatLng static method.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addData(data)this

Adds a GeoJSON object to the layer.

+
resetStyle(layer)this

Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.

+
setStyle(style)this

Changes styles of GeoJSON vector layers with the given style function.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.GeoJSON:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
geometryToLayer(<Object> featureData, <GeoJSON options> options?)LayerCreates a Layer from a given GeoJSON feature. Can use a custom +pointToLayer and/or coordsToLatLng +functions if provided as options.
coordsToLatLng(<Array> coords)LatLngCreates a LatLng object from an array of 2 numbers (longitude, latitude) +or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
coordsToLatLngs(<Array> coords, <Number> levelsDeep?, <Function> coordsToLatLng?)ArrayCreates a multidimensional array of LatLngs from a GeoJSON coordinates array. +levelsDeep specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default). +Can use a custom coordsToLatLng function.
latLngToCoords(<LatLng> latlng, <Number> precision?)ArrayReverse of coordsToLatLng
latLngsToCoords(<Array> latlngs, <Number> levelsDeep?, <Boolean> closed?)ArrayReverse of coordsToLatLngs +closed determines whether the first point should be appended to the end of the array to close the feature, only used when levelsDeep is 0. False by default.
asFeature(<Object> geojson)ObjectNormalize GeoJSON geometries/features into GeoJSON features.
+ +
+ + +

GridLayer

Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces TileLayer.Canvas. +GridLayer can be extended to create a tiled grid of HTML elements like <canvas>, <img> or <div>. GridLayer will handle creating and animating these DOM elements for you.

+ +
+

Usage example

+ +
+ +

Synchronous usage

+ + + +

To create a custom layer, extend GridLayer and implement the createTile() method, which will be passed a Point object with the x, y, and z (zoom level) coordinates to draw your tile.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords){
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // get a canvas context and draw something on it using coords.x, coords.y and coords.z
+        var ctx = tile.getContext('2d');
+        // return the tile so it can be rendered on screen
+        return tile;
+    }
+});
+
+ + + +
+ +

Asynchronous usage

+ + + +

Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the done() callback.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords, done){
+        var error;
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // draw something asynchronously and pass the tile to the done() callback
+        setTimeout(function() {
+            done(error, tile);
+        }, 1000);
+        return tile;
+    }
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.gridLayer(<GridLayer options> options?)Creates a new instance of GridLayer with the supplied options.
+ +
+ + +
+

Options

+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + undefinedThe maximum zoom level up to which this layer will be displayed (inclusive).
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+ +

Extension methods

+ +
Layers extending GridLayer shall reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, must be overridden by classes extending GridLayer. +Returns the HTMLElement corresponding to the given coords. If the done callback +is specified, it must be called when the tile has finished loading and drawing.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LatLng

Represents a geographical point with a certain latitude and longitude.

+ +
+

Usage example

+ +
+ + + + + +
var latlng = L.latLng(50.5, 30.5);
+

All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:

+
map.panTo([50, 30]);
+map.panTo({lon: 30, lat: 50});
+map.panTo({lat: 50, lng: 30});
+map.panTo(L.latLng(50, 30));
+

Note that LatLng does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLng(<Number> latitude, <Number> longitude, <Number> altitude?)Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).
L.latLng(<Array> coords)Expects an array of the form [Number, Number] or [Number, Number, Number] instead.
L.latLng(<Object> coords)Expects an plain object of the form {lat: Number, lng: Number} or {lat: Number, lng: Number, alt: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
equals(<LatLng> otherLatLng, <Number> maxMargin?)Boolean

Returns true if the given LatLng point is at the same position (within a small margin of error). The margin of error can be overridden by setting maxMargin to a small number.

+
toString()String

Returns a string representation of the point (for debugging purposes).

+
distanceTo(<LatLng> otherLatLng)Number

Returns the distance (in meters) to the given LatLng calculated using the Spherical Law of Cosines.

+
wrap()LatLng

Returns a new LatLng object with the longitude wrapped so it's always between -180 and +180 degrees.

+
toBounds(<Number> sizeInMeters)LatLngBounds

Returns a new LatLngBounds object in which each boundary is sizeInMeters/2 meters apart from the LatLng.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lat + NumberLatitude in degrees
lng + NumberLongitude in degrees
alt + NumberAltitude in meters (optional)
+ +
+ + +

LatLngBounds

Represents a rectangular geographical area on a map.

+ +
+

Usage example

+ +
+ + + + + +
var corner1 = L.latLng(40.712, -74.227),
+corner2 = L.latLng(40.774, -74.125),
+bounds = L.latLngBounds(corner1, corner2);
+
+

All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
map.fitBounds([
+    [40.712, -74.227],
+    [40.774, -74.125]
+]);
+
+

Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners outside the [-180, 180] degrees longitude range. +Note that LatLngBounds does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLngBounds(<LatLng> corner1, <LatLng> corner2)Creates a LatLngBounds object by defining two diagonally opposite corners of the rectangle.
L.latLngBounds(<LatLng[]> latlngs)Creates a LatLngBounds object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with fitBounds.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<LatLng> latlng)this

Extend the bounds to contain the given point

+
extend(<LatLngBounds> otherBounds)this

Extend the bounds to contain the given bounds

+
pad(<Number> bufferRatio)LatLngBounds

Returns bounds created by extending or retracting the current bounds by a given ratio in each direction. +For example, a ratio of 0.5 extends the bounds by 50% in each direction. +Negative values will retract the bounds.

+
getCenter()LatLng

Returns the center point of the bounds.

+
getSouthWest()LatLng

Returns the south-west point of the bounds.

+
getNorthEast()LatLng

Returns the north-east point of the bounds.

+
getNorthWest()LatLng

Returns the north-west point of the bounds.

+
getSouthEast()LatLng

Returns the south-east point of the bounds.

+
getWest()Number

Returns the west longitude of the bounds

+
getSouth()Number

Returns the south latitude of the bounds

+
getEast()Number

Returns the east longitude of the bounds

+
getNorth()Number

Returns the north latitude of the bounds

+
contains(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<LatLng> latlng)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.

+
toBBoxString()String

Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.

+
equals(<LatLngBounds> otherBounds, <Number> maxMargin?)Boolean

Returns true if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting maxMargin to a small number.

+
isValid()Boolean

Returns true if the bounds are properly initialized.

+
+ +
+ + +

Point

Represents a point with x and y coordinates in pixels.

+ +
+

Usage example

+ +
+ + + + + +
var point = L.point(200, 300);
+
+

All Leaflet methods and options that accept Point objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:

+
map.panBy([200, 300]);
+map.panBy(L.point(200, 300));
+
+

Note that Point does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.point(<Number> x, <Number> y, <Boolean> round?)Creates a Point object with the given x and y coordinates. If optional round is set to true, rounds the x and y values.
L.point(<Number[]> coords)Expects an array of the form [x, y] instead.
L.point(<Object> coords)Expects a plain object of the form {x: Number, y: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
clone()Point

Returns a copy of the current point.

+
add(<Point> otherPoint)Point

Returns the result of addition of the current and the given points.

+
subtract(<Point> otherPoint)Point

Returns the result of subtraction of the given point from the current.

+
divideBy(<Number> num)Point

Returns the result of division of the current point by the given number.

+
multiplyBy(<Number> num)Point

Returns the result of multiplication of the current point by the given number.

+
scaleBy(<Point> scale)Point

Multiply each coordinate of the current point by each coordinate of +scale. In linear algebra terms, multiply the point by the +scaling matrix +defined by scale.

+
unscaleBy(<Point> scale)Point

Inverse of scaleBy. Divide each coordinate of the current point by +each coordinate of scale.

+
round()Point

Returns a copy of the current point with rounded coordinates.

+
floor()Point

Returns a copy of the current point with floored coordinates (rounded down).

+
ceil()Point

Returns a copy of the current point with ceiled coordinates (rounded up).

+
trunc()Point

Returns a copy of the current point with truncated coordinates (rounded towards zero).

+
distanceTo(<Point> otherPoint)Number

Returns the cartesian distance between the current and the given points.

+
equals(<Point> otherPoint)Boolean

Returns true if the given point has the same coordinates.

+
contains(<Point> otherPoint)Boolean

Returns true if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).

+
toString()String

Returns a string representation of the point for debugging purposes.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
x + NumberThe x coordinate of the point
y + NumberThe y coordinate of the point
+ +
+ + +

Bounds

Represents a rectangular area in pixel coordinates.

+ +
+

Usage example

+ +
+ + + + + +
var p1 = L.point(10, 10),
+p2 = L.point(40, 60),
+bounds = L.bounds(p1, p2);
+
+

All Leaflet methods that accept Bounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
otherBounds.intersects([[10, 10], [40, 60]]);
+
+

Note that Bounds does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.bounds(<Point> corner1, <Point> corner2)Creates a Bounds object from two corners coordinate pairs.
L.bounds(<Point[]> points)Creates a Bounds object from the given array of points.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<Point> point)this

Extends the bounds to contain the given point.

+
getCenter(<Boolean> round?)Point

Returns the center point of the bounds.

+
getBottomLeft()Point

Returns the bottom-left point of the bounds.

+
getTopRight()Point

Returns the top-right point of the bounds.

+
getTopLeft()Point

Returns the top-left point of the bounds (i.e. this.min).

+
getBottomRight()Point

Returns the bottom-right point of the bounds (i.e. this.max).

+
getSize()Point

Returns the size of the given bounds

+
contains(<Bounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<Point> point)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<Bounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds +intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds +overlap if their intersection is an area.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
min + PointThe top left corner of the rectangle.
max + PointThe bottom right corner of the rectangle.
+ +
+ + +

Icon

Represents an icon to provide when creating a marker.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.icon({
+    iconUrl: 'my-icon.png',
+    iconSize: [38, 95],
+    iconAnchor: [22, 94],
+    popupAnchor: [-3, -76],
+    shadowUrl: 'my-icon-shadow.png',
+    shadowSize: [68, 95],
+    shadowAnchor: [22, 94]
+});
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

L.Icon.Default extends L.Icon and is the blue icon Leaflet uses for markers by default.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.icon(<Icon options> options)Creates an icon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + [0, 0]The coordinates of the point from which popups will "open", relative to the icon anchor.
tooltipAnchorPoint + [0, 0]The coordinates of the point from which tooltips will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+ + +
+ +
+

Icon.Default

+ +
+ + + +
A trivial subclass of Icon, represents the icon to use in Markers when +no icon is specified. Points to the blue marker image distributed with Leaflet +releases. +In order to customize the default icon, just change the properties of L.Icon.Default.prototype.options +(which is a set of Icon options). +If you want to completely replace the default icon, override the +L.Marker.prototype.options.icon with your own icon instead.
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
imagePathString + Icon.Default will try to auto-detect the location of the +blue icon images. If you are placing these images in a non-standard +way, set this option to point to the right path.
+ +
+ + +

DivIcon

Represents a lightweight icon for markers that uses a simple <div> +element instead of an image. Inherits from Icon but ignores the iconUrl and shadow options.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.divIcon({className: 'my-div-icon'});
+// you can set .my-div-icon styles in CSS
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.divIcon(<DivIcon options> options)Creates a DivIcon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
htmlString + ''Custom HTML code to put inside the div element, empty by default.
bgPosPoint + [0, 0]Optional relative position of the background, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + [0, 0]The coordinates of the point from which popups will "open", relative to the icon anchor.
tooltipAnchorPoint + [0, 0]The coordinates of the point from which tooltips will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+
+
+ +

Control.Zoom

A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its zoomControl option to false. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.zoom(<Control.Zoom options> options)Creates a zoom control
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomInTextString + '+'The text set on the 'zoom in' button.
zoomInTitleString + 'Zoom in'The title set on the 'zoom in' button.
zoomOutTextString + '&#x2212' +The text set on the 'zoom out' button.
zoomOutTitleString + 'Zoom out'The title set on the 'zoom out' button.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Attribution

The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its attributionControl option to false, and it fetches attribution texts from layers with the getAttribution method automatically. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.attribution(<Control.Attribution options> options)Creates an attribution control.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
prefixString + 'Leaflet'The HTML text shown before the attributions. Pass false to disable.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setPrefix(<String> prefix)this

Sets the text before the attributions.

+
addAttribution(<String> text)this

Adds an attribution text (e.g. 'Vector data &copy; Mapbox').

+
removeAttribution(<String> text)this

Removes an attribution text.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Layers

The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the detailed example). Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
var baseLayers = {
+    "Mapbox": mapbox,
+    "OpenStreetMap": osm
+};
+var overlays = {
+    "Marker": marker,
+    "Roads": roadsLayer
+};
+L.control.layers(baseLayers, overlays).addTo(map);
+
+

The baseLayers and overlays parameters are object literals with layer names as keys and Layer objects as values:

+
{
+    "<someName1>": layer1,
+    "<someName2>": layer2
+}
+
+

The layer names can contain HTML, which allows you to add additional styling to the items:

+
{"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>": myLayer}
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.layers(<Object> baselayers?, <Object> overlays?, <Control.Layers options> options?)Creates an attribution control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
collapsedBoolean + trueIf true, the control will be collapsed into an icon and expanded on mouse hover or touch.
autoZIndexBoolean + trueIf true, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
hideSingleBaseBoolean + falseIf true, the base layers in the control will be hidden when there is only one.
sortLayersBoolean + falseWhether to sort the layers. When false, layers will keep the order +in which they were added to the control.
sortFunctionFunction + *A compare function +that will be used for sorting the layers, when sortLayers is true. +The function receives both the L.Layer instances and their names, as in +sortFunction(layerA, layerB, nameA, nameB). +By default, it sorts layers alphabetically by their name.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addBaseLayer(<Layer> layer, <String> name)this

Adds a base layer (radio button entry) with the given name to the control.

+
addOverlay(<Layer> layer, <String> name)this

Adds an overlay (checkbox entry) with the given name to the control.

+
removeLayer(<Layer> layer)this

Remove the given layer from the control.

+
expand()this

Expand the control container if collapsed.

+
collapse()this

Collapse the control container if expanded.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Scale

A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
L.control.scale().addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.scale(<Control.Scale options> options?)Creates an scale control with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
maxWidthNumber + 100Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
metricBoolean + TrueWhether to show the metric scale line (m/km).
imperialBoolean + TrueWhether to show the imperial scale line (mi/ft).
updateWhenIdleBoolean + falseIf true, the control is updated on moveend, otherwise it's always up-to-date (updated on move).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Browser

A namespace with static properties for browser/feature detection used by Leaflet internally.

+ +
+

Usage example

+ +
+ + + + + +
if (L.Browser.ielt9) {
+  alert('Upgrade your browser, dude!');
+}
+
+ + + +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
ie + Booleantrue for all Internet Explorer versions (not Edge).
ielt9 + Booleantrue for Internet Explorer versions less than 9.
edge + Booleantrue for the Edge web browser.
webkit + Booleantrue for webkit-based browsers like Chrome and Safari (including mobile versions).
android + Booleantrue for any browser running on an Android platform.
android23 + Booleantrue for browsers running on Android 2 or Android 3.
androidStock + Booleantrue for the Android stock browser (i.e. not Chrome)
opera + Booleantrue for the Opera browser
chrome + Booleantrue for the Chrome browser.
gecko + Booleantrue for gecko-based browsers like Firefox.
safari + Booleantrue for the Safari browser.
opera12 + Booleantrue for the Opera browser supporting CSS transforms (version 12 or later).
win + Booleantrue when the browser is running in a Windows platform
ie3d + Booleantrue for all Internet Explorer versions supporting CSS transforms.
webkit3d + Booleantrue for webkit-based browsers supporting CSS transforms.
gecko3d + Booleantrue for gecko-based browsers supporting CSS transforms.
any3d + Booleantrue for all browsers supporting CSS transforms.
mobile + Booleantrue for all browsers running in a mobile device.
mobileWebkit + Booleantrue for all webkit-based browsers in a mobile device.
mobileWebkit3d + Booleantrue for all webkit-based browsers in a mobile device supporting CSS transforms.
msPointer + Booleantrue for browsers implementing the Microsoft touch events model (notably IE10).
pointer + Booleantrue for all browsers supporting pointer events.
touch + Booleantrue for all browsers supporting touch events. +This does not necessarily mean that the browser is running in a computer with +a touchscreen, it only means that the browser is capable of understanding +touch events.
mobileOpera + Booleantrue for the Opera browser in a mobile device.
mobileGecko + Booleantrue for gecko-based browsers running in a mobile device.
retina + Booleantrue for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%.
canvas + Booleantrue when the browser supports <canvas>.
svg + Booleantrue when the browser supports SVG.
vml + Booleantrue if the browser supports VML.
+ +
+ + +

Util

Various utility functions, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> dest, <Object> src?)ObjectMerges the properties of the src object (or multiple objects) into dest object and returns the latter. Has an L.extend shortcut.
create(<Object> proto, <Object> properties?)ObjectCompatibility polyfill for Object.create
bind(<Function> fn, )FunctionReturns a new function bound to the arguments passed, like Function.prototype.bind. +Has a L.bind() shortcut.
stamp(<Object> obj)NumberReturns the unique ID of an object, assigning it one if it doesn't have it.
throttle(<Function> fn, <Number> time, <Object> context)FunctionReturns a function which executes function fn with the given scope context +(so that the this keyword refers to context inside fn's code). The function +fn will be called no more than one time per given amount of time. The arguments +received by the bound function will be any arguments passed when binding the +function, followed by any arguments passed when invoking the bound function. +Has an L.throttle shortcut.
wrapNum(<Number> num, <Number[]> range, <Boolean> includeMax?)NumberReturns the number num modulo range in such a way so it lies within +range[0] and range[1]. The returned value will be always smaller than +range[1] unless includeMax is set to true.
falseFn()FunctionReturns a function which always returns false.
formatNum(<Number> num, <Number> digits?)NumberReturns the number num rounded to digits decimals, or to 6 decimals by default.
trim(<String> str)StringCompatibility polyfill for String.prototype.trim
splitWords(<String> str)String[]Trims and splits the string on whitespace and returns the array of parts.
setOptions(<Object> obj, <Object> options)ObjectMerges the given properties to the options of the obj object, returning the resulting options. See Class options. Has an L.setOptions shortcut.
getParamString(<Object> obj, <String> existingUrl?, <Boolean> uppercase?)StringConverts an object into a parameter URL string, e.g. {a: "foo", b: "bar"} +translates to '?a=foo&b=bar'. If existingUrl is set, the parameters will +be appended at the end. If uppercase is true, the parameter names will +be uppercased (e.g. '?A=foo&B=bar')
template(<String> str, <Object> data)StringSimple templating facility, accepts a template string of the form 'Hello {a}, {b}' +and a data object like {a: 'foo', b: 'bar'}, returns evaluated string +('Hello foo, bar'). You can also specify functions instead of strings for +data values — they will be evaluated passing data as an argument.
isArray(obj)BooleanCompatibility polyfill for Array.isArray
indexOf(<Array> array, <Object> el)NumberCompatibility polyfill for Array.prototype.indexOf
requestAnimFrame(<Function> fn, <Object> context?, <Boolean> immediate?)NumberSchedules fn to be executed when the browser repaints. fn is bound to +context if given. When immediate is set, fn is called immediately if +the browser doesn't have native support for +window.requestAnimationFrame, +otherwise it's delayed. Returns a request ID that can be used to cancel the request.
cancelAnimFrame(<Number> id)undefinedCancels a previous requestAnimFrame. See also window.cancelAnimationFrame.
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lastId + NumberLast unique ID used by stamp()
emptyImageUrl + StringData URI string containing a base64-encoded empty GIF image. +Used as a hack to free memory from unused images on WebKit-powered +mobile devices (by setting image src to this string).
+ +
+ + +

Transformation

Represents an affine transformation: a set of coefficients a, b, c, d +for transforming a point of a form (x, y) into (a*x + b, c*y + d) and doing +the reverse. Used by Leaflet in its projections code.

+ +
+

Usage example

+ +
+ + + + + +
var transformation = L.transformation(2, 5, -1, 10),
+    p = L.point(1, 2),
+    p2 = transformation.transform(p), //  L.point(7, 8)
+    p3 = transformation.untransform(p2); //  L.point(1, 2)
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.transformation(<Number> a, <Number> b, <Number> c, <Number> d)Instantiates a Transformation object with the given coefficients.
L.transformation(<Array> coefficients)Expects an coefficients array of the form +[a: Number, b: Number, c: Number, d: Number].
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
transform(<Point> point, <Number> scale?)Point

Returns a transformed point, optionally multiplied by the given scale. +Only accepts actual L.Point instances, not arrays.

+
untransform(<Point> point, <Number> scale?)Point

Returns the reverse transformation of the given point, optionally divided +by the given scale. Only accepts actual L.Point instances, not arrays.

+
+ +
+ + +

LineUtil

Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
simplify(<Point[]> points, <Number> tolerance)Point[]Dramatically reduces the number of points in a polyline while retaining +its shape and returns a new array of simplified points, using the +Douglas-Peucker algorithm. +Used for a huge performance boost when processing/displaying Leaflet polylines for +each zoom level and also reducing visual noise. tolerance affects the amount of +simplification (lesser value means higher quality but slower and with more points). +Also released as a separated micro-library Simplify.js.
pointToSegmentDistance(<Point> p, <Point> p1, <Point> p2)NumberReturns the distance between point p and segment p1 to p2.
closestPointOnSegment(<Point> p, <Point> p1, <Point> p2)NumberReturns the closest point from a point p on a segment p1 to p2.
clipSegment(<Point> a, <Point> b, <Bounds> bounds, <Boolean> useLastCode?, <Boolean> round?)Point[]|BooleanClips the segment a to b by rectangular bounds with the +Cohen-Sutherland algorithm +(modifying the segment points directly!). Used by Leaflet to only show polyline +points that are on the screen or near, increasing performance.
isFlat(<LatLng[]> latlngs)BooleanReturns true if latlngs is a flat array, false is nested.
+ +
+ + +

PolyUtil

Various utility functions for polygon geometries.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + +
FunctionReturnsDescription
clipPolygon(<Point[]> points, <Bounds> bounds, <Boolean> round?)Point[]Clips the polygon geometry defined by the given points by the given bounds (using the Sutherland-Hodgman algorithm). +Used by Leaflet to only show polygon points that are on the screen or near, increasing +performance. Note that polygon points needs different algorithm for clipping +than polyline, so there's a separate method for it.
+ +
+ + +

DomEvent

Utility functions to work with the DOM events, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
on(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisAdds a listener function (fn) to a particular DOM event type of the +element el. You can optionally specify the context of the listener +(object the this keyword will point to). You can also pass several +space-separated types (e.g. 'click dblclick').
on(<HTMLElement> el, <Object> eventMap, <Object> context?)thisAdds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
off(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisRemoves a previously added listener function. +Note that if you passed a custom context to on, you must pass the same +context to off in order to remove the listener.
off(<HTMLElement> el, <Object> eventMap, <Object> context?)thisRemoves a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
stopPropagation(<DOMEvent> ev)thisStop the given event from propagation to parent elements. Used inside the listener functions: +
L.DomEvent.on(div, 'click', function (ev) {
+    L.DomEvent.stopPropagation(ev);
+});
+
disableScrollPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'mousewheel' events (plus browser variants).
disableClickPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'click', 'doubleclick', +'mousedown' and 'touchstart' events (plus browser variants).
preventDefault(<DOMEvent> ev)thisPrevents the default action of the DOM Event ev from happening (such as +following a link in the href of the a element, or doing a POST request +with page reload when a <form> is submitted). +Use it inside listener functions.
stop(<DOMEvent> ev)thisDoes stopPropagation and preventDefault at the same time.
getMousePosition(<DOMEvent> ev, <HTMLElement> container?)PointGets normalized mouse position from a DOM event relative to the +container or to the whole page if not specified.
getWheelDelta(<DOMEvent> ev)NumberGets normalized wheel delta from a mousewheel DOM event, in vertical +pixels scrolled (negative if scrolling down). +Events from pointing devices without precise scrolling are mapped to +a best guess of 60 pixels.
addListener()thisAlias to L.DomEvent.on
removeListener()thisAlias to L.DomEvent.off
+ +
+ + +

DomUtil

Utility functions to work with the DOM +tree, used by Leaflet internally. +Most functions expecting or returning a HTMLElement also work for +SVG elements. The only difference is that classes refer to CSS classes +in HTML and SVG classes in SVG.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
get(<String|HTMLElement> id)HTMLElementReturns an element given its DOM id, or returns the element itself +if it was passed directly.
getStyle(<HTMLElement> el, <String> styleAttrib)StringReturns the value for a certain style attribute on an element, +including computed values or values set through CSS.
create(<String> tagName, <String> className?, <HTMLElement> container?)HTMLElementCreates an HTML element with tagName, sets its class to className, and optionally appends it to container element.
remove(<HTMLElement> el)Removes el from its parent element
empty(<HTMLElement> el)Removes all of el's children elements from el
toFront(<HTMLElement> el)Makes el the last child of its parent, so it renders in front of the other children.
toBack(<HTMLElement> el)Makes el the first child of its parent, so it renders behind the other children.
hasClass(<HTMLElement> el, <String> name)BooleanReturns true if the element's class attribute contains name.
addClass(<HTMLElement> el, <String> name)Adds name to the element's class attribute.
removeClass(<HTMLElement> el, <String> name)Removes name from the element's class attribute.
setClass(<HTMLElement> el, <String> name)Sets the element's class.
getClass(<HTMLElement> el)StringReturns the element's class.
setOpacity(<HTMLElement> el, <Number> opacity)Set the opacity of an element (including old IE support). +opacity must be a number from 0 to 1.
testProp(<String[]> props)String|falseGoes through the array of style names and returns the first name +that is a valid style name for an element. If no such name is found, +it returns false. Useful for vendor-prefixed styles like transform.
setTransform(<HTMLElement> el, <Point> offset, <Number> scale?)Resets the 3D CSS transform of el so it is translated by offset pixels +and optionally scaled by scale. Does not have an effect if the +browser doesn't support 3D CSS transforms.
setPosition(<HTMLElement> el, <Point> position)Sets the position of el to coordinates specified by position, +using CSS translate or top/left positioning depending on the browser +(used by Leaflet internally to position its layers).
getPosition(<HTMLElement> el)PointReturns the coordinates of an element previously positioned with setPosition.
disableTextSelection()Prevents the user from generating selectstart DOM events, usually generated +when the user drags the mouse through a page with text. Used internally +by Leaflet to override the behaviour of any click-and-drag interaction on +the map. Affects drag interactions on the whole document.
enableTextSelection()Cancels the effects of a previous L.DomUtil.disableTextSelection.
disableImageDrag()As L.DomUtil.disableTextSelection, but +for dragstart DOM events, usually generated when the user drags an image.
enableImageDrag()Cancels the effects of a previous L.DomUtil.disableImageDrag.
preventOutline(<HTMLElement> el)Makes the outline +of the element el invisible. Used internally by Leaflet to prevent +focusable elements from displaying an outline when the user performs a +drag interaction on them.
restoreOutline()Cancels the effects of a previous L.DomUtil.preventOutline.
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
TRANSFORM + StringVendor-prefixed transform style name (e.g. 'webkitTransform' for WebKit).
TRANSITION + StringVendor-prefixed transition style name.
TRANSITION_END + StringVendor-prefixed transitionend event name.
+ +
+ + +

PosAnimation

Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.

+ +
+

Usage example

+ +
+ + + + + +
var fx = new L.PosAnimation();
+fx.run(el, [300, 500], 0.5);
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.PosAnimation()Creates a PosAnimation object.
+ + +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
start + EventFired when the animation starts
step + EventFired continuously during the animation.
end + EventFired when the animation ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
run(<HTMLElement> el, <Point> newPos, <Number> duration?, <Number> easeLinearity?)

Run an animation of a given element to a new position, optionally setting +duration in seconds (0.25 by default) and easing linearity factor (3rd +argument of the cubic bezier curve, +0.5 by default).

+
stop()

Stops the animation (if currently running).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Draggable

A class for making DOM elements draggable (including touch support). +Used internally for map and marker dragging. Only works for elements +that were positioned with L.DomUtil.setPosition.

+ +
+

Usage example

+ +
+ + + + + +
var draggable = new L.Draggable(elementToDrag);
+draggable.enable();
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.Draggable(<HTMLElement> el, <HTMLElement> dragHandle?, <Boolean> preventOutline?, <Draggable options> options?)Creates a Draggable object for moving el when you start dragging the dragHandle element (equals el itself by default).
+ + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
clickToleranceNumber + 3The max number of pixels a user can shift the mouse pointer during a click +for it to be considered a valid click (as opposed to a mouse drag).
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
down + EventFired when a drag is about to start.
dragstart + EventFired when a drag starts
predrag + EventFired continuously during dragging before each corresponding +update of the element's position.
drag + EventFired continuously during dragging.
dragend + DragEndEventFired when the drag ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()

Enables the dragging ability

+
disable()

Disables the dragging ability

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Class

L.Class powers the OOP facilities of Leaflet and is used to create almost all of the Leaflet classes documented here. +In addition to implementing a simple classical inheritance model, it introduces several special properties for convenient code organization — options, includes and statics.

+ +
+

Usage example

+ +
+ + + + + +
var MyClass = L.Class.extend({
+initialize: function (greeter) {
+    this.greeter = greeter;
+    // class constructor
+},
+greet: function (name) {
+    alert(this.greeter + ', ' + name)
+    }
+});
+// create instance of MyClass, passing "Hello" to the constructor
+var a = new MyClass("Hello");
+// call greet method, alerting "Hello, World"
+a.greet("World");
+
+ + + +
+ +

Class Factories

+ + + +

You may have noticed that Leaflet objects are created without using +the new keyword. This is achieved by complementing each class with a +lowercase factory method:

+
new L.Map('map'); // becomes:
+L.map('map');
+
+

The factories are implemented very easily, and you can do this for your own classes:

+
L.map = function (id, options) {
+    return new L.Map(id, options);
+};
+
+ + + +
+ +

Inheritance

+ + + +

You use L.Class.extend to define new classes, but you can use the same method on any class to inherit from it:

+
var MyChildClass = MyClass.extend({
+    // ... new properties and methods
+});
+
+

This will create a class that inherits all methods and properties of the parent class (through a proper prototype chain), adding or overriding the ones you pass to extend. It will also properly react to instanceof:

+
var a = new MyChildClass();
+a instanceof MyChildClass; // true
+a instanceof MyClass; // true
+
+

You can call parent methods (including constructor) from corresponding child ones (as you do with super calls in other languages) by accessing parent class prototype and using JavaScript's call or apply:

+
var MyChildClass = MyClass.extend({
+    initialize: function () {
+        MyClass.prototype.initialize.call(this, "Yo");
+    },
+    greet: function (name) {
+        MyClass.prototype.greet.call(this, 'bro ' + name + '!');
+    }
+});
+var a = new MyChildClass();
+a.greet('Jason'); // alerts "Yo, bro Jason!"
+
+ + +
+ +

Options

+ + + +

options is a special property that unlike other objects that you pass +to extend will be merged with the parent one instead of overriding it +completely, which makes managing configuration of objects and default +values convenient:

+
var MyClass = L.Class.extend({
+    options: {
+        myOption1: 'foo',
+        myOption2: 'bar'
+    }
+});
+var MyChildClass = MyClass.extend({
+    options: {
+        myOption1: 'baz',
+        myOption3: 5
+    }
+});
+var a = new MyChildClass();
+a.options.myOption1; // 'baz'
+a.options.myOption2; // 'bar'
+a.options.myOption3; // 5
+
+

There's also L.Util.setOptions, a method for +conveniently merging options passed to constructor with the defaults +defines in the class:

+
var MyClass = L.Class.extend({
+    options: {
+        foo: 'bar',
+        bla: 5
+    },
+    initialize: function (options) {
+        L.Util.setOptions(this, options);
+        ...
+    }
+});
+var a = new MyClass({bla: 10});
+a.options; // {foo: 'bar', bla: 10}
+
+

Note that the options object allows any keys, not just +the options defined by the class and its base classes. +This means you can use the options object to store +application specific information, as long as you avoid +keys that are already used by the class in question.

+ + + +
+ +

Includes

+ + + +

includes is a special class property that merges all specified objects into the class (such objects are called mixins).

+
 var MyMixin = {
+    foo: function () { ... },
+    bar: 5
+};
+var MyClass = L.Class.extend({
+    includes: MyMixin
+});
+var a = new MyClass();
+a.foo();
+
+

You can also do such includes in runtime with the include method:

+
MyClass.include(MyMixin);
+
+

statics is just a convenience property that injects specified object properties as the static properties of the class, useful for defining constants:

+
var MyClass = L.Class.extend({
+    statics: {
+        FOO: 'bar',
+        BLA: 5
+    }
+});
+MyClass.FOO; // 'bar'
+
+ + + +
+ +

Constructor hooks

+ + + +

If you're a plugin developer, you often need to add additional initialization code to existing classes (e.g. editing hooks for L.Polyline). Leaflet comes with a way to do it easily using the addInitHook method:

+
MyClass.addInitHook(function () {
+    // ... do something in constructor additionally
+    // e.g. add event listeners, set custom properties etc.
+});
+
+

You can also use the following shortcut when you just need to make one additional method call:

+
MyClass.addInitHook('methodName', arg1, arg2, …);
+
+ + + +
+ + +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> props)FunctionExtends the current class given the properties to be included. +Returns a Javascript function that is a class constructor (to be called with new).
include(<Object> properties)thisIncludes a mixin into the current class.
mergeOptions(<Object> options)thisMerges options into the defaults of the class.
addInitHook(<Function> fn)thisAdds a constructor hook to the class.
+ +
+ + +

Evented

A set of methods shared between event-powered classes (like Map and Marker). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire 'click' event).

+ +
+

Usage example

+ +
+ + + + + +
map.on('click', function(e) {
+    alert(e.latlng);
+} );
+
+

Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:

+
function onClick(e) { ... }
+map.on('click', onClick);
+map.off('click', onClick);
+
+ + + +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+ + +

Layer

A set of methods from the Layer base class that all Leaflet layers use. +Inherits all methods, options and events from L.Evented.

+ +
+

Usage example

+ +
+ + + + + +
var layer = L.Marker(latlng).addTo(map);
+layer.addTo(map);
+layer.remove();
+
+ + + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Layer will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+ +

Extension methods

+ +
Every layer should extend from L.Layer and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)this

Should contain code that creates DOM elements for the layer, adds them to map panes where they should belong and puts listeners on relevant map events. Called on map.addLayer(layer).

+
onRemove(<Map> map)this

Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in onAdd. Called on map.removeLayer(layer).

+
getEvents()Object

This optional method should return an object like { viewreset: this._reset } for addEventListener. The event handlers in this object will be automatically added and removed from the map with your layer.

+
getAttribution()String

This optional method should return a string containing HTML to be shown on the Attribution control whenever the layer is visible.

+
beforeAdd(<Map> map)this

Optional method. Called on map.addLayer(layer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.

+
+ +
+ +

Popup methods

+ +
All layers share a set of methods convenient for binding popups to it. +
var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
+layer.openPopup();
+layer.closePopup();
+
+

Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+ +

Tooltip methods

+ +
All layers share a set of methods convenient for binding tooltips to it. +
var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
+layer.openTooltip();
+layer.closeTooltip();
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Interactive layer

Some Layers can be made interactive - when the user interacts +with such a layer, mouse events like click and mouseover can be handled. +Use the event handling methods to handle these events.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ +

Mouse events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Control

L.Control is a base class for implementing map controls. Handles positioning. +All other controls extend from this class.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Control will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+ +

Extension methods

+ +
Every control should extend from L.Control and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)HTMLElement

Should return the container DOM element for the control and add listeners on relevant map events. Called on control.addTo(map).

+
onRemove(<Map> map)

Optional method. Should contain all clean up code that removes the listeners previously added in onAdd. Called on control.remove().

+
+ +
+ + +

Handler

Abstract class for map interaction handlers

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()this

Enables the handler

+
disable()this

Disables the handler

+
enabled()Boolean

Returns true if the handler is enabled

+
+ +
+ +

Extension methods

+ +
Classes inheriting from Handler must implement the two following methods:
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHooks()

Called when the handler is enabled, should add event hooks.

+
removeHooks()

Called when the handler is disabled, should remove the event hooks added previously.

+
+ +
+ + +
+

Functions

+ +
+ +

There is static function which can be called without instantiating L.Handler:

+ + + + + + + + + + + + + + +
FunctionReturnsDescription
addTo(<Map> map, <String> name)thisAdds a new Handler to the given map with the given name.
+ +
+ + +

Projection

An object with methods for projecting geographical coordinates of the world onto +a flat surface (and back). See Map projection.

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
project(<LatLng> latlng)Point

Projects geographical coordinates into a 2D point. +Only accepts actual L.LatLng instances, not arrays.

+
unproject(<Point> point)LatLng

The inverse of project. Projects a 2D point into a geographical location. +Only accepts actual L.Point instances, not arrays. +Note that the projection instances do not inherit from Leafet's Class object, +and can't be instantiated. Also, new classes can't inherit from them, +and methods can't be added to them with the include function.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
bounds + BoundsThe bounds (specified in CRS units) where the projection is valid
+ +
+ + +
+

Defined projections

+ +
+ + + +
Leaflet comes with a set of already defined Projections out of the box:
+ + + + + + + + + + + + + + + + + + + +
ProjectionDescription
L.Projection.LonLatEquirectangular, or Plate Carree projection — the most simple projection, +mostly used by GIS enthusiasts. Directly maps x as longitude, and y as +latitude. Also suitable for flat worlds, e.g. game maps. Used by the +EPSG:4326 and Simple CRS.
L.Projection.MercatorElliptical Mercator projection — more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS.
L.Projection.SphericalMercatorSpherical Mercator projection — the most common projection for online maps, +used by almost all free and commercial tile providers. Assumes that Earth is +a sphere. Used by the EPSG:3857 CRS.
+ +
+ + +

CRS

+
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
latLngToPoint(<LatLng> latlng, <Number> zoom)Point

Projects geographical coordinates into pixel coordinates for a given zoom.

+
pointToLatLng(<Point> point, <Number> zoom)LatLng

The inverse of latLngToPoint. Projects pixel coordinates on a given +zoom into geographical coordinates.

+
project(<LatLng> latlng)Point

Projects geographical coordinates into coordinates in units accepted for +this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).

+
unproject(<Point> point)LatLng

Given a projected coordinate returns the corresponding LatLng. +The inverse of project.

+
scale(<Number> zoom)Number

Returns the scale used when transforming projected coordinates into +pixel coordinates for a particular zoom. For example, it returns +256 * 2^zoom for Mercator-based CRS.

+
zoom(<Number> scale)Number

Inverse of scale(), returns the zoom level corresponding to a scale +factor of scale.

+
getProjectedBounds(<Number> zoom)Bounds

Returns the projection's bounds scaled and transformed for the provided zoom.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +CRS's wrapLat and wrapLng properties, if they are outside the CRS's bounds.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring +that its center is within the CRS's bounds. +Only accepts actual L.LatLngBounds instances, not arrays.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
code + StringStandard code name of the CRS passed into WMS services (e.g. 'EPSG:3857')
wrapLng + Number[]An array of two numbers defining whether the longitude (horizontal) coordinate +axis wraps around a given range and how. Defaults to [-180, 180] in most +geographical CRSs. If undefined, the longitude axis does not wrap around.
wrapLat + Number[]Like wrapLng, but for the latitude (vertical) axis.
infinite + BooleanIf true, the coordinate space will be unbounded (infinite in both axes)
+ +
+ + +
+

Defined CRSs

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CRSDescription
L.CRS.EPSG3395Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.
L.CRS.EPSG3857The most common CRS for online maps, used by almost all free and commercial +tile providers. Uses Spherical Mercator projection. Set in by default in +Map's crs option.
L.CRS.EPSG4326A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. +Leaflet 1.0.x complies with the TMS coordinate scheme for EPSG:4326, +which is a breaking change from 0.7.x behaviour. If you are using a TileLayer +with this CRS, ensure that there are two 256x256 pixel tiles covering the +whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), +or (-180,-90) for TileLayers with the tms option set.
L.CRS.EarthServes as the base for CRS that are global such that they cover the earth. +Can only be used as the base for other CRS and cannot be used directly, +since it does not have a code, projection or transformation. distance() returns +meters.
L.CRS.SimpleA simple CRS that maps longitude and latitude into x and y directly. +May be used for maps of flat surfaces (e.g. game maps). Note that the y +axis should still be inverted (going from bottom to top). distance() returns +simple euclidean distance.
L.CRS.BaseObject that defines coordinate reference systems for projecting +geographical points into pixel (screen) coordinates and back (and to +coordinates in other units for WMS services). See +spatial reference system. +Leaflet defines the most usual CRSs by default. If you want to use a +CRS not defined by default, take a look at the +Proj4Leaflet plugin. +Note that the CRS instances do not inherit from Leafet's Class object, +and can't be instantiated. Also, new classes can't inherit from them, +and methods can't be added to them with the include function.
+ +
+ + +

Renderer

Base class for vector renderer implementations (SVG, Canvas). Handles the +DOM container of the renderer, its bounds, and its zoom animation. +A Renderer works as an implicit layer group for all Paths - the renderer +itself can be added or removed to the map. All paths use a renderer, which can +be implicit (the map will decide the type of renderer and use it automatically) +or explicit (using the renderer option of the path). +Do not use this class directly, use SVG and Canvas instead.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Event objects

Whenever a class inheriting from Evented fires an event, a listener function +will be called with an event argument, which is a plain object containing +information about the event. For example:

+
map.on('click', function(ev) {
+    alert(ev.latlng); // ev is an event object (MouseEvent in this case)
+});
+
+

The information available depends on the event type:

+ + + +
+

Event

+ +
+ + + +
The base event object. All other event objects contain these properties too.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+ + +
+ +
+

KeyboardEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
originalEvent + DOMEventThe original DOM KeyboardEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

MouseEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngThe geographical point where the mouse event occured.
layerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map layer.
containerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map сontainer.
originalEvent + DOMEventThe original DOM MouseEvent or DOM TouchEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

LocationEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngDetected geographical location of the user.
bounds + LatLngBoundsGeographical bounds of the area user is located in (with respect to the accuracy of location).
accuracy + NumberAccuracy of location in meters.
altitude + NumberHeight of the position above the WGS84 ellipsoid in meters.
altitudeAccuracy + NumberAccuracy of altitude in meters.
heading + NumberThe direction of travel in degrees counting clockwise from true North.
speed + NumberCurrent velocity in meters per second.
timestamp + NumberThe time when the position was acquired.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
message + StringError message.
code + NumberError code (if applicable).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

LayerEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

LayersControlEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
name + StringThe name of the layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

TileEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

TileErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
error + *Error passed to the tile's done() callback.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ResizeEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
oldSize + PointThe old size before resize event.
newSize + PointThe new size after the resize event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

GeoJSONEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer for the GeoJSON feature that is being added to the map.
properties + ObjectGeoJSON properties of the feature.
geometryType + StringGeoJSON geometry type of the feature.
id + StringGeoJSON ID of the feature (if present).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

PopupEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
popup + PopupThe popup that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

TooltipEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
tooltip + TooltipThe tooltip that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

DragEndEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
distance + NumberThe distance in pixels the draggable element was moved by.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ZoomAnimEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
center + LatLngThe current center of the map
zoom + NumberThe current zoom level of the map
noUpdate + BooleanWhether layers should update their contents due to this event
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +

DivOverlay

Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
offsetPoint + Point(0, 7)The offset of the popup position. Useful to control the anchor +of the popup when opening it on some overlays.
classNameString + ''A custom CSS class name to assign to the popup.
paneString + 'popupPane'Map pane where the popup will be added.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Global Switches

Global switches are created for rare cases and generally make +Leaflet to not detect a particular browser feature even if it's +there. You need to set the switch as a global variable to true +before including Leaflet on the page, like this:

+
<script>L_NO_TOUCH = true;</script>
+<script src="leaflet.js"></script>
+
+ + + + + + + + + + + + + + + + + +
SwitchDescription
L_NO_TOUCHForces Leaflet to not use touch events even if it detects them.
L_DISABLE_3DForces Leaflet to not use hardware-accelerated CSS 3D transforms for positioning (which may cause glitches in some rare environments) even if they're supported.
+ +

noConflict

This method restores the L global variable to the original value +it had before Leaflet inclusion, and returns the real Leaflet +namespace so you can put it elsewhere, like this:

+
<script src='libs/l.js'>
+<!-- L points to some other library -->
+<script src='leaflet.js'>
+<!-- you include Leaflet, it replaces the L variable to Leaflet namespace -->
+<script>
+var Leaflet = L.noConflict();
+// now L points to that other library again, and you can use Leaflet.Map etc.
+</script>
+
+ +

version

A constant that represents the Leaflet version in use.

+
L.version; // contains "1.0.0" (or whatever version is currently in use)
+
+ + + + + + + +
+ + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.1.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.1.html new file mode 100644 index 000000000..35d96e2b9 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.1.html @@ -0,0 +1,4 @@ +--- +layout: redirected +redirect_to: reference-1.3.0.html +--- \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.2.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.2.html new file mode 100644 index 000000000..82b61c7c0 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.2.html @@ -0,0 +1,24105 @@ +--- +layout: v2 +title: Documentation +bodyclass: api-page +--- + +

Leaflet API reference

+ +

This reference reflects Leaflet 1.3.2 and Leaflet 1.3.3. Check this list if you are using a different version of Leaflet.

+ +
+ +
+

UI Layers

+ +

Raster Layers

+ +

Vector Layers

+ +
+
+

Other Layers

+ +

Basic Types

+ +

Controls

+ +
+
+ + + + + + +

Utility

+ +

DOM Utility

+ +
+
+

Base Classes

+ + +

Misc

+ +
+
+ +

Map

The central class of the API — it is used to create a map on a page and manipulate it.

+ +
+

Usage example

+ +
+ + + + + +
// initialize the map on the "map" div with a given center and zoom
+var map = L.map('map', {
+    center: [51.505, -0.09],
+    zoom: 13
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.map(<String> id, <Map options> options?)Instantiates a map object given the DOM ID of a <div> element +and optionally an object literal with Map options.
L.map(<HTMLElement> el, <Map options> options?)Instantiates a map object given an instance of a <div> HTML element +and optionally an object literal with Map options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
preferCanvasBoolean + falseWhether Paths should be rendered on a Canvas renderer. +By default, all Paths are rendered in a SVG renderer.
+ +
+ +

Control options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionControlBoolean + trueWhether a attribution control is added to the map by default.
zoomControlBoolean + trueWhether a zoom control is added to the map by default.
+ +
+ +

Interaction Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
closePopupOnClickBoolean + trueSet it to false if you don't want popups to close when user clicks the map.
boxZoomBoolean + trueWhether the map can be zoomed to a rectangular area specified by +dragging the mouse while pressing the shift key.
doubleClickZoomBoolean|String + trueWhether the map can be zoomed in by double clicking on it and +zoomed out by double clicking while holding shift. If passed +'center', double-click zoom will zoom to the center of the + view regardless of where the mouse was.
draggingBoolean + trueWhether the map be draggable with mouse/touch or not.
zoomSnapNumber + 1Forces the map's zoom level to always be a multiple of this, particularly +right after a fitBounds() or a pinch-zoom. +By default, the zoom level snaps to the nearest integer; lower values +(e.g. 0.5 or 0.1) allow for greater granularity. A value of 0 +means the zoom level will not be snapped after fitBounds or a pinch-zoom.
zoomDeltaNumber + 1Controls how much the map's zoom level will change after a +zoomIn(), zoomOut(), pressing + +or - on the keyboard, or using the zoom controls. +Values smaller than 1 (e.g. 0.5) allow for greater granularity.
trackResizeBoolean + trueWhether the map automatically handles browser window resize to update itself.
+ +
+ +

Panning Inertia Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
inertiaBoolean + *If enabled, panning of the map will have an inertia effect where +the map builds momentum while dragging and continues moving in +the same direction for some time. Feels especially nice on touch +devices. Enabled by default unless running on old Android devices.
inertiaDecelerationNumber + 3000The rate with which the inertial movement slows down, in pixels/second².
inertiaMaxSpeedNumber + InfinityMax speed of the inertial movement, in pixels/second.
easeLinearityNumber + 0.2
worldCopyJumpBoolean + falseWith this option enabled, the map tracks when you pan to another "copy" +of the world and seamlessly jumps to the original one so that all overlays +like markers and vector layers are still visible.
maxBoundsViscosityNumber + 0.0If maxBounds is set, this option will control how solid the bounds +are when dragging the map around. The default value of 0.0 allows the +user to drag outside the bounds at normal speed, higher values will +slow down map dragging outside bounds, and 1.0 makes the bounds fully +solid, preventing the user from dragging outside the bounds.
+ +
+ +

Keyboard Navigation Options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
keyboardBoolean + trueMakes the map focusable and allows users to navigate the map with keyboard +arrows and +/- keys.
keyboardPanDeltaNumber + 80Amount of pixels to pan when pressing an arrow key.
+ +
+ +

Mousewheel options

+ + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
scrollWheelZoomBoolean|String + trueWhether the map can be zoomed by using the mouse wheel. If passed 'center', +it will zoom to the center of the view regardless of where the mouse was.
wheelDebounceTimeNumber + 40Limits the rate at which a wheel can fire (in milliseconds). By default +user can't zoom via wheel more often than once per 40 ms.
wheelPxPerZoomLevelNumber + 60How many scroll pixels (as reported by L.DomEvent.getWheelDelta) +mean a change of one full zoom level. Smaller values will make wheel-zooming +faster (and vice versa).
+ +
+ +

Touch interaction options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tapBoolean + trueEnables mobile hacks for supporting instant taps (fixing 200ms click +delay on iOS/Android) and touch holds (fired as contextmenu events).
tapToleranceNumber + 15The max number of pixels a user can shift his finger during touch +for it to be considered a valid tap.
touchZoomBoolean|String + *Whether the map can be zoomed by touch-dragging with two fingers. If +passed 'center', it will zoom to the center of the view regardless of +where the touch events (fingers) were. Enabled for touch-capable web +browsers except for old Androids.
bounceAtZoomLimitsBoolean + trueSet it to false if you don't want the map to zoom beyond min/max zoom +and then bounce back when pinch-zooming.
+ +
+ +

Map State Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
crsCRS + L.CRS.EPSG3857The Coordinate Reference System to use. Don't change this if you're not +sure what it means.
centerLatLng + undefinedInitial geographic center of the map
zoomNumber + undefinedInitial map zoom level
minZoomNumber + *Minimum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the lowest of their minZoom options will be used instead.
maxZoomNumber + *Maximum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the highest of their maxZoom options will be used instead.
layersLayer[] + []Array of layers that will be added to the map initially
maxBoundsLatLngBounds + nullWhen this option is set, the map restricts the view to the given +geographical bounds, bouncing the user back if the user tries to pan +outside the view. To set the restriction dynamically, use +setMaxBounds method.
rendererRenderer + *The default method for drawing vector layers on the map. L.SVG +or L.Canvas by default depending on browser support.
+ +
+ +

Animation Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomAnimationBoolean + trueWhether the map zoom animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
zoomAnimationThresholdNumber + 4Won't animate zoom if the zoom difference exceeds this value.
fadeAnimationBoolean + trueWhether the tile fade animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
markerZoomAnimationBoolean + trueWhether markers animate their zoom with the zoom animation, if disabled +they will disappear for the length of the animation. By default it's +enabled in all browsers that support CSS3 Transitions except Android.
transform3DLimitNumber + 2^23Defines the maximum size of a CSS translation transform. The default +value should not be changed unless a web browser positions layers in +the wrong place after doing a large panBy.
+ +
+ + +
+

Events

+ +
+ +

Layer events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
baselayerchange + LayersControlEventFired when the base layer is changed through the layer control.
overlayadd + LayersControlEventFired when an overlay is selected through the layer control.
overlayremove + LayersControlEventFired when an overlay is deselected through the layer control.
layeradd + LayerEventFired when a new layer is added to the map.
layerremove + LayerEventFired when some layer is removed from the map
+ +
+ +

Map state change events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
zoomlevelschange + EventFired when the number of zoomlevels on the map is changed due +to adding or removing a layer.
resize + ResizeEventFired when the map is resized.
unload + EventFired when the map is destroyed with remove method.
viewreset + EventFired when the map needs to redraw its content (this usually happens +on map zoom or load). Very useful for creating custom overlays.
load + EventFired when the map is initialized (when its center and zoom are set +for the first time).
zoomstart + EventFired when the map zoom is about to change (e.g. before zoom animation).
movestart + EventFired when the view of the map starts changing (e.g. user starts dragging the map).
zoom + EventFired repeatedly during any change in zoom level, including zoom +and fly animations.
move + EventFired repeatedly during any movement of the map, including pan and +fly animations.
zoomend + EventFired when the map has changed, after any animations.
moveend + EventFired when the center of the map stops changing (e.g. user stopped +dragging the map).
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup is opened in the map
popupclose + PopupEventFired when a popup in the map is closed
autopanstart + EventFired when the map starts autopanning when opening a popup.
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip is opened in the map.
tooltipclose + TooltipEventFired when a tooltip in the map is closed.
+ +
+ +

Location events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
locationerror + ErrorEventFired when geolocation (using the locate method) failed.
locationfound + LocationEventFired when geolocation (using the locate method) +went successfully.
+ +
+ +

Interaction events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the map.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the map.
mousedown + MouseEventFired when the user pushes the mouse button on the map.
mouseup + MouseEventFired when the user releases the mouse button on the map.
mouseover + MouseEventFired when the mouse enters the map.
mouseout + MouseEventFired when the mouse leaves the map.
mousemove + MouseEventFired while the mouse moves over the map.
contextmenu + MouseEventFired when the user pushes the right mouse button on the map, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
keypress + KeyboardEventFired when the user presses a key from the keyboard while the map is focused.
preclick + MouseEventFired before mouse click on the map (sometimes useful when you +want something to happen on click before any existing click +handlers start running).
+ +
+ +

Other Methods

+ + + + + + + + + + + + + +
EventDataDescription
zoomanim + ZoomAnimEventFired on every frame of a zoom animation
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getRenderer(<Path> layer)Renderer

Returns the instance of Renderer that should be used to render the given +Path. It will ensure that the renderer options of the map and paths +are respected, and that the renderers do exist on the map.

+
+ +
+ +

Methods for Layers and Controls

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addControl(<Control> control)this

Adds the given control to the map

+
removeControl(<Control> control)this

Removes the given control from the map

+
addLayer(<Layer> layer)this

Adds the given layer to the map

+
removeLayer(<Layer> layer)this

Removes the given layer from the map.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the map

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the map, optionally specifying context of the iterator function.

+
map.eachLayer(function(layer){
+    layer.bindPopup('Hello');
+});
+
openPopup(<Popup> popup)this

Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).

+
openPopup(<String|HTMLElement> content, <LatLng> latlng, <Popup options> options?)this

Creates a popup with the specified content and options and opens it in the given point on a map.

+
closePopup(<Popup> popup?)this

Closes the popup previously opened with openPopup (or the given one).

+
openTooltip(<Tooltip> tooltip)this

Opens the specified tooltip.

+
openTooltip(<String|HTMLElement> content, <LatLng> latlng, <Tooltip options> options?)this

Creates a tooltip with the specified content and options and open it.

+
closeTooltip(<Tooltip> tooltip?)this

Closes the tooltip given as parameter.

+
+ +
+ +

Methods for modifying map state

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setView(<LatLng> center, <Number> zoom, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) with the given +animation options.

+
setZoom(<Number> zoom, <Zoom/pan options> options?)this

Sets the zoom of the map.

+
zoomIn(<Number> delta?, <Zoom options> options?)this

Increases the zoom of the map by delta (zoomDelta by default).

+
zoomOut(<Number> delta?, <Zoom options> options?)this

Decreases the zoom of the map by delta (zoomDelta by default).

+
setZoomAround(<LatLng> latlng, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified geographical point on the map +stationary (e.g. used internally for scroll zoom and double-click zoom).

+
setZoomAround(<Point> offset, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.

+
fitBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets a map view that contains the given geographical bounds with the +maximum zoom level possible.

+
fitWorld(<fitBounds options> options?)this

Sets a map view that mostly contains the whole world with the maximum +zoom level possible.

+
panTo(<LatLng> latlng, <Pan options> options?)this

Pans the map to a given center.

+
panBy(<Point> offset, <Pan options> options?)this

Pans the map by a given number of pixels (animated).

+
flyTo(<LatLng> latlng, <Number> zoom?, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) performing a smooth +pan-zoom animation.

+
flyToBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets the view of the map with a smooth animation like flyTo, +but takes a bounds parameter like fitBounds.

+
setMaxBounds(<Bounds> bounds)this

Restricts the map view to the given bounds (see the maxBounds option).

+
setMinZoom(<Number> zoom)this

Sets the lower limit for the available zoom levels (see the minZoom option).

+
setMaxZoom(<Number> zoom)this

Sets the upper limit for the available zoom levels (see the maxZoom option).

+
panInsideBounds(<LatLngBounds> bounds, <Pan options> options?)this

Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.

+
invalidateSize(<Zoom/pan options> options)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default. If options.pan is false, panning will not occur. +If options.debounceMoveend is true, it will delay moveend event so +that it doesn't happen often even if the method is called many +times in a row.

+
invalidateSize(<Boolean> animate)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default.

+
stop()this

Stops the currently running panTo or flyTo animation, if any.

+
+ +
+ +

Geolocation methods

+ + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
locate(<Locate options> options?)this

Tries to locate the user using the Geolocation API, firing a locationfound +event with location data on success or a locationerror event on failure, +and optionally sets the map view to the user's location with respect to +detection accuracy (or to the world view if geolocation failed). +Note that, if your page doesn't use HTTPS, this method will fail in +modern browsers (Chrome 50 and newer) +See Locate options for more details.

+
stopLocate()this

Stops watching location previously initiated by map.locate({watch: true}) +and aborts resetting the map view if map.locate was called with +{setView: true}.

+
+ +
+ +

Other Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHandler(<String> name, <Function> HandlerClass)this

Adds a new Handler to the map, given its name and constructor function.

+
remove()this

Destroys the map and clears all related event listeners.

+
createPane(<String> name, <HTMLElement> container?)HTMLElement

Creates a new map pane with the given name if it doesn't exist already, +then returns it. The pane is created as a child of container, or +as a child of the main map pane if not set.

+
getPane(<String|HTMLElement> pane)HTMLElement

Returns a map pane, given its name or its HTML element (its identity).

+
getPanes()Object

Returns a plain object containing the names of all panes as keys and +the panes as values.

+
getContainer()HTMLElement

Returns the HTML element that contains the map.

+
whenReady(<Function> fn, <Object> context?)this

Runs the given function fn when the map gets initialized with +a view (center and zoom) and at least one layer, or immediately +if it's already initialized, optionally passing a function context.

+
+ +
+ +

Methods for Getting Map State

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getCenter()LatLng

Returns the geographical center of the map view

+
getZoom()Number

Returns the current zoom level of the map view

+
getBounds()LatLngBounds

Returns the geographical bounds visible in the current map view

+
getMinZoom()Number

Returns the minimum zoom level of the map (if set in the minZoom option of the map or of any layers), or 0 by default.

+
getMaxZoom()Number

Returns the maximum zoom level of the map (if set in the maxZoom option of the map or of any layers).

+
getBoundsZoom(<LatLngBounds> bounds, <Boolean> inside?, <Point> padding?)Number

Returns the maximum zoom level on which the given bounds fit to the map +view in its entirety. If inside (optional) is set to true, the method +instead returns the minimum zoom level on which the map view fits into +the given bounds in its entirety.

+
getSize()Point

Returns the current size of the map container (in pixels).

+
getPixelBounds()Bounds

Returns the bounds of the current map view in projected pixel +coordinates (sometimes useful in layer and overlay implementations).

+
getPixelOrigin()Point

Returns the projected pixel coordinates of the top left point of +the map layer (useful in custom layer and overlay implementations).

+
getPixelWorldBounds(<Number> zoom?)Bounds

Returns the world's bounds in pixel coordinates for zoom level zoom. +If zoom is omitted, the map's current zoom level is used.

+
+ +
+ +

Conversion Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getZoomScale(<Number> toZoom, <Number> fromZoom)Number

Returns the scale factor to be applied to a map transition from zoom level +fromZoom to toZoom. Used internally to help with zoom animations.

+
getScaleZoom(<Number> scale, <Number> fromZoom)Number

Returns the zoom level that the map would end up at, if it is at fromZoom +level and everything is scaled by a factor of scale. Inverse of +getZoomScale.

+
project(<LatLng> latlng, <Number> zoom)Point

Projects a geographical coordinate LatLng according to the projection +of the map's CRS, then scales it according to zoom and the CRS's +Transformation. The result is pixel coordinate relative to +the CRS origin.

+
unproject(<Point> point, <Number> zoom)LatLng

Inverse of project.

+
layerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the origin pixel, +returns the corresponding geographical coordinate (for the current zoom level).

+
latLngToLayerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the origin pixel.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +map's CRS's wrapLat and wrapLng properties, if they are outside the +CRS's bounds. +By default this means longitude is wrapped around the dateline so its +value is between -180 and +180 degrees.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring that +its center is within the CRS's bounds. +By default this means the center longitude is wrapped around the dateline so its +value is between -180 and +180 degrees, and the majority of the bounds +overlaps the CRS's bounds.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates according to +the map's CRS. By default this measures distance in meters.

+
containerPointToLayerPoint(<Point> point)Point

Given a pixel coordinate relative to the map container, returns the corresponding +pixel coordinate relative to the origin pixel.

+
layerPointToContainerPoint(<Point> point)Point

Given a pixel coordinate relative to the origin pixel, +returns the corresponding pixel coordinate relative to the map container.

+
containerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the map container, returns +the corresponding geographical coordinate (for the current zoom level).

+
latLngToContainerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the map container.

+
mouseEventToContainerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to the +map container where the event took place.

+
mouseEventToLayerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to +the origin pixel where the event took place.

+
mouseEventToLatLng(<MouseEvent> ev)LatLng

Given a MouseEvent object, returns geographical coordinate where the +event took place.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Handlers

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
boxZoom + HandlerBox (shift-drag with mouse) zoom handler.
doubleClickZoom + HandlerDouble click zoom handler.
dragging + HandlerMap dragging handler (by both mouse and touch).
keyboard + HandlerKeyboard navigation handler.
scrollWheelZoom + HandlerScroll wheel zoom handler.
tap + HandlerMobile touch hacks (quick tap and touch hold) handler.
touchZoom + HandlerTouch zoom handler.
+ +
+ + +
+

Map panes

+ +
+ + + +
Panes are DOM elements used to control the ordering of layers on the map. You +can access panes with map.getPane or +map.getPanes methods. New panes can be created with the +map.createPane method. +Every map has the following default panes that differ only in zIndex.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PaneTypeZ-indexDescription
mapPaneHTMLElement + 'auto'Pane that contains all other map panes
tilePaneHTMLElement + 200Pane for GridLayers and TileLayers
overlayPaneHTMLElement + 400Pane for vectors (Paths, like Polylines and Polygons), ImageOverlays and VideoOverlays
shadowPaneHTMLElement + 500Pane for overlay shadows (e.g. Marker shadows)
markerPaneHTMLElement + 600Pane for Icons of Markers
tooltipPaneHTMLElement + 650Pane for Tooltips.
popupPaneHTMLElement + 700Pane for Popups.
+ +
+ + +
+ +
+

Locate options

+ +
+ + + +
Some of the geolocation methods for Map take in an options parameter. This +is a plain javascript object with the following optional components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
watchBoolean + falseIf true, starts continuous watching of location changes (instead of detecting it +once) using W3C watchPosition method. You can later stop watching using +map.stopLocate() method.
setViewBoolean + falseIf true, automatically sets the map view to the user location with respect to +detection accuracy, or to world view if geolocation failed.
maxZoomNumber + InfinityThe maximum zoom for automatic view setting when using setView option.
timeoutNumber + 10000Number of milliseconds to wait for a response from geolocation before firing a +locationerror event.
maximumAgeNumber + 0Maximum age of detected location. If less than this amount of milliseconds +passed since last geolocation response, locate will return a cached location.
enableHighAccuracyBoolean + falseEnables high accuracy, see description in the W3C spec.
+ +
+ + +
+ +
+

Zoom options

+ +
+ + + +
Some of the Map methods which modify the zoom level take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+ + +
+ +
+

Pan options

+ +
+ + + +
Some of the Map methods which modify the center of the map take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If true, panning will always be animated if possible. If false, it will +not animate panning, either resetting the map view if panning more than a +screen away, or just setting a new offset for the map pane (except for panBy +which always does the latter).
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+ + +
+ +
+

Zoom/pan options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +
+ +
+

FitBounds options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingTopLeftPoint + [0, 0]Sets the amount of padding in the top left corner of a map container that +shouldn't be accounted for when setting the view to fit bounds. Useful if you +have some control overlays on the map like a sidebar and you don't want them +to obscure objects you're zooming to.
paddingBottomRightPoint + [0, 0]The same for the bottom right corner of the map.
paddingPoint + [0, 0]Equivalent of setting both top left and bottom right padding to the same value.
maxZoomNumber + nullThe maximum possible zoom to use.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +

Marker

L.Marker is used to display clickable/draggable icons on the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.marker([50.5, 30.5]).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.marker(<LatLng> latlng, <Marker options> options?)Instantiates a Marker object given a geographical point and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconIcon + *Icon instance to use for rendering the marker. +See Icon documentation for details on how to customize the marker icon. +If not specified, a common instance of L.Icon.Default is used.
draggableBoolean + falseWhether the marker is draggable with mouse/touch or not.
autoPanBoolean + falseSet it to true if you want the map to do panning animation when marker hits the edges.
autoPanPaddingPoint + Point(50, 50)Equivalent of setting both top left and bottom right autopan padding to the same value.
autoPanSpeedNumber + 10Number of pixels the map should move by.
keyboardBoolean + trueWhether the marker can be tabbed to with a keyboard and clicked by pressing enter.
titleString + ''Text for the browser tooltip that appear on marker hover (no tooltip by default).
altString + ''Text for the alt attribute of the icon image (useful for accessibility).
zIndexOffsetNumber + 0By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like 1000 (or high negative value, respectively).
opacityNumber + 1.0The opacity of the marker.
riseOnHoverBoolean + falseIf true, the marker will get on top of others when you hover the mouse over it.
riseOffsetNumber + 250The z-index offset used for the riseOnHover feature.
paneString + 'markerPane'Map pane where the markers icon will be added.
bubblingMouseEventsBoolean + falseWhen true, a mouse event on this marker will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + +
In addition to shared layer methods like addTo() and remove() and popup methods like bindPopup() you can also use the following methods:
+ + + + + + + + + + + + +
EventDataDescription
move + EventFired when the marker is moved via setLatLng or by dragging. Old and new coordinates are included in event arguments as oldLatLng, latlng.
+ +
+ +

Dragging events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
dragstart + EventFired when the user starts dragging the marker.
movestart + EventFired when the marker starts moving (because of dragging).
drag + EventFired repeatedly while the user drags the marker.
dragend + DragEndEventFired when the user stops dragging the marker.
moveend + EventFired when the marker stops moving (because of dragging).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the marker (as a GeoJSON Point Feature).

+
getLatLng()LatLng

Returns the current geographical position of the marker.

+
setLatLng(<LatLng> latlng)this

Changes the marker position to the given point.

+
setZIndexOffset(<Number> offset)this

Changes the zIndex offset of the marker.

+
setIcon(<Icon> icon)this

Changes the marker icon.

+
setOpacity(<Number> opacity)this

Changes the opacity of the marker.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Interaction handlers

+ +
Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see Handler methods). Example: +
marker.dragging.disable();
+
+ + + + + + + + + + + + +
PropertyTypeDescription
dragging + HandlerMarker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set marker.options.draggable).
+ +
+ + +

Used to open popups in certain places of the map. Use Map.openPopup to +open popups while making sure that only one popup is open at one time +(recommended for usability), or use Map.addLayer to open as many as you want.

+ +
+ + +
+ + + + + +

If you want to just bind a popup to marker click and then open it, it's really easy:

+
marker.bindPopup(popupContent).openPopup();
+
+

Path overlays like polylines also have a bindPopup method. +Here's a more complicated way to open a popup on a map:

+
var popup = L.popup()
+    .setLatLng(latlng)
+    .setContent('<p>Hello world!<br />This is a nice popup.</p>')
+    .openOn(map);
+
+ + + +
+ + +
+ + +
+ + + + + + + + + + + + + + +
FactoryDescription
+ +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +

Tooltip

Used to display small texts on top of map layers.

+ +
+

Usage example

+ +
+ + + + + +
marker.bindTooltip("my tooltip text").openTooltip();
+
+

Note about tooltip offset. Leaflet takes two options in consideration +for computing tooltip offsetting:

+
    +
  • the offset Tooltip option: it defaults to [0, 0], and it's specific to one tooltip. +Add a positive x offset to move the tooltip to the right, and a positive y offset to +move it to the bottom. Negatives will move to the left and top.
  • +
  • the tooltipAnchor Icon option: this will only be considered for Marker. You +should adapt this value if you use a custom icon.
  • +
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tooltip(<Tooltip options> options?, <Layer> source?)Instantiates a Tooltip object given an optional options object that describes its appearance and location and an optional source object that is used to tag the tooltip with a reference to the Layer to which it refers.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'tooltipPane'Map pane where the tooltip will be added.
offsetPoint + Point(0, 0)Optional offset of the tooltip position.
directionString + 'auto'Direction where to open the tooltip. Possible values are: right, left, +top, bottom, center, auto. +auto will dynamically switch between right and left according to the tooltip +position on the map.
permanentBoolean + falseWhether to open the tooltip permanently or only on mouseover.
stickyBoolean + falseIf true, the tooltip will follow the mouse instead of being fixed at the feature center.
interactiveBoolean + falseIf true, the tooltip will listen to the feature events.
opacityNumber + 0.9Tooltip container opacity.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
classNameString + ''A custom CSS class name to assign to the popup.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer

Used to load and display tile layers on the map. Extends GridLayer.

+ +
+

Usage example

+ +
+ + + + + +
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
+
+ + + +
+ +

URL template

+ + + +

A string of the following form:

+
'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
+

{s} means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; a, b or c by default, can be omitted), {z} — zoom level, {x} and {y} — tile coordinates. {r} can be used to add "@2x" to the URL to load retina tiles. +You can use custom keys in the template, which will be evaluated from TileLayer options, like this:

+
L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
+
+ + +
+ + +
+

Creation

+ +
+ +

Extension methods

+ + + + + + + + + + + + +
FactoryDescription
L.tilelayer(<String> urlTemplate, <TileLayer options> options?)Instantiates a tile layer object given a URL template and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the tiles. +If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data. +Refer to CORS Settings for valid String values.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropriate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+ +

Extension methods

+ +
Layers extending TileLayer might reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
getTileUrl(<Object> coords)String

Called only internally, returns the URL for a tile given its coordinates. +Classes extending TileLayer can override this function to provide custom tile URL naming schemes.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer.WMS

Used to display WMS services as tile layers on the map. Extends TileLayer.

+ +
+

Usage example

+ +
+ + + + + +
var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
+    layers: 'nexrad-n0r-900913',
+    format: 'image/png',
+    transparent: true,
+    attribution: "Weather data © 2012 IEM Nexrad"
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tileLayer.wms(<String> baseUrl, <TileLayer.WMS options> options)Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.
+ +
+ + +
+

Options

+ +
+ + + +
If any custom options not documented here are used, they will be sent to the +WMS server as extra parameters in each request URL. This can be useful for +non-standard vendor WMS parameters.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
layersString + ''(required) Comma-separated list of WMS layers to show.
stylesString + ''Comma-separated list of WMS styles.
formatString + 'image/jpeg'WMS image format (use 'image/png' for layers with transparency).
transparentBoolean + falseIf true, the WMS service will return images with transparency.
versionString + '1.1.1'Version of the WMS service to use
crsCRS + nullCoordinate Reference System to use for the WMS requests, defaults to +map CRS. Don't change this if you're not sure what it means.
uppercaseBoolean + falseIf true, WMS request parameter keys will be uppercase.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the tiles. +If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data. +Refer to CORS Settings for valid String values.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setParams(<Object> params, <Boolean> noRedraw?)this

Merges an object with the new parameters and re-requests tiles on the current screen (unless noRedraw was set to true).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropriate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

ImageOverlay

Used to load and display a single image over specific bounds of the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
+    imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
+L.imageOverlay(imageUrl, imageBounds).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.imageOverlay(<String> imageUrl, <LatLngBounds> bounds, <ImageOverlay options> options?)Instantiates an image overlay object given the URL of the image and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the image. +If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data. +Refer to CORS Settings for valid String values.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the tile layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the ImageOverlay layer has loaded its image
error + EventFired when the ImageOverlay layer has loaded its image
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers +Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
getElement()HTMLElement

Returns the instance of HTMLImageElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

VideoOverlay

Used to load and display a video player over specific bounds of the map. Extends ImageOverlay. +A video overlay uses the <video> +HTML5 element.

+ +
+

Usage example

+ +
+ + + + + +
var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
+    videoBounds = [[ 32, -130], [ 13, -100]];
+L.videoOverlay(videoUrl, videoBounds ).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.videoOverlay(<String|Array|HTMLVideoElement> video, <LatLngBounds> bounds, <VideoOverlay options> options?)Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
autoplayBoolean + trueWhether the video starts playing automatically when loaded.
loopBoolean + trueWhether the video will loop back to the beginning when played.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the image. +If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data. +Refer to CORS Settings for valid String values.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the tile layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the video has finished loading the first frame
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
error + EventFired when the ImageOverlay layer has loaded its image
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getElement()HTMLVideoElement

Returns the instance of HTMLVideoElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers +Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Path

An abstract class that contains options and constants shared between vector +overlays (Polygon, Polyline, Circle). Do not use it directly. Extends Layer.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polyline

A class for drawing polyline overlays on a map. Extends Path.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polyline from an array of LatLng points
+var latlngs = [
+    [45.51, -122.68],
+    [37.77, -122.43],
+    [34.04, -118.2]
+];
+var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polyline
+map.fitBounds(polyline.getBounds());
+
+

You can also pass a multi-dimensional array to represent a MultiPolyline shape:

+
// create a red polyline from an array of arrays of LatLng points
+var latlngs = [
+    [[45.51, -122.68],
+     [37.77, -122.43],
+     [34.04, -118.2]],
+    [[40.78, -73.91],
+     [41.83, -87.62],
+     [32.76, -96.72]]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polyline(<LatLng[]> latlngs, <Polyline options> options?)Instantiates a polyline object given an array of geographical points and +optionally an options object. You can create a Polyline object with +multiple separate lines (MultiPolyline) by passing an array of arrays +of geographic points.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polyline (as a GeoJSON LineString or MultiLineString Feature).

+
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint(<Point> p)Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polygon

A class for drawing polygon overlays on a map. Extends Polyline. +Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polygon from an array of LatLng points
+var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
+var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polygon
+map.fitBounds(polygon.getBounds());
+
+

You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:

+
var latlngs = [
+  [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+  [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+];
+
+

Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.

+
var latlngs = [
+  [ // first polygon
+    [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+    [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+  ],
+  [ // second polygon
+    [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
+  ]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polygon(<LatLng[]> latlngs, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint(<Point> p)Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Rectangle

A class for drawing rectangle overlays on a map. Extends Polygon.

+ +
+

Usage example

+ +
+ + + + + +
// define rectangle geographical bounds
+var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
+// create an orange rectangle
+L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
+// zoom the map to the rectangle bounds
+map.fitBounds(bounds);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.rectangle(<LatLngBounds> latLngBounds, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setBounds(<LatLngBounds> latLngBounds)this

Redraws the rectangle with the passed bounds.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint(<Point> p)Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Circle

A class for drawing circle overlays on a map. Extends CircleMarker. +It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).

+ +
+

Usage example

+ +
+ + + + + +
L.circle([50.5, 30.5], {radius: 200}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.circle(<LatLng> latlng, <Circle options> options?)Instantiates a circle object given a geographical point, and an options object +which contains the circle radius.
L.circle(<LatLng> latlng, <Number> radius, <Circle options> options?)Obsolete way of instantiating a circle, for compatibility with 0.7.x code. +Do not use in new applications or plugins.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + Radius of the circle, in meters.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setRadius(<Number> radius)this

Sets the radius of a circle. Units are in meters.

+
getRadius()Number

Returns the current radius of a circle. Units are in meters.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

CircleMarker

A circle of a fixed size with radius specified in pixels. Extends Path.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.circleMarker(<LatLng> latlng, <CircleMarker options> options?)Instantiates a circle marker object given a geographical point, and an optional options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + 10Radius of the circle marker, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
setRadius(<Number> radius)this

Sets the radius of a circle marker. Units are in pixels.

+
getRadius()Number

Returns the current radius of the circle

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

SVG

Allows vector layers to be displayed with SVG. +Inherits Renderer. +Due to technical limitations, SVG is not +available in all web browsers, notably Android 2.x and 3.x. +Although SVG is not available on IE7 and IE8, these browsers support +VML +(a now deprecated technology), and the SVG renderer will fall back to VML in +this case. +Although SVG is not available on IE7 and IE8, these browsers support VML, and the SVG renderer will fall back to VML in this case. +VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility +with old versions of Internet Explorer.

+ +
+

Usage example

+ +
+ + + + + +

Use SVG by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.svg()
+});
+
+

Use a SVG renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.svg({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.svg(<Renderer options> options?)Creates a SVG renderer with the given options.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.SVG:
+ + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
create(<String> name)SVGElementReturns a instance of SVGElement, +corresponding to the class name passed. For example, using 'line' will return +an instance of SVGLineElement.
pointsToPath(<Point[]> rings, <Boolean> closed)StringGenerates a SVG path string for multiple rings, with each ring turning +into "M..L..L.." instructions
+ +
+ + +

Canvas

Allows vector layers to be displayed with <canvas>. +Inherits Renderer. +Due to technical limitations, Canvas is not +available in all web browsers, notably IE8, and overlapping geometries might +not display properly in some edge cases.

+ +
+

Usage example

+ +
+ + + + + +

Use Canvas by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.canvas()
+});
+
+

Use a Canvas renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.canvas({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.canvas(<Renderer options> options?)Creates a Canvas renderer with the given options.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LayerGroup

Used to group several layers and handle them as one. If you add it to the map, +any layers added or removed from the group will be added/removed on the map as +well. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.layerGroup([marker1, marker2])
+    .addLayer(polyline)
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.layerGroup(<Layer[]> layers?, <Object> options?)Create a layer group, optionally given an initial set of layers and an options object.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

FeatureGroup

Extended LayerGroup that makes it easier to do the same thing to all its member layers:

+
    +
  • bindPopup binds a popup to all of the layers at once (likewise with bindTooltip)
  • +
  • Events are propagated to the FeatureGroup, so if the group has an event +handler, it will handle events from any of the layers. This includes mouse events +and custom events.
  • +
  • Has layeradd and layerremove events
  • +
+ +
+

Usage example

+ +
+ + + + + +
L.featureGroup([marker1, marker2, polyline])
+    .bindPopup('Hello world!')
+    .on('click', function() { alert('Clicked on a member of the group!'); })
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.featureGroup(<Layer[]> layers)Create a feature group, optionally given an initial set of layers.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setStyle(<Path options> style)this

Sets the given path options to each layer of the group that has a setStyle method.

+
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

GeoJSON

Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse +GeoJSON data and display it on the map. Extends FeatureGroup.

+ +
+

Usage example

+ +
+ + + + + +
L.geoJSON(data, {
+    style: function (feature) {
+        return {color: feature.properties.color};
+    }
+}).bindPopup(function (layer) {
+    return layer.feature.properties.description;
+}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.geoJSON(<Object> geojson?, <GeoJSON options> options?)Creates a GeoJSON layer. Optionally accepts an object in +GeoJSON format to display on the map +(you can alternatively add it later with addData method) and an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
pointToLayerFunction + *A Function defining how GeoJSON points spawn Leaflet layers. It is internally +called when data is added, passing the GeoJSON point feature and its LatLng. +The default is to spawn a default Marker: +
function(geoJsonPoint, latlng) {
+    return L.marker(latlng);
+}
+
styleFunction + *A Function defining the Path options for styling GeoJSON lines and polygons, +called internally when data is added. +The default value is to not override any defaults: +
function (geoJsonFeature) {
+    return {}
+}
+
onEachFeatureFunction + *A Function that will be called once for each created Feature, after it has +been created and styled. Useful for attaching events and popups to features. +The default is to do nothing with the newly created layers: +
function (feature, layer) {}
+
filterFunction + *A Function that will be used to decide whether to include a feature or not. +The default is to include all features: +
function (geoJsonFeature) {
+    return true;
+}
+
+

Note: dynamically changing the filter option will have effect only on newly +added data. It will not re-evaluate already included features.

coordsToLatLngFunction + *A Function that will be used for converting GeoJSON coordinates to LatLngs. +The default is the coordsToLatLng static method.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addData(data)this

Adds a GeoJSON object to the layer.

+
resetStyle(layer)this

Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.

+
setStyle(style)this

Changes styles of GeoJSON vector layers with the given style function.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.GeoJSON:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
geometryToLayer(<Object> featureData, <GeoJSON options> options?)LayerCreates a Layer from a given GeoJSON feature. Can use a custom +pointToLayer and/or coordsToLatLng +functions if provided as options.
coordsToLatLng(<Array> coords)LatLngCreates a LatLng object from an array of 2 numbers (longitude, latitude) +or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
coordsToLatLngs(<Array> coords, <Number> levelsDeep?, <Function> coordsToLatLng?)ArrayCreates a multidimensional array of LatLngs from a GeoJSON coordinates array. +levelsDeep specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default). +Can use a custom coordsToLatLng function.
latLngToCoords(<LatLng> latlng, <Number> precision?)ArrayReverse of coordsToLatLng
latLngsToCoords(<Array> latlngs, <Number> levelsDeep?, <Boolean> closed?)ArrayReverse of coordsToLatLngs +closed determines whether the first point should be appended to the end of the array to close the feature, only used when levelsDeep is 0. False by default.
asFeature(<Object> geojson)ObjectNormalize GeoJSON geometries/features into GeoJSON features.
+ +
+ + +

GridLayer

Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces TileLayer.Canvas. +GridLayer can be extended to create a tiled grid of HTML elements like <canvas>, <img> or <div>. GridLayer will handle creating and animating these DOM elements for you.

+ +
+

Usage example

+ +
+ +

Synchronous usage

+ + + +

To create a custom layer, extend GridLayer and implement the createTile() method, which will be passed a Point object with the x, y, and z (zoom level) coordinates to draw your tile.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords){
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // get a canvas context and draw something on it using coords.x, coords.y and coords.z
+        var ctx = tile.getContext('2d');
+        // return the tile so it can be rendered on screen
+        return tile;
+    }
+});
+
+ + + +
+ +

Asynchronous usage

+ + + +

Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the done() callback.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords, done){
+        var error;
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // draw something asynchronously and pass the tile to the done() callback
+        setTimeout(function() {
+            done(error, tile);
+        }, 1000);
+        return tile;
+    }
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.gridLayer(<GridLayer options> options?)Creates a new instance of GridLayer with the supplied options.
+ +
+ + +
+

Options

+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + undefinedThe maximum zoom level up to which this layer will be displayed (inclusive).
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+ +

Extension methods

+ +
Layers extending GridLayer shall reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, must be overridden by classes extending GridLayer. +Returns the HTMLElement corresponding to the given coords. If the done callback +is specified, it must be called when the tile has finished loading and drawing.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LatLng

Represents a geographical point with a certain latitude and longitude.

+ +
+

Usage example

+ +
+ + + + + +
var latlng = L.latLng(50.5, 30.5);
+

All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:

+
map.panTo([50, 30]);
+map.panTo({lon: 30, lat: 50});
+map.panTo({lat: 50, lng: 30});
+map.panTo(L.latLng(50, 30));
+

Note that LatLng does not inherit from Leaflet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLng(<Number> latitude, <Number> longitude, <Number> altitude?)Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).
L.latLng(<Array> coords)Expects an array of the form [Number, Number] or [Number, Number, Number] instead.
L.latLng(<Object> coords)Expects an plain object of the form {lat: Number, lng: Number} or {lat: Number, lng: Number, alt: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
equals(<LatLng> otherLatLng, <Number> maxMargin?)Boolean

Returns true if the given LatLng point is at the same position (within a small margin of error). The margin of error can be overridden by setting maxMargin to a small number.

+
toString()String

Returns a string representation of the point (for debugging purposes).

+
distanceTo(<LatLng> otherLatLng)Number

Returns the distance (in meters) to the given LatLng calculated using the Spherical Law of Cosines.

+
wrap()LatLng

Returns a new LatLng object with the longitude wrapped so it's always between -180 and +180 degrees.

+
toBounds(<Number> sizeInMeters)LatLngBounds

Returns a new LatLngBounds object in which each boundary is sizeInMeters/2 meters apart from the LatLng.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lat + NumberLatitude in degrees
lng + NumberLongitude in degrees
alt + NumberAltitude in meters (optional)
+ +
+ + +

LatLngBounds

Represents a rectangular geographical area on a map.

+ +
+

Usage example

+ +
+ + + + + +
var corner1 = L.latLng(40.712, -74.227),
+corner2 = L.latLng(40.774, -74.125),
+bounds = L.latLngBounds(corner1, corner2);
+
+

All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
map.fitBounds([
+    [40.712, -74.227],
+    [40.774, -74.125]
+]);
+
+

Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners outside the [-180, 180] degrees longitude range. +Note that LatLngBounds does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLngBounds(<LatLng> corner1, <LatLng> corner2)Creates a LatLngBounds object by defining two diagonally opposite corners of the rectangle.
L.latLngBounds(<LatLng[]> latlngs)Creates a LatLngBounds object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with fitBounds.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<LatLng> latlng)this

Extend the bounds to contain the given point

+
extend(<LatLngBounds> otherBounds)this

Extend the bounds to contain the given bounds

+
pad(<Number> bufferRatio)LatLngBounds

Returns bounds created by extending or retracting the current bounds by a given ratio in each direction. +For example, a ratio of 0.5 extends the bounds by 50% in each direction. +Negative values will retract the bounds.

+
getCenter()LatLng

Returns the center point of the bounds.

+
getSouthWest()LatLng

Returns the south-west point of the bounds.

+
getNorthEast()LatLng

Returns the north-east point of the bounds.

+
getNorthWest()LatLng

Returns the north-west point of the bounds.

+
getSouthEast()LatLng

Returns the south-east point of the bounds.

+
getWest()Number

Returns the west longitude of the bounds

+
getSouth()Number

Returns the south latitude of the bounds

+
getEast()Number

Returns the east longitude of the bounds

+
getNorth()Number

Returns the north latitude of the bounds

+
contains(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<LatLng> latlng)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.

+
toBBoxString()String

Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.

+
equals(<LatLngBounds> otherBounds, <Number> maxMargin?)Boolean

Returns true if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting maxMargin to a small number.

+
isValid()Boolean

Returns true if the bounds are properly initialized.

+
+ +
+ + +

Point

Represents a point with x and y coordinates in pixels.

+ +
+

Usage example

+ +
+ + + + + +
var point = L.point(200, 300);
+
+

All Leaflet methods and options that accept Point objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:

+
map.panBy([200, 300]);
+map.panBy(L.point(200, 300));
+
+

Note that Point does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.point(<Number> x, <Number> y, <Boolean> round?)Creates a Point object with the given x and y coordinates. If optional round is set to true, rounds the x and y values.
L.point(<Number[]> coords)Expects an array of the form [x, y] instead.
L.point(<Object> coords)Expects a plain object of the form {x: Number, y: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
clone()Point

Returns a copy of the current point.

+
add(<Point> otherPoint)Point

Returns the result of addition of the current and the given points.

+
subtract(<Point> otherPoint)Point

Returns the result of subtraction of the given point from the current.

+
divideBy(<Number> num)Point

Returns the result of division of the current point by the given number.

+
multiplyBy(<Number> num)Point

Returns the result of multiplication of the current point by the given number.

+
scaleBy(<Point> scale)Point

Multiply each coordinate of the current point by each coordinate of +scale. In linear algebra terms, multiply the point by the +scaling matrix +defined by scale.

+
unscaleBy(<Point> scale)Point

Inverse of scaleBy. Divide each coordinate of the current point by +each coordinate of scale.

+
round()Point

Returns a copy of the current point with rounded coordinates.

+
floor()Point

Returns a copy of the current point with floored coordinates (rounded down).

+
ceil()Point

Returns a copy of the current point with ceiled coordinates (rounded up).

+
trunc()Point

Returns a copy of the current point with truncated coordinates (rounded towards zero).

+
distanceTo(<Point> otherPoint)Number

Returns the cartesian distance between the current and the given points.

+
equals(<Point> otherPoint)Boolean

Returns true if the given point has the same coordinates.

+
contains(<Point> otherPoint)Boolean

Returns true if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).

+
toString()String

Returns a string representation of the point for debugging purposes.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
x + NumberThe x coordinate of the point
y + NumberThe y coordinate of the point
+ +
+ + +

Bounds

Represents a rectangular area in pixel coordinates.

+ +
+

Usage example

+ +
+ + + + + +
var p1 = L.point(10, 10),
+p2 = L.point(40, 60),
+bounds = L.bounds(p1, p2);
+
+

All Leaflet methods that accept Bounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
otherBounds.intersects([[10, 10], [40, 60]]);
+
+

Note that Bounds does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.bounds(<Point> corner1, <Point> corner2)Creates a Bounds object from two corners coordinate pairs.
L.bounds(<Point[]> points)Creates a Bounds object from the given array of points.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<Point> point)this

Extends the bounds to contain the given point.

+
getCenter(<Boolean> round?)Point

Returns the center point of the bounds.

+
getBottomLeft()Point

Returns the bottom-left point of the bounds.

+
getTopRight()Point

Returns the top-right point of the bounds.

+
getTopLeft()Point

Returns the top-left point of the bounds (i.e. this.min).

+
getBottomRight()Point

Returns the bottom-right point of the bounds (i.e. this.max).

+
getSize()Point

Returns the size of the given bounds

+
contains(<Bounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<Point> point)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<Bounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds +intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds +overlap if their intersection is an area.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
min + PointThe top left corner of the rectangle.
max + PointThe bottom right corner of the rectangle.
+ +
+ + +

Icon

Represents an icon to provide when creating a marker.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.icon({
+    iconUrl: 'my-icon.png',
+    iconSize: [38, 95],
+    iconAnchor: [22, 94],
+    popupAnchor: [-3, -76],
+    shadowUrl: 'my-icon-shadow.png',
+    shadowSize: [68, 95],
+    shadowAnchor: [22, 94]
+});
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

L.Icon.Default extends L.Icon and is the blue icon Leaflet uses for markers by default.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.icon(<Icon options> options)Creates an icon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + [0, 0]The coordinates of the point from which popups will "open", relative to the icon anchor.
tooltipAnchorPoint + [0, 0]The coordinates of the point from which tooltips will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+ + +
+ +
+

Icon.Default

+ +
+ + + +
A trivial subclass of Icon, represents the icon to use in Markers when +no icon is specified. Points to the blue marker image distributed with Leaflet +releases. +In order to customize the default icon, just change the properties of L.Icon.Default.prototype.options +(which is a set of Icon options). +If you want to completely replace the default icon, override the +L.Marker.prototype.options.icon with your own icon instead.
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
imagePathString + Icon.Default will try to auto-detect the location of the +blue icon images. If you are placing these images in a non-standard +way, set this option to point to the right path.
+ +
+ + +

DivIcon

Represents a lightweight icon for markers that uses a simple <div> +element instead of an image. Inherits from Icon but ignores the iconUrl and shadow options.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.divIcon({className: 'my-div-icon'});
+// you can set .my-div-icon styles in CSS
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.divIcon(<DivIcon options> options)Creates a DivIcon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
htmlString + ''Custom HTML code to put inside the div element, empty by default.
bgPosPoint + [0, 0]Optional relative position of the background, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + [0, 0]The coordinates of the point from which popups will "open", relative to the icon anchor.
tooltipAnchorPoint + [0, 0]The coordinates of the point from which tooltips will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+
+
+ +

Control.Zoom

A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its zoomControl option to false. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.zoom(<Control.Zoom options> options)Creates a zoom control
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomInTextString + '+'The text set on the 'zoom in' button.
zoomInTitleString + 'Zoom in'The title set on the 'zoom in' button.
zoomOutTextString + '&#x2212' +The text set on the 'zoom out' button.
zoomOutTitleString + 'Zoom out'The title set on the 'zoom out' button.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Attribution

The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its attributionControl option to false, and it fetches attribution texts from layers with the getAttribution method automatically. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.attribution(<Control.Attribution options> options)Creates an attribution control.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
prefixString + 'Leaflet'The HTML text shown before the attributions. Pass false to disable.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setPrefix(<String> prefix)this

Sets the text before the attributions.

+
addAttribution(<String> text)this

Adds an attribution text (e.g. 'Vector data &copy; Mapbox').

+
removeAttribution(<String> text)this

Removes an attribution text.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Layers

The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the detailed example). Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
var baseLayers = {
+    "Mapbox": mapbox,
+    "OpenStreetMap": osm
+};
+var overlays = {
+    "Marker": marker,
+    "Roads": roadsLayer
+};
+L.control.layers(baseLayers, overlays).addTo(map);
+
+

The baseLayers and overlays parameters are object literals with layer names as keys and Layer objects as values:

+
{
+    "<someName1>": layer1,
+    "<someName2>": layer2
+}
+
+

The layer names can contain HTML, which allows you to add additional styling to the items:

+
{"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>": myLayer}
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.layers(<Object> baselayers?, <Object> overlays?, <Control.Layers options> options?)Creates an attribution control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
collapsedBoolean + trueIf true, the control will be collapsed into an icon and expanded on mouse hover or touch.
autoZIndexBoolean + trueIf true, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
hideSingleBaseBoolean + falseIf true, the base layers in the control will be hidden when there is only one.
sortLayersBoolean + falseWhether to sort the layers. When false, layers will keep the order +in which they were added to the control.
sortFunctionFunction + *A compare function +that will be used for sorting the layers, when sortLayers is true. +The function receives both the L.Layer instances and their names, as in +sortFunction(layerA, layerB, nameA, nameB). +By default, it sorts layers alphabetically by their name.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addBaseLayer(<Layer> layer, <String> name)this

Adds a base layer (radio button entry) with the given name to the control.

+
addOverlay(<Layer> layer, <String> name)this

Adds an overlay (checkbox entry) with the given name to the control.

+
removeLayer(<Layer> layer)this

Remove the given layer from the control.

+
expand()this

Expand the control container if collapsed.

+
collapse()this

Collapse the control container if expanded.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Scale

A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
L.control.scale().addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.scale(<Control.Scale options> options?)Creates an scale control with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
maxWidthNumber + 100Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
metricBoolean + TrueWhether to show the metric scale line (m/km).
imperialBoolean + TrueWhether to show the imperial scale line (mi/ft).
updateWhenIdleBoolean + falseIf true, the control is updated on moveend, otherwise it's always up-to-date (updated on move).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Browser

A namespace with static properties for browser/feature detection used by Leaflet internally.

+ +
+

Usage example

+ +
+ + + + + +
if (L.Browser.ielt9) {
+  alert('Upgrade your browser, dude!');
+}
+
+ + + +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
ie + Booleantrue for all Internet Explorer versions (not Edge).
ielt9 + Booleantrue for Internet Explorer versions less than 9.
edge + Booleantrue for the Edge web browser.
webkit + Booleantrue for webkit-based browsers like Chrome and Safari (including mobile versions).
android + Booleantrue for any browser running on an Android platform.
android23 + Booleantrue for browsers running on Android 2 or Android 3.
androidStock + Booleantrue for the Android stock browser (i.e. not Chrome)
opera + Booleantrue for the Opera browser
chrome + Booleantrue for the Chrome browser.
gecko + Booleantrue for gecko-based browsers like Firefox.
safari + Booleantrue for the Safari browser.
opera12 + Booleantrue for the Opera browser supporting CSS transforms (version 12 or later).
win + Booleantrue when the browser is running in a Windows platform
ie3d + Booleantrue for all Internet Explorer versions supporting CSS transforms.
webkit3d + Booleantrue for webkit-based browsers supporting CSS transforms.
gecko3d + Booleantrue for gecko-based browsers supporting CSS transforms.
any3d + Booleantrue for all browsers supporting CSS transforms.
mobile + Booleantrue for all browsers running in a mobile device.
mobileWebkit + Booleantrue for all webkit-based browsers in a mobile device.
mobileWebkit3d + Booleantrue for all webkit-based browsers in a mobile device supporting CSS transforms.
msPointer + Booleantrue for browsers implementing the Microsoft touch events model (notably IE10).
pointer + Booleantrue for all browsers supporting pointer events.
touch + Booleantrue for all browsers supporting touch events. +This does not necessarily mean that the browser is running in a computer with +a touchscreen, it only means that the browser is capable of understanding +touch events.
mobileOpera + Booleantrue for the Opera browser in a mobile device.
mobileGecko + Booleantrue for gecko-based browsers running in a mobile device.
retina + Booleantrue for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%.
canvas + Booleantrue when the browser supports <canvas>.
svg + Booleantrue when the browser supports SVG.
vml + Booleantrue if the browser supports VML.
+ +
+ + +

Util

Various utility functions, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> dest, <Object> src?)ObjectMerges the properties of the src object (or multiple objects) into dest object and returns the latter. Has an L.extend shortcut.
create(<Object> proto, <Object> properties?)ObjectCompatibility polyfill for Object.create
bind(<Function> fn, )FunctionReturns a new function bound to the arguments passed, like Function.prototype.bind. +Has a L.bind() shortcut.
stamp(<Object> obj)NumberReturns the unique ID of an object, assigning it one if it doesn't have it.
throttle(<Function> fn, <Number> time, <Object> context)FunctionReturns a function which executes function fn with the given scope context +(so that the this keyword refers to context inside fn's code). The function +fn will be called no more than one time per given amount of time. The arguments +received by the bound function will be any arguments passed when binding the +function, followed by any arguments passed when invoking the bound function. +Has an L.throttle shortcut.
wrapNum(<Number> num, <Number[]> range, <Boolean> includeMax?)NumberReturns the number num modulo range in such a way so it lies within +range[0] and range[1]. The returned value will be always smaller than +range[1] unless includeMax is set to true.
falseFn()FunctionReturns a function which always returns false.
formatNum(<Number> num, <Number> digits?)NumberReturns the number num rounded to digits decimals, or to 6 decimals by default.
trim(<String> str)StringCompatibility polyfill for String.prototype.trim
splitWords(<String> str)String[]Trims and splits the string on whitespace and returns the array of parts.
setOptions(<Object> obj, <Object> options)ObjectMerges the given properties to the options of the obj object, returning the resulting options. See Class options. Has an L.setOptions shortcut.
getParamString(<Object> obj, <String> existingUrl?, <Boolean> uppercase?)StringConverts an object into a parameter URL string, e.g. {a: "foo", b: "bar"} +translates to '?a=foo&b=bar'. If existingUrl is set, the parameters will +be appended at the end. If uppercase is true, the parameter names will +be uppercased (e.g. '?A=foo&B=bar')
template(<String> str, <Object> data)StringSimple templating facility, accepts a template string of the form 'Hello {a}, {b}' +and a data object like {a: 'foo', b: 'bar'}, returns evaluated string +('Hello foo, bar'). You can also specify functions instead of strings for +data values — they will be evaluated passing data as an argument.
isArray(obj)BooleanCompatibility polyfill for Array.isArray
indexOf(<Array> array, <Object> el)NumberCompatibility polyfill for Array.prototype.indexOf
requestAnimFrame(<Function> fn, <Object> context?, <Boolean> immediate?)NumberSchedules fn to be executed when the browser repaints. fn is bound to +context if given. When immediate is set, fn is called immediately if +the browser doesn't have native support for +window.requestAnimationFrame, +otherwise it's delayed. Returns a request ID that can be used to cancel the request.
cancelAnimFrame(<Number> id)undefinedCancels a previous requestAnimFrame. See also window.cancelAnimationFrame.
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lastId + NumberLast unique ID used by stamp()
emptyImageUrl + StringData URI string containing a base64-encoded empty GIF image. +Used as a hack to free memory from unused images on WebKit-powered +mobile devices (by setting image src to this string).
+ +
+ + +

Transformation

Represents an affine transformation: a set of coefficients a, b, c, d +for transforming a point of a form (x, y) into (a*x + b, c*y + d) and doing +the reverse. Used by Leaflet in its projections code.

+ +
+

Usage example

+ +
+ + + + + +
var transformation = L.transformation(2, 5, -1, 10),
+    p = L.point(1, 2),
+    p2 = transformation.transform(p), //  L.point(7, 8)
+    p3 = transformation.untransform(p2); //  L.point(1, 2)
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.transformation(<Number> a, <Number> b, <Number> c, <Number> d)Instantiates a Transformation object with the given coefficients.
L.transformation(<Array> coefficients)Expects an coefficients array of the form +[a: Number, b: Number, c: Number, d: Number].
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
transform(<Point> point, <Number> scale?)Point

Returns a transformed point, optionally multiplied by the given scale. +Only accepts actual L.Point instances, not arrays.

+
untransform(<Point> point, <Number> scale?)Point

Returns the reverse transformation of the given point, optionally divided +by the given scale. Only accepts actual L.Point instances, not arrays.

+
+ +
+ + +

LineUtil

Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
simplify(<Point[]> points, <Number> tolerance)Point[]Dramatically reduces the number of points in a polyline while retaining +its shape and returns a new array of simplified points, using the +Douglas-Peucker algorithm. +Used for a huge performance boost when processing/displaying Leaflet polylines for +each zoom level and also reducing visual noise. tolerance affects the amount of +simplification (lesser value means higher quality but slower and with more points). +Also released as a separated micro-library Simplify.js.
pointToSegmentDistance(<Point> p, <Point> p1, <Point> p2)NumberReturns the distance between point p and segment p1 to p2.
closestPointOnSegment(<Point> p, <Point> p1, <Point> p2)NumberReturns the closest point from a point p on a segment p1 to p2.
clipSegment(<Point> a, <Point> b, <Bounds> bounds, <Boolean> useLastCode?, <Boolean> round?)Point[]|BooleanClips the segment a to b by rectangular bounds with the +Cohen-Sutherland algorithm +(modifying the segment points directly!). Used by Leaflet to only show polyline +points that are on the screen or near, increasing performance.
isFlat(<LatLng[]> latlngs)BooleanReturns true if latlngs is a flat array, false is nested.
+ +
+ + +

PolyUtil

Various utility functions for polygon geometries.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + +
FunctionReturnsDescription
clipPolygon(<Point[]> points, <Bounds> bounds, <Boolean> round?)Point[]Clips the polygon geometry defined by the given points by the given bounds (using the Sutherland-Hodgman algorithm). +Used by Leaflet to only show polygon points that are on the screen or near, increasing +performance. Note that polygon points needs different algorithm for clipping +than polyline, so there's a separate method for it.
+ +
+ + +

DomEvent

Utility functions to work with the DOM events, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
on(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisAdds a listener function (fn) to a particular DOM event type of the +element el. You can optionally specify the context of the listener +(object the this keyword will point to). You can also pass several +space-separated types (e.g. 'click dblclick').
on(<HTMLElement> el, <Object> eventMap, <Object> context?)thisAdds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
off(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisRemoves a previously added listener function. +Note that if you passed a custom context to on, you must pass the same +context to off in order to remove the listener.
off(<HTMLElement> el, <Object> eventMap, <Object> context?)thisRemoves a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
stopPropagation(<DOMEvent> ev)thisStop the given event from propagation to parent elements. Used inside the listener functions: +
L.DomEvent.on(div, 'click', function (ev) {
+    L.DomEvent.stopPropagation(ev);
+});
+
disableScrollPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'mousewheel' events (plus browser variants).
disableClickPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'click', 'doubleclick', +'mousedown' and 'touchstart' events (plus browser variants).
preventDefault(<DOMEvent> ev)thisPrevents the default action of the DOM Event ev from happening (such as +following a link in the href of the a element, or doing a POST request +with page reload when a <form> is submitted). +Use it inside listener functions.
stop(<DOMEvent> ev)thisDoes stopPropagation and preventDefault at the same time.
getMousePosition(<DOMEvent> ev, <HTMLElement> container?)PointGets normalized mouse position from a DOM event relative to the +container (border excluded) or to the whole page if not specified.
getWheelDelta(<DOMEvent> ev)NumberGets normalized wheel delta from a mousewheel DOM event, in vertical +pixels scrolled (negative if scrolling down). +Events from pointing devices without precise scrolling are mapped to +a best guess of 60 pixels.
addListener()thisAlias to L.DomEvent.on
removeListener()thisAlias to L.DomEvent.off
+ +
+ + +

DomUtil

Utility functions to work with the DOM +tree, used by Leaflet internally. +Most functions expecting or returning a HTMLElement also work for +SVG elements. The only difference is that classes refer to CSS classes +in HTML and SVG classes in SVG.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
get(<String|HTMLElement> id)HTMLElementReturns an element given its DOM id, or returns the element itself +if it was passed directly.
getStyle(<HTMLElement> el, <String> styleAttrib)StringReturns the value for a certain style attribute on an element, +including computed values or values set through CSS.
create(<String> tagName, <String> className?, <HTMLElement> container?)HTMLElementCreates an HTML element with tagName, sets its class to className, and optionally appends it to container element.
remove(<HTMLElement> el)Removes el from its parent element
empty(<HTMLElement> el)Removes all of el's children elements from el
toFront(<HTMLElement> el)Makes el the last child of its parent, so it renders in front of the other children.
toBack(<HTMLElement> el)Makes el the first child of its parent, so it renders behind the other children.
hasClass(<HTMLElement> el, <String> name)BooleanReturns true if the element's class attribute contains name.
addClass(<HTMLElement> el, <String> name)Adds name to the element's class attribute.
removeClass(<HTMLElement> el, <String> name)Removes name from the element's class attribute.
setClass(<HTMLElement> el, <String> name)Sets the element's class.
getClass(<HTMLElement> el)StringReturns the element's class.
setOpacity(<HTMLElement> el, <Number> opacity)Set the opacity of an element (including old IE support). +opacity must be a number from 0 to 1.
testProp(<String[]> props)String|falseGoes through the array of style names and returns the first name +that is a valid style name for an element. If no such name is found, +it returns false. Useful for vendor-prefixed styles like transform.
setTransform(<HTMLElement> el, <Point> offset, <Number> scale?)Resets the 3D CSS transform of el so it is translated by offset pixels +and optionally scaled by scale. Does not have an effect if the +browser doesn't support 3D CSS transforms.
setPosition(<HTMLElement> el, <Point> position)Sets the position of el to coordinates specified by position, +using CSS translate or top/left positioning depending on the browser +(used by Leaflet internally to position its layers).
getPosition(<HTMLElement> el)PointReturns the coordinates of an element previously positioned with setPosition.
disableTextSelection()Prevents the user from generating selectstart DOM events, usually generated +when the user drags the mouse through a page with text. Used internally +by Leaflet to override the behaviour of any click-and-drag interaction on +the map. Affects drag interactions on the whole document.
enableTextSelection()Cancels the effects of a previous L.DomUtil.disableTextSelection.
disableImageDrag()As L.DomUtil.disableTextSelection, but +for dragstart DOM events, usually generated when the user drags an image.
enableImageDrag()Cancels the effects of a previous L.DomUtil.disableImageDrag.
preventOutline(<HTMLElement> el)Makes the outline +of the element el invisible. Used internally by Leaflet to prevent +focusable elements from displaying an outline when the user performs a +drag interaction on them.
restoreOutline()Cancels the effects of a previous L.DomUtil.preventOutline.
getSizedParentNode(<HTMLElement> el)HTMLElementFinds the closest parent node which size (width and height) is not null.
getScale(<HTMLElement> el)ObjectComputes the CSS scale currently applied on the element. +Returns an object with x and y members as horizontal and vertical scales respectively, +and boundingClientRect as the result of getBoundingClientRect().
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
TRANSFORM + StringVendor-prefixed transform style name (e.g. 'webkitTransform' for WebKit).
TRANSITION + StringVendor-prefixed transition style name.
TRANSITION_END + StringVendor-prefixed transitionend event name.
+ +
+ + +

PosAnimation

Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.

+ +
+

Usage example

+ +
+ + + + + +
var fx = new L.PosAnimation();
+fx.run(el, [300, 500], 0.5);
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.PosAnimation()Creates a PosAnimation object.
+ + +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
start + EventFired when the animation starts
step + EventFired continuously during the animation.
end + EventFired when the animation ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
run(<HTMLElement> el, <Point> newPos, <Number> duration?, <Number> easeLinearity?)

Run an animation of a given element to a new position, optionally setting +duration in seconds (0.25 by default) and easing linearity factor (3rd +argument of the cubic bezier curve, +0.5 by default).

+
stop()

Stops the animation (if currently running).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Draggable

A class for making DOM elements draggable (including touch support). +Used internally for map and marker dragging. Only works for elements +that were positioned with L.DomUtil.setPosition.

+ +
+

Usage example

+ +
+ + + + + +
var draggable = new L.Draggable(elementToDrag);
+draggable.enable();
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.Draggable(<HTMLElement> el, <HTMLElement> dragHandle?, <Boolean> preventOutline?, <Draggable options> options?)Creates a Draggable object for moving el when you start dragging the dragHandle element (equals el itself by default).
+ + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
clickToleranceNumber + 3The max number of pixels a user can shift the mouse pointer during a click +for it to be considered a valid click (as opposed to a mouse drag).
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
down + EventFired when a drag is about to start.
dragstart + EventFired when a drag starts
predrag + EventFired continuously during dragging before each corresponding +update of the element's position.
drag + EventFired continuously during dragging.
dragend + DragEndEventFired when the drag ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()

Enables the dragging ability

+
disable()

Disables the dragging ability

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Class

L.Class powers the OOP facilities of Leaflet and is used to create almost all of the Leaflet classes documented here. +In addition to implementing a simple classical inheritance model, it introduces several special properties for convenient code organization — options, includes and statics.

+ +
+

Usage example

+ +
+ + + + + +
var MyClass = L.Class.extend({
+initialize: function (greeter) {
+    this.greeter = greeter;
+    // class constructor
+},
+greet: function (name) {
+    alert(this.greeter + ', ' + name)
+    }
+});
+// create instance of MyClass, passing "Hello" to the constructor
+var a = new MyClass("Hello");
+// call greet method, alerting "Hello, World"
+a.greet("World");
+
+ + + +
+ +

Class Factories

+ + + +

You may have noticed that Leaflet objects are created without using +the new keyword. This is achieved by complementing each class with a +lowercase factory method:

+
new L.Map('map'); // becomes:
+L.map('map');
+
+

The factories are implemented very easily, and you can do this for your own classes:

+
L.map = function (id, options) {
+    return new L.Map(id, options);
+};
+
+ + + +
+ +

Inheritance

+ + + +

You use L.Class.extend to define new classes, but you can use the same method on any class to inherit from it:

+
var MyChildClass = MyClass.extend({
+    // ... new properties and methods
+});
+
+

This will create a class that inherits all methods and properties of the parent class (through a proper prototype chain), adding or overriding the ones you pass to extend. It will also properly react to instanceof:

+
var a = new MyChildClass();
+a instanceof MyChildClass; // true
+a instanceof MyClass; // true
+
+

You can call parent methods (including constructor) from corresponding child ones (as you do with super calls in other languages) by accessing parent class prototype and using JavaScript's call or apply:

+
var MyChildClass = MyClass.extend({
+    initialize: function () {
+        MyClass.prototype.initialize.call(this, "Yo");
+    },
+    greet: function (name) {
+        MyClass.prototype.greet.call(this, 'bro ' + name + '!');
+    }
+});
+var a = new MyChildClass();
+a.greet('Jason'); // alerts "Yo, bro Jason!"
+
+ + +
+ +

Options

+ + + +

options is a special property that unlike other objects that you pass +to extend will be merged with the parent one instead of overriding it +completely, which makes managing configuration of objects and default +values convenient:

+
var MyClass = L.Class.extend({
+    options: {
+        myOption1: 'foo',
+        myOption2: 'bar'
+    }
+});
+var MyChildClass = MyClass.extend({
+    options: {
+        myOption1: 'baz',
+        myOption3: 5
+    }
+});
+var a = new MyChildClass();
+a.options.myOption1; // 'baz'
+a.options.myOption2; // 'bar'
+a.options.myOption3; // 5
+
+

There's also L.Util.setOptions, a method for +conveniently merging options passed to constructor with the defaults +defines in the class:

+
var MyClass = L.Class.extend({
+    options: {
+        foo: 'bar',
+        bla: 5
+    },
+    initialize: function (options) {
+        L.Util.setOptions(this, options);
+        ...
+    }
+});
+var a = new MyClass({bla: 10});
+a.options; // {foo: 'bar', bla: 10}
+
+

Note that the options object allows any keys, not just +the options defined by the class and its base classes. +This means you can use the options object to store +application specific information, as long as you avoid +keys that are already used by the class in question.

+ + + +
+ +

Includes

+ + + +

includes is a special class property that merges all specified objects into the class (such objects are called mixins).

+
 var MyMixin = {
+    foo: function () { ... },
+    bar: 5
+};
+var MyClass = L.Class.extend({
+    includes: MyMixin
+});
+var a = new MyClass();
+a.foo();
+
+

You can also do such includes in runtime with the include method:

+
MyClass.include(MyMixin);
+
+

statics is just a convenience property that injects specified object properties as the static properties of the class, useful for defining constants:

+
var MyClass = L.Class.extend({
+    statics: {
+        FOO: 'bar',
+        BLA: 5
+    }
+});
+MyClass.FOO; // 'bar'
+
+ + + +
+ +

Constructor hooks

+ + + +

If you're a plugin developer, you often need to add additional initialization code to existing classes (e.g. editing hooks for L.Polyline). Leaflet comes with a way to do it easily using the addInitHook method:

+
MyClass.addInitHook(function () {
+    // ... do something in constructor additionally
+    // e.g. add event listeners, set custom properties etc.
+});
+
+

You can also use the following shortcut when you just need to make one additional method call:

+
MyClass.addInitHook('methodName', arg1, arg2, …);
+
+ + + +
+ + +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> props)FunctionExtends the current class given the properties to be included. +Returns a Javascript function that is a class constructor (to be called with new).
include(<Object> properties)thisIncludes a mixin into the current class.
mergeOptions(<Object> options)thisMerges options into the defaults of the class.
addInitHook(<Function> fn)thisAdds a constructor hook to the class.
+ +
+ + +

Evented

A set of methods shared between event-powered classes (like Map and Marker). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire 'click' event).

+ +
+

Usage example

+ +
+ + + + + +
map.on('click', function(e) {
+    alert(e.latlng);
+} );
+
+

Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:

+
function onClick(e) { ... }
+map.on('click', onClick);
+map.off('click', onClick);
+
+ + + +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+ + +

Layer

A set of methods from the Layer base class that all Leaflet layers use. +Inherits all methods, options and events from L.Evented.

+ +
+

Usage example

+ +
+ + + + + +
var layer = L.Marker(latlng).addTo(map);
+layer.addTo(map);
+layer.remove();
+
+ + + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Layer will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+ +

Extension methods

+ +
Every layer should extend from L.Layer and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)this

Should contain code that creates DOM elements for the layer, adds them to map panes where they should belong and puts listeners on relevant map events. Called on map.addLayer(layer).

+
onRemove(<Map> map)this

Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in onAdd. Called on map.removeLayer(layer).

+
getEvents()Object

This optional method should return an object like { viewreset: this._reset } for addEventListener. The event handlers in this object will be automatically added and removed from the map with your layer.

+
getAttribution()String

This optional method should return a string containing HTML to be shown on the Attribution control whenever the layer is visible.

+
beforeAdd(<Map> map)this

Optional method. Called on map.addLayer(layer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.

+
+ +
+ +

Popup methods

+ +
All layers share a set of methods convenient for binding popups to it. +
var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
+layer.openPopup();
+layer.closePopup();
+
+

Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+ +

Tooltip methods

+ +
All layers share a set of methods convenient for binding tooltips to it. +
var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
+layer.openTooltip();
+layer.closeTooltip();
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Interactive layer

Some Layers can be made interactive - when the user interacts +with such a layer, mouse events like click and mouseover can be handled. +Use the event handling methods to handle these events.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ +

Mouse events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Control

L.Control is a base class for implementing map controls. Handles positioning. +All other controls extend from this class.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Control will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+ +

Extension methods

+ +
Every control should extend from L.Control and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)HTMLElement

Should return the container DOM element for the control and add listeners on relevant map events. Called on control.addTo(map).

+
onRemove(<Map> map)

Optional method. Should contain all clean up code that removes the listeners previously added in onAdd. Called on control.remove().

+
+ +
+ + +

Handler

Abstract class for map interaction handlers

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()this

Enables the handler

+
disable()this

Disables the handler

+
enabled()Boolean

Returns true if the handler is enabled

+
+ +
+ +

Extension methods

+ +
Classes inheriting from Handler must implement the two following methods:
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHooks()

Called when the handler is enabled, should add event hooks.

+
removeHooks()

Called when the handler is disabled, should remove the event hooks added previously.

+
+ +
+ + +
+

Functions

+ +
+ +

There is static function which can be called without instantiating L.Handler:

+ + + + + + + + + + + + + + +
FunctionReturnsDescription
addTo(<Map> map, <String> name)thisAdds a new Handler to the given map with the given name.
+ +
+ + +

Projection

An object with methods for projecting geographical coordinates of the world onto +a flat surface (and back). See Map projection.

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
project(<LatLng> latlng)Point

Projects geographical coordinates into a 2D point. +Only accepts actual L.LatLng instances, not arrays.

+
unproject(<Point> point)LatLng

The inverse of project. Projects a 2D point into a geographical location. +Only accepts actual L.Point instances, not arrays. +Note that the projection instances do not inherit from Leafet's Class object, +and can't be instantiated. Also, new classes can't inherit from them, +and methods can't be added to them with the include function.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
bounds + BoundsThe bounds (specified in CRS units) where the projection is valid
+ +
+ + +
+

Defined projections

+ +
+ + + +
Leaflet comes with a set of already defined Projections out of the box:
+ + + + + + + + + + + + + + + + + + + +
ProjectionDescription
L.Projection.LonLatEquirectangular, or Plate Carree projection — the most simple projection, +mostly used by GIS enthusiasts. Directly maps x as longitude, and y as +latitude. Also suitable for flat worlds, e.g. game maps. Used by the +EPSG:4326 and Simple CRS.
L.Projection.MercatorElliptical Mercator projection — more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS.
L.Projection.SphericalMercatorSpherical Mercator projection — the most common projection for online maps, +used by almost all free and commercial tile providers. Assumes that Earth is +a sphere. Used by the EPSG:3857 CRS.
+ +
+ + +

CRS

+
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
latLngToPoint(<LatLng> latlng, <Number> zoom)Point

Projects geographical coordinates into pixel coordinates for a given zoom.

+
pointToLatLng(<Point> point, <Number> zoom)LatLng

The inverse of latLngToPoint. Projects pixel coordinates on a given +zoom into geographical coordinates.

+
project(<LatLng> latlng)Point

Projects geographical coordinates into coordinates in units accepted for +this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).

+
unproject(<Point> point)LatLng

Given a projected coordinate returns the corresponding LatLng. +The inverse of project.

+
scale(<Number> zoom)Number

Returns the scale used when transforming projected coordinates into +pixel coordinates for a particular zoom. For example, it returns +256 * 2^zoom for Mercator-based CRS.

+
zoom(<Number> scale)Number

Inverse of scale(), returns the zoom level corresponding to a scale +factor of scale.

+
getProjectedBounds(<Number> zoom)Bounds

Returns the projection's bounds scaled and transformed for the provided zoom.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +CRS's wrapLat and wrapLng properties, if they are outside the CRS's bounds.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring +that its center is within the CRS's bounds. +Only accepts actual L.LatLngBounds instances, not arrays.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
code + StringStandard code name of the CRS passed into WMS services (e.g. 'EPSG:3857')
wrapLng + Number[]An array of two numbers defining whether the longitude (horizontal) coordinate +axis wraps around a given range and how. Defaults to [-180, 180] in most +geographical CRSs. If undefined, the longitude axis does not wrap around.
wrapLat + Number[]Like wrapLng, but for the latitude (vertical) axis.
infinite + BooleanIf true, the coordinate space will be unbounded (infinite in both axes)
+ +
+ + +
+

Defined CRSs

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CRSDescription
L.CRS.EarthServes as the base for CRS that are global such that they cover the earth. +Can only be used as the base for other CRS and cannot be used directly, +since it does not have a code, projection or transformation. distance() returns +meters.
L.CRS.EPSG3395Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.
L.CRS.EPSG3857The most common CRS for online maps, used by almost all free and commercial +tile providers. Uses Spherical Mercator projection. Set in by default in +Map's crs option.
L.CRS.EPSG4326A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. +Leaflet 1.0.x complies with the TMS coordinate scheme for EPSG:4326, +which is a breaking change from 0.7.x behaviour. If you are using a TileLayer +with this CRS, ensure that there are two 256x256 pixel tiles covering the +whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), +or (-180,-90) for TileLayers with the tms option set.
L.CRS.BaseObject that defines coordinate reference systems for projecting +geographical points into pixel (screen) coordinates and back (and to +coordinates in other units for WMS services). See +spatial reference system. +Leaflet defines the most usual CRSs by default. If you want to use a +CRS not defined by default, take a look at the +Proj4Leaflet plugin. +Note that the CRS instances do not inherit from Leafet's Class object, +and can't be instantiated. Also, new classes can't inherit from them, +and methods can't be added to them with the include function.
L.CRS.SimpleA simple CRS that maps longitude and latitude into x and y directly. +May be used for maps of flat surfaces (e.g. game maps). Note that the y +axis should still be inverted (going from bottom to top). distance() returns +simple euclidean distance.
+ +
+ + +

Renderer

Base class for vector renderer implementations (SVG, Canvas). Handles the +DOM container of the renderer, its bounds, and its zoom animation. +A Renderer works as an implicit layer group for all Paths - the renderer +itself can be added or removed to the map. All paths use a renderer, which can +be implicit (the map will decide the type of renderer and use it automatically) +or explicit (using the renderer option of the path). +Do not use this class directly, use SVG and Canvas instead.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Event objects

Whenever a class inheriting from Evented fires an event, a listener function +will be called with an event argument, which is a plain object containing +information about the event. For example:

+
map.on('click', function(ev) {
+    alert(ev.latlng); // ev is an event object (MouseEvent in this case)
+});
+
+

The information available depends on the event type:

+ + + +
+

Event

+ +
+ + + +
The base event object. All other event objects contain these properties too.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+ + +
+ +
+

KeyboardEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
originalEvent + DOMEventThe original DOM KeyboardEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

MouseEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngThe geographical point where the mouse event occured.
layerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map layer.
containerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map сontainer.
originalEvent + DOMEventThe original DOM MouseEvent or DOM TouchEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

LocationEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngDetected geographical location of the user.
bounds + LatLngBoundsGeographical bounds of the area user is located in (with respect to the accuracy of location).
accuracy + NumberAccuracy of location in meters.
altitude + NumberHeight of the position above the WGS84 ellipsoid in meters.
altitudeAccuracy + NumberAccuracy of altitude in meters.
heading + NumberThe direction of travel in degrees counting clockwise from true North.
speed + NumberCurrent velocity in meters per second.
timestamp + NumberThe time when the position was acquired.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
message + StringError message.
code + NumberError code (if applicable).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

LayerEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

LayersControlEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
name + StringThe name of the layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

TileEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

TileErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
error + *Error passed to the tile's done() callback.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ResizeEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
oldSize + PointThe old size before resize event.
newSize + PointThe new size after the resize event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

GeoJSONEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer for the GeoJSON feature that is being added to the map.
properties + ObjectGeoJSON properties of the feature.
geometryType + StringGeoJSON geometry type of the feature.
id + StringGeoJSON ID of the feature (if present).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

PopupEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
popup + PopupThe popup that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

TooltipEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
tooltip + TooltipThe tooltip that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

DragEndEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
distance + NumberThe distance in pixels the draggable element was moved by.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ZoomAnimEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
center + LatLngThe current center of the map
zoom + NumberThe current zoom level of the map
noUpdate + BooleanWhether layers should update their contents due to this event
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +

DivOverlay

Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
offsetPoint + Point(0, 7)The offset of the popup position. Useful to control the anchor +of the popup when opening it on some overlays.
classNameString + ''A custom CSS class name to assign to the popup.
paneString + 'popupPane'Map pane where the popup will be added.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Global Switches

Global switches are created for rare cases and generally make +Leaflet to not detect a particular browser feature even if it's +there. You need to set the switch as a global variable to true +before including Leaflet on the page, like this:

+
<script>L_NO_TOUCH = true;</script>
+<script src="leaflet.js"></script>
+
+ + + + + + + + + + + + + + + + + +
SwitchDescription
L_NO_TOUCHForces Leaflet to not use touch events even if it detects them.
L_DISABLE_3DForces Leaflet to not use hardware-accelerated CSS 3D transforms for positioning (which may cause glitches in some rare environments) even if they're supported.
+ +

noConflict

This method restores the L global variable to the original value +it had before Leaflet inclusion, and returns the real Leaflet +namespace so you can put it elsewhere, like this:

+
<script src='libs/l.js'>
+<!-- L points to some other library -->
+<script src='leaflet.js'>
+<!-- you include Leaflet, it replaces the L variable to Leaflet namespace -->
+<script>
+var Leaflet = L.noConflict();
+// now L points to that other library again, and you can use Leaflet.Map etc.
+</script>
+
+ +

version

A constant that represents the Leaflet version in use.

+
L.version; // contains "1.0.0" (or whatever version is currently in use)
+
+ + + + + + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.3.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.3.html new file mode 100644 index 000000000..7b7c70d47 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.3.html @@ -0,0 +1,4 @@ +--- +layout: redirected +redirect_to: reference-1.3.2.html +--- \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.4.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.4.html new file mode 100644 index 000000000..8bcd6f695 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-1.3.4.html @@ -0,0 +1,24151 @@ +--- +layout: v2 +title: Documentation +bodyclass: api-page +--- + +

Leaflet API reference

+ +

This reference reflects Leaflet 1.3.4. Check this list if you are using a different version of Leaflet.

+ +
+ +
+

UI Layers

+ +

Raster Layers

+ +

Vector Layers

+ +
+
+

Other Layers

+ +

Basic Types

+ +

Controls

+ +
+
+ + + + + + +

Utility

+ +

DOM Utility

+ +
+
+

Base Classes

+ + +

Misc

+ +
+
+ +

Map

The central class of the API — it is used to create a map on a page and manipulate it.

+ +
+

Usage example

+ +
+ + + + + +
// initialize the map on the "map" div with a given center and zoom
+var map = L.map('map', {
+    center: [51.505, -0.09],
+    zoom: 13
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.map(<String> id, <Map options> options?)Instantiates a map object given the DOM ID of a <div> element +and optionally an object literal with Map options.
L.map(<HTMLElement> el, <Map options> options?)Instantiates a map object given an instance of a <div> HTML element +and optionally an object literal with Map options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
preferCanvasBoolean + falseWhether Paths should be rendered on a Canvas renderer. +By default, all Paths are rendered in a SVG renderer.
+ +
+ +

Control options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionControlBoolean + trueWhether a attribution control is added to the map by default.
zoomControlBoolean + trueWhether a zoom control is added to the map by default.
+ +
+ +

Interaction Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
closePopupOnClickBoolean + trueSet it to false if you don't want popups to close when user clicks the map.
boxZoomBoolean + trueWhether the map can be zoomed to a rectangular area specified by +dragging the mouse while pressing the shift key.
doubleClickZoomBoolean|String + trueWhether the map can be zoomed in by double clicking on it and +zoomed out by double clicking while holding shift. If passed +'center', double-click zoom will zoom to the center of the + view regardless of where the mouse was.
draggingBoolean + trueWhether the map be draggable with mouse/touch or not.
zoomSnapNumber + 1Forces the map's zoom level to always be a multiple of this, particularly +right after a fitBounds() or a pinch-zoom. +By default, the zoom level snaps to the nearest integer; lower values +(e.g. 0.5 or 0.1) allow for greater granularity. A value of 0 +means the zoom level will not be snapped after fitBounds or a pinch-zoom.
zoomDeltaNumber + 1Controls how much the map's zoom level will change after a +zoomIn(), zoomOut(), pressing + +or - on the keyboard, or using the zoom controls. +Values smaller than 1 (e.g. 0.5) allow for greater granularity.
trackResizeBoolean + trueWhether the map automatically handles browser window resize to update itself.
+ +
+ +

Panning Inertia Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
inertiaBoolean + *If enabled, panning of the map will have an inertia effect where +the map builds momentum while dragging and continues moving in +the same direction for some time. Feels especially nice on touch +devices. Enabled by default unless running on old Android devices.
inertiaDecelerationNumber + 3000The rate with which the inertial movement slows down, in pixels/second².
inertiaMaxSpeedNumber + InfinityMax speed of the inertial movement, in pixels/second.
easeLinearityNumber + 0.2
worldCopyJumpBoolean + falseWith this option enabled, the map tracks when you pan to another "copy" +of the world and seamlessly jumps to the original one so that all overlays +like markers and vector layers are still visible.
maxBoundsViscosityNumber + 0.0If maxBounds is set, this option will control how solid the bounds +are when dragging the map around. The default value of 0.0 allows the +user to drag outside the bounds at normal speed, higher values will +slow down map dragging outside bounds, and 1.0 makes the bounds fully +solid, preventing the user from dragging outside the bounds.
+ +
+ +

Keyboard Navigation Options

+ + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
keyboardBoolean + trueMakes the map focusable and allows users to navigate the map with keyboard +arrows and +/- keys.
keyboardPanDeltaNumber + 80Amount of pixels to pan when pressing an arrow key.
+ +
+ +

Mousewheel options

+ + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
scrollWheelZoomBoolean|String + trueWhether the map can be zoomed by using the mouse wheel. If passed 'center', +it will zoom to the center of the view regardless of where the mouse was.
wheelDebounceTimeNumber + 40Limits the rate at which a wheel can fire (in milliseconds). By default +user can't zoom via wheel more often than once per 40 ms.
wheelPxPerZoomLevelNumber + 60How many scroll pixels (as reported by L.DomEvent.getWheelDelta) +mean a change of one full zoom level. Smaller values will make wheel-zooming +faster (and vice versa).
+ +
+ +

Touch interaction options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tapBoolean + trueEnables mobile hacks for supporting instant taps (fixing 200ms click +delay on iOS/Android) and touch holds (fired as contextmenu events).
tapToleranceNumber + 15The max number of pixels a user can shift his finger during touch +for it to be considered a valid tap.
touchZoomBoolean|String + *Whether the map can be zoomed by touch-dragging with two fingers. If +passed 'center', it will zoom to the center of the view regardless of +where the touch events (fingers) were. Enabled for touch-capable web +browsers except for old Androids.
bounceAtZoomLimitsBoolean + trueSet it to false if you don't want the map to zoom beyond min/max zoom +and then bounce back when pinch-zooming.
+ +
+ +

Map State Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
crsCRS + L.CRS.EPSG3857The Coordinate Reference System to use. Don't change this if you're not +sure what it means.
centerLatLng + undefinedInitial geographic center of the map
zoomNumber + undefinedInitial map zoom level
minZoomNumber + *Minimum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the lowest of their minZoom options will be used instead.
maxZoomNumber + *Maximum zoom level of the map. +If not specified and at least one GridLayer or TileLayer is in the map, +the highest of their maxZoom options will be used instead.
layersLayer[] + []Array of layers that will be added to the map initially
maxBoundsLatLngBounds + nullWhen this option is set, the map restricts the view to the given +geographical bounds, bouncing the user back if the user tries to pan +outside the view. To set the restriction dynamically, use +setMaxBounds method.
rendererRenderer + *The default method for drawing vector layers on the map. L.SVG +or L.Canvas by default depending on browser support.
+ +
+ +

Animation Options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomAnimationBoolean + trueWhether the map zoom animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
zoomAnimationThresholdNumber + 4Won't animate zoom if the zoom difference exceeds this value.
fadeAnimationBoolean + trueWhether the tile fade animation is enabled. By default it's enabled +in all browsers that support CSS3 Transitions except Android.
markerZoomAnimationBoolean + trueWhether markers animate their zoom with the zoom animation, if disabled +they will disappear for the length of the animation. By default it's +enabled in all browsers that support CSS3 Transitions except Android.
transform3DLimitNumber + 2^23Defines the maximum size of a CSS translation transform. The default +value should not be changed unless a web browser positions layers in +the wrong place after doing a large panBy.
+ +
+ + +
+

Events

+ +
+ +

Layer events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
baselayerchange + LayersControlEventFired when the base layer is changed through the layer control.
overlayadd + LayersControlEventFired when an overlay is selected through the layer control.
overlayremove + LayersControlEventFired when an overlay is deselected through the layer control.
layeradd + LayerEventFired when a new layer is added to the map.
layerremove + LayerEventFired when some layer is removed from the map
+ +
+ +

Map state change events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
zoomlevelschange + EventFired when the number of zoomlevels on the map is changed due +to adding or removing a layer.
resize + ResizeEventFired when the map is resized.
unload + EventFired when the map is destroyed with remove method.
viewreset + EventFired when the map needs to redraw its content (this usually happens +on map zoom or load). Very useful for creating custom overlays.
load + EventFired when the map is initialized (when its center and zoom are set +for the first time).
zoomstart + EventFired when the map zoom is about to change (e.g. before zoom animation).
movestart + EventFired when the view of the map starts changing (e.g. user starts dragging the map).
zoom + EventFired repeatedly during any change in zoom level, including zoom +and fly animations.
move + EventFired repeatedly during any movement of the map, including pan and +fly animations.
zoomend + EventFired when the map has changed, after any animations.
moveend + EventFired when the center of the map stops changing (e.g. user stopped +dragging the map).
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup is opened in the map
popupclose + PopupEventFired when a popup in the map is closed
autopanstart + EventFired when the map starts autopanning when opening a popup.
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip is opened in the map.
tooltipclose + TooltipEventFired when a tooltip in the map is closed.
+ +
+ +

Location events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
locationerror + ErrorEventFired when geolocation (using the locate method) failed.
locationfound + LocationEventFired when geolocation (using the locate method) +went successfully.
+ +
+ +

Interaction events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the map.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the map.
mousedown + MouseEventFired when the user pushes the mouse button on the map.
mouseup + MouseEventFired when the user releases the mouse button on the map.
mouseover + MouseEventFired when the mouse enters the map.
mouseout + MouseEventFired when the mouse leaves the map.
mousemove + MouseEventFired while the mouse moves over the map.
contextmenu + MouseEventFired when the user pushes the right mouse button on the map, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
keypress + KeyboardEventFired when the user presses a key from the keyboard while the map is focused.
preclick + MouseEventFired before mouse click on the map (sometimes useful when you +want something to happen on click before any existing click +handlers start running).
+ +
+ +

Other Methods

+ + + + + + + + + + + + + +
EventDataDescription
zoomanim + ZoomAnimEventFired on every frame of a zoom animation
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getRenderer(<Path> layer)Renderer

Returns the instance of Renderer that should be used to render the given +Path. It will ensure that the renderer options of the map and paths +are respected, and that the renderers do exist on the map.

+
+ +
+ +

Methods for Layers and Controls

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addControl(<Control> control)this

Adds the given control to the map

+
removeControl(<Control> control)this

Removes the given control from the map

+
addLayer(<Layer> layer)this

Adds the given layer to the map

+
removeLayer(<Layer> layer)this

Removes the given layer from the map.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the map

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the map, optionally specifying context of the iterator function.

+
map.eachLayer(function(layer){
+    layer.bindPopup('Hello');
+});
+
openPopup(<Popup> popup)this

Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).

+
openPopup(<String|HTMLElement> content, <LatLng> latlng, <Popup options> options?)this

Creates a popup with the specified content and options and opens it in the given point on a map.

+
closePopup(<Popup> popup?)this

Closes the popup previously opened with openPopup (or the given one).

+
openTooltip(<Tooltip> tooltip)this

Opens the specified tooltip.

+
openTooltip(<String|HTMLElement> content, <LatLng> latlng, <Tooltip options> options?)this

Creates a tooltip with the specified content and options and open it.

+
closeTooltip(<Tooltip> tooltip?)this

Closes the tooltip given as parameter.

+
+ +
+ +

Methods for modifying map state

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setView(<LatLng> center, <Number> zoom, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) with the given +animation options.

+
setZoom(<Number> zoom, <Zoom/pan options> options?)this

Sets the zoom of the map.

+
zoomIn(<Number> delta?, <Zoom options> options?)this

Increases the zoom of the map by delta (zoomDelta by default).

+
zoomOut(<Number> delta?, <Zoom options> options?)this

Decreases the zoom of the map by delta (zoomDelta by default).

+
setZoomAround(<LatLng> latlng, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified geographical point on the map +stationary (e.g. used internally for scroll zoom and double-click zoom).

+
setZoomAround(<Point> offset, <Number> zoom, <Zoom options> options)this

Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.

+
fitBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets a map view that contains the given geographical bounds with the +maximum zoom level possible.

+
fitWorld(<fitBounds options> options?)this

Sets a map view that mostly contains the whole world with the maximum +zoom level possible.

+
panTo(<LatLng> latlng, <Pan options> options?)this

Pans the map to a given center.

+
panBy(<Point> offset, <Pan options> options?)this

Pans the map by a given number of pixels (animated).

+
flyTo(<LatLng> latlng, <Number> zoom?, <Zoom/pan options> options?)this

Sets the view of the map (geographical center and zoom) performing a smooth +pan-zoom animation.

+
flyToBounds(<LatLngBounds> bounds, <fitBounds options> options?)this

Sets the view of the map with a smooth animation like flyTo, +but takes a bounds parameter like fitBounds.

+
setMaxBounds(<Bounds> bounds)this

Restricts the map view to the given bounds (see the maxBounds option).

+
setMinZoom(<Number> zoom)this

Sets the lower limit for the available zoom levels (see the minZoom option).

+
setMaxZoom(<Number> zoom)this

Sets the upper limit for the available zoom levels (see the maxZoom option).

+
panInsideBounds(<LatLngBounds> bounds, <Pan options> options?)this

Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.

+
invalidateSize(<Zoom/pan options> options)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default. If options.pan is false, panning will not occur. +If options.debounceMoveend is true, it will delay moveend event so +that it doesn't happen often even if the method is called many +times in a row.

+
invalidateSize(<Boolean> animate)this

Checks if the map container size changed and updates the map if so — +call it after you've changed the map size dynamically, also animating +pan by default.

+
stop()this

Stops the currently running panTo or flyTo animation, if any.

+
+ +
+ +

Geolocation methods

+ + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
locate(<Locate options> options?)this

Tries to locate the user using the Geolocation API, firing a locationfound +event with location data on success or a locationerror event on failure, +and optionally sets the map view to the user's location with respect to +detection accuracy (or to the world view if geolocation failed). +Note that, if your page doesn't use HTTPS, this method will fail in +modern browsers (Chrome 50 and newer) +See Locate options for more details.

+
stopLocate()this

Stops watching location previously initiated by map.locate({watch: true}) +and aborts resetting the map view if map.locate was called with +{setView: true}.

+
+ +
+ +

Other Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHandler(<String> name, <Function> HandlerClass)this

Adds a new Handler to the map, given its name and constructor function.

+
remove()this

Destroys the map and clears all related event listeners.

+
createPane(<String> name, <HTMLElement> container?)HTMLElement

Creates a new map pane with the given name if it doesn't exist already, +then returns it. The pane is created as a child of container, or +as a child of the main map pane if not set.

+
getPane(<String|HTMLElement> pane)HTMLElement

Returns a map pane, given its name or its HTML element (its identity).

+
getPanes()Object

Returns a plain object containing the names of all panes as keys and +the panes as values.

+
getContainer()HTMLElement

Returns the HTML element that contains the map.

+
whenReady(<Function> fn, <Object> context?)this

Runs the given function fn when the map gets initialized with +a view (center and zoom) and at least one layer, or immediately +if it's already initialized, optionally passing a function context.

+
+ +
+ +

Methods for Getting Map State

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getCenter()LatLng

Returns the geographical center of the map view

+
getZoom()Number

Returns the current zoom level of the map view

+
getBounds()LatLngBounds

Returns the geographical bounds visible in the current map view

+
getMinZoom()Number

Returns the minimum zoom level of the map (if set in the minZoom option of the map or of any layers), or 0 by default.

+
getMaxZoom()Number

Returns the maximum zoom level of the map (if set in the maxZoom option of the map or of any layers).

+
getBoundsZoom(<LatLngBounds> bounds, <Boolean> inside?, <Point> padding?)Number

Returns the maximum zoom level on which the given bounds fit to the map +view in its entirety. If inside (optional) is set to true, the method +instead returns the minimum zoom level on which the map view fits into +the given bounds in its entirety.

+
getSize()Point

Returns the current size of the map container (in pixels).

+
getPixelBounds()Bounds

Returns the bounds of the current map view in projected pixel +coordinates (sometimes useful in layer and overlay implementations).

+
getPixelOrigin()Point

Returns the projected pixel coordinates of the top left point of +the map layer (useful in custom layer and overlay implementations).

+
getPixelWorldBounds(<Number> zoom?)Bounds

Returns the world's bounds in pixel coordinates for zoom level zoom. +If zoom is omitted, the map's current zoom level is used.

+
+ +
+ +

Conversion Methods

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getZoomScale(<Number> toZoom, <Number> fromZoom)Number

Returns the scale factor to be applied to a map transition from zoom level +fromZoom to toZoom. Used internally to help with zoom animations.

+
getScaleZoom(<Number> scale, <Number> fromZoom)Number

Returns the zoom level that the map would end up at, if it is at fromZoom +level and everything is scaled by a factor of scale. Inverse of +getZoomScale.

+
project(<LatLng> latlng, <Number> zoom)Point

Projects a geographical coordinate LatLng according to the projection +of the map's CRS, then scales it according to zoom and the CRS's +Transformation. The result is pixel coordinate relative to +the CRS origin.

+
unproject(<Point> point, <Number> zoom)LatLng

Inverse of project.

+
layerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the origin pixel, +returns the corresponding geographical coordinate (for the current zoom level).

+
latLngToLayerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the origin pixel.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +map's CRS's wrapLat and wrapLng properties, if they are outside the +CRS's bounds. +By default this means longitude is wrapped around the dateline so its +value is between -180 and +180 degrees.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring that +its center is within the CRS's bounds. +By default this means the center longitude is wrapped around the dateline so its +value is between -180 and +180 degrees, and the majority of the bounds +overlaps the CRS's bounds.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates according to +the map's CRS. By default this measures distance in meters.

+
containerPointToLayerPoint(<Point> point)Point

Given a pixel coordinate relative to the map container, returns the corresponding +pixel coordinate relative to the origin pixel.

+
layerPointToContainerPoint(<Point> point)Point

Given a pixel coordinate relative to the origin pixel, +returns the corresponding pixel coordinate relative to the map container.

+
containerPointToLatLng(<Point> point)LatLng

Given a pixel coordinate relative to the map container, returns +the corresponding geographical coordinate (for the current zoom level).

+
latLngToContainerPoint(<LatLng> latlng)Point

Given a geographical coordinate, returns the corresponding pixel coordinate +relative to the map container.

+
mouseEventToContainerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to the +map container where the event took place.

+
mouseEventToLayerPoint(<MouseEvent> ev)Point

Given a MouseEvent object, returns the pixel coordinate relative to +the origin pixel where the event took place.

+
mouseEventToLatLng(<MouseEvent> ev)LatLng

Given a MouseEvent object, returns geographical coordinate where the +event took place.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Controls

+ + + + + + + + + + + + + +
PropertyTypeDescription
zoomControl + Control.ZoomThe default zoom control (only available if the +zoomControl option was true when creating the map).
+ +
+ +

Handlers

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
boxZoom + HandlerBox (shift-drag with mouse) zoom handler.
doubleClickZoom + HandlerDouble click zoom handler.
dragging + HandlerMap dragging handler (by both mouse and touch).
keyboard + HandlerKeyboard navigation handler.
scrollWheelZoom + HandlerScroll wheel zoom handler.
tap + HandlerMobile touch hacks (quick tap and touch hold) handler.
touchZoom + HandlerTouch zoom handler.
+ +
+ + +
+

Map panes

+ +
+ + + +
Panes are DOM elements used to control the ordering of layers on the map. You +can access panes with map.getPane or +map.getPanes methods. New panes can be created with the +map.createPane method. +Every map has the following default panes that differ only in zIndex.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PaneTypeZ-indexDescription
mapPaneHTMLElement + 'auto'Pane that contains all other map panes
tilePaneHTMLElement + 200Pane for GridLayers and TileLayers
overlayPaneHTMLElement + 400Pane for vectors (Paths, like Polylines and Polygons), ImageOverlays and VideoOverlays
shadowPaneHTMLElement + 500Pane for overlay shadows (e.g. Marker shadows)
markerPaneHTMLElement + 600Pane for Icons of Markers
tooltipPaneHTMLElement + 650Pane for Tooltips.
popupPaneHTMLElement + 700Pane for Popups.
+ +
+ + +
+ +
+

Locate options

+ +
+ + + +
Some of the geolocation methods for Map take in an options parameter. This +is a plain javascript object with the following optional components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
watchBoolean + falseIf true, starts continuous watching of location changes (instead of detecting it +once) using W3C watchPosition method. You can later stop watching using +map.stopLocate() method.
setViewBoolean + falseIf true, automatically sets the map view to the user location with respect to +detection accuracy, or to world view if geolocation failed.
maxZoomNumber + InfinityThe maximum zoom for automatic view setting when using setView option.
timeoutNumber + 10000Number of milliseconds to wait for a response from geolocation before firing a +locationerror event.
maximumAgeNumber + 0Maximum age of detected location. If less than this amount of milliseconds +passed since last geolocation response, locate will return a cached location.
enableHighAccuracyBoolean + falseEnables high accuracy, see description in the W3C spec.
+ +
+ + +
+ +
+

Zoom options

+ +
+ + + +
Some of the Map methods which modify the zoom level take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+ + +
+ +
+

Pan options

+ +
+ + + +
Some of the Map methods which modify the center of the map take in an options +parameter. This is a plain javascript object with the following optional +components:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If true, panning will always be animated if possible. If false, it will +not animate panning, either resetting the map view if panning more than a +screen away, or just setting a new offset for the map pane (except for panBy +which always does the latter).
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+ + +
+ +
+

Zoom/pan options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +
+ +
+

FitBounds options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingTopLeftPoint + [0, 0]Sets the amount of padding in the top left corner of a map container that +shouldn't be accounted for when setting the view to fit bounds. Useful if you +have some control overlays on the map like a sidebar and you don't want them +to obscure objects you're zooming to.
paddingBottomRightPoint + [0, 0]The same for the bottom right corner of the map.
paddingPoint + [0, 0]Equivalent of setting both top left and bottom right padding to the same value.
maxZoomNumber + nullThe maximum possible zoom to use.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
animateBoolean + If not specified, zoom animation will happen if the zoom origin is inside the +current view. If true, the map will attempt animating zoom disregarding where +zoom origin is. Setting false will make it always reset the view completely +without animation.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
durationNumber + 0.25Duration of animated panning, in seconds.
easeLinearityNumber + 0.25The curvature factor of panning animation easing (third parameter of the +Cubic Bezier curve). 1.0 means linear animation, +and the smaller this number, the more bowed the curve.
noMoveStartBoolean + falseIf true, panning won't fire movestart event on start (used internally for +panning inertia).
+ +
+
+
+ +

Marker

L.Marker is used to display clickable/draggable icons on the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.marker([50.5, 30.5]).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.marker(<LatLng> latlng, <Marker options> options?)Instantiates a Marker object given a geographical point and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconIcon + *Icon instance to use for rendering the marker. +See Icon documentation for details on how to customize the marker icon. +If not specified, a common instance of L.Icon.Default is used.
keyboardBoolean + trueWhether the marker can be tabbed to with a keyboard and clicked by pressing enter.
titleString + ''Text for the browser tooltip that appear on marker hover (no tooltip by default).
altString + ''Text for the alt attribute of the icon image (useful for accessibility).
zIndexOffsetNumber + 0By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like 1000 (or high negative value, respectively).
opacityNumber + 1.0The opacity of the marker.
riseOnHoverBoolean + falseIf true, the marker will get on top of others when you hover the mouse over it.
riseOffsetNumber + 250The z-index offset used for the riseOnHover feature.
paneString + 'markerPane'Map pane where the markers icon will be added.
bubblingMouseEventsBoolean + falseWhen true, a mouse event on this marker will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ +

Draggable marker options

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
draggableBoolean + falseWhether the marker is draggable with mouse/touch or not.
autoPanBoolean + falseWhether to pan the map when dragging this marker near its edge or not.
autoPanPaddingPoint + Point(50, 50)Distance (in pixels to the left/right and to the top/bottom) of the +map edge to start panning the map.
autoPanSpeedNumber + 10Number of pixels the map should pan by.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + +
In addition to shared layer methods like addTo() and remove() and popup methods like bindPopup() you can also use the following methods:
+ + + + + + + + + + + + +
EventDataDescription
move + EventFired when the marker is moved via setLatLng or by dragging. Old and new coordinates are included in event arguments as oldLatLng, latlng.
+ +
+ +

Dragging events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
dragstart + EventFired when the user starts dragging the marker.
movestart + EventFired when the marker starts moving (because of dragging).
drag + EventFired repeatedly while the user drags the marker.
dragend + DragEndEventFired when the user stops dragging the marker.
moveend + EventFired when the marker stops moving (because of dragging).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the marker (as a GeoJSON Point Feature).

+
getLatLng()LatLng

Returns the current geographical position of the marker.

+
setLatLng(<LatLng> latlng)this

Changes the marker position to the given point.

+
setZIndexOffset(<Number> offset)this

Changes the zIndex offset of the marker.

+
setIcon(<Icon> icon)this

Changes the marker icon.

+
setOpacity(<Number> opacity)this

Changes the opacity of the marker.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Properties

+ +
+ +

Interaction handlers

+ +
Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see Handler methods). Example: +
marker.dragging.disable();
+
+ + + + + + + + + + + + +
PropertyTypeDescription
dragging + HandlerMarker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set marker.options.draggable).
+ +
+ + +

Used to open popups in certain places of the map. Use Map.openPopup to +open popups while making sure that only one popup is open at one time +(recommended for usability), or use Map.addLayer to open as many as you want.

+ +
+ + +
+ + + + + +

If you want to just bind a popup to marker click and then open it, it's really easy:

+
marker.bindPopup(popupContent).openPopup();
+
+

Path overlays like polylines also have a bindPopup method. +Here's a more complicated way to open a popup on a map:

+
var popup = L.popup()
+    .setLatLng(latlng)
+    .setContent('<p>Hello world!<br />This is a nice popup.</p>')
+    .openOn(map);
+
+ + + +
+ + +
+ + +
+ + + + + + + + + + + + + + +
FactoryDescription
+ +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
+ +
+
+
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
+ +
+
+
+ +

Tooltip

Used to display small texts on top of map layers.

+ +
+

Usage example

+ +
+ + + + + +
marker.bindTooltip("my tooltip text").openTooltip();
+
+

Note about tooltip offset. Leaflet takes two options in consideration +for computing tooltip offsetting:

+
    +
  • the offset Tooltip option: it defaults to [0, 0], and it's specific to one tooltip. +Add a positive x offset to move the tooltip to the right, and a positive y offset to +move it to the bottom. Negatives will move to the left and top.
  • +
  • the tooltipAnchor Icon option: this will only be considered for Marker. You +should adapt this value if you use a custom icon.
  • +
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tooltip(<Tooltip options> options?, <Layer> source?)Instantiates a Tooltip object given an optional options object that describes its appearance and location and an optional source object that is used to tag the tooltip with a reference to the Layer to which it refers.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'tooltipPane'Map pane where the tooltip will be added.
offsetPoint + Point(0, 0)Optional offset of the tooltip position.
directionString + 'auto'Direction where to open the tooltip. Possible values are: right, left, +top, bottom, center, auto. +auto will dynamically switch between right and left according to the tooltip +position on the map.
permanentBoolean + falseWhether to open the tooltip permanently or only on mouseover.
stickyBoolean + falseIf true, the tooltip will follow the mouse instead of being fixed at the feature center.
interactiveBoolean + falseIf true, the tooltip will listen to the feature events.
opacityNumber + 0.9Tooltip container opacity.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
classNameString + ''A custom CSS class name to assign to the popup.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer

Used to load and display tile layers on the map. Extends GridLayer.

+ +
+

Usage example

+ +
+ + + + + +
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).addTo(map);
+
+ + + +
+ +

URL template

+ + + +

A string of the following form:

+
'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'
+

{s} means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; a, b or c by default, can be omitted), {z} — zoom level, {x} and {y} — tile coordinates. {r} can be used to add "@2x" to the URL to load retina tiles. +You can use custom keys in the template, which will be evaluated from TileLayer options, like this:

+
L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});
+
+ + +
+ + +
+

Creation

+ +
+ +

Extension methods

+ + + + + + + + + + + + +
FactoryDescription
L.tilelayer(<String> urlTemplate, <TileLayer options> options?)Instantiates a tile layer object given a URL template and optionally an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the tiles. +If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data. +Refer to CORS Settings for valid String values.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropriate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+ +

Extension methods

+ +
Layers extending TileLayer might reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
getTileUrl(<Object> coords)String

Called only internally, returns the URL for a tile given its coordinates. +Classes extending TileLayer can override this function to provide custom tile URL naming schemes.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

TileLayer.WMS

Used to display WMS services as tile layers on the map. Extends TileLayer.

+ +
+

Usage example

+ +
+ + + + + +
var nexrad = L.tileLayer.wms("http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi", {
+    layers: 'nexrad-n0r-900913',
+    format: 'image/png',
+    transparent: true,
+    attribution: "Weather data © 2012 IEM Nexrad"
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.tileLayer.wms(<String> baseUrl, <TileLayer.WMS options> options)Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.
+ +
+ + +
+

Options

+ +
+ + + +
If any custom options not documented here are used, they will be sent to the +WMS server as extra parameters in each request URL. This can be useful for +non-standard vendor WMS parameters.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
layersString + ''(required) Comma-separated list of WMS layers to show.
stylesString + ''Comma-separated list of WMS styles.
formatString + 'image/jpeg'WMS image format (use 'image/png' for layers with transparency).
transparentBoolean + falseIf true, the WMS service will return images with transparency.
versionString + '1.1.1'Version of the WMS service to use
crsCRS + nullCoordinate Reference System to use for the WMS requests, defaults to +map CRS. Don't change this if you're not sure what it means.
uppercaseBoolean + falseIf true, WMS request parameter keys will be uppercase.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + 18The maximum zoom level up to which this layer will be displayed (inclusive).
subdomainsString|String[] + 'abc'Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.
errorTileUrlString + ''URL to the tile image to show in place of the tile that failed to load.
zoomOffsetNumber + 0The zoom number used in tile URLs will be offset with this value.
tmsBoolean + falseIf true, inverses Y axis numbering for tiles (turn this on for TMS services).
zoomReverseBoolean + falseIf set to true, the zoom number used in tile URLs will be reversed (maxZoom - zoom instead of zoom)
detectRetinaBoolean + falseIf true and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the tiles. +If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data. +Refer to CORS Settings for valid String values.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setParams(<Object> params, <Boolean> noRedraw?)this

Merges an object with the new parameters and re-requests tiles on the current screen (unless noRedraw was set to true).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setUrl(<String> url, <Boolean> noRedraw?)this

Updates the layer's URL template and redraws it (unless noRedraw is set to true).

+
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, overrides GridLayer's createTile() +to return an <img> HTML element with the appropriate image URL given coords. The done +callback is called when the tile has been loaded.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

ImageOverlay

Used to load and display a single image over specific bounds of the map. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',
+    imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];
+L.imageOverlay(imageUrl, imageBounds).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.imageOverlay(<String> imageUrl, <LatLngBounds> bounds, <ImageOverlay options> options?)Instantiates an image overlay object given the URL of the image and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the image. +If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data. +Refer to CORS Settings for valid String values.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the overlay layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the ImageOverlay layer has loaded its image
error + EventFired when the ImageOverlay layer fails to load its image
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers

+
setZIndex(<Number> value)this

Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
getElement()HTMLElement

Returns the instance of HTMLImageElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

VideoOverlay

Used to load and display a video player over specific bounds of the map. Extends ImageOverlay. +A video overlay uses the <video> +HTML5 element.

+ +
+

Usage example

+ +
+ + + + + +
var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
+    videoBounds = [[ 32, -130], [ 13, -100]];
+L.videoOverlay(videoUrl, videoBounds ).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.videoOverlay(<String|Array|HTMLVideoElement> video, <LatLngBounds> bounds, <VideoOverlay options> options?)Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the +geographical bounds it is tied to.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
autoplayBoolean + trueWhether the video starts playing automatically when loaded.
loopBoolean + trueWhether the video will loop back to the beginning when played.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
opacityNumber + 1.0The opacity of the image overlay.
altString + ''Text for the alt attribute of the image (useful for accessibility).
interactiveBoolean + falseIf true, the image overlay will emit mouse events when clicked or hovered.
crossOriginBoolean|String + falseWhether the crossOrigin attribute will be added to the image. +If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data. +Refer to CORS Settings for valid String values.
errorOverlayUrlString + ''URL to the overlay image to show in place of the overlay that failed to load.
zIndexNumber + 1The explicit zIndex of the overlay layer.
classNameString + ''A custom class name to assign to the image. Empty by default.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
load + EventFired when the video has finished loading the first frame
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
error + EventFired when the ImageOverlay layer fails to load its image
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
getElement()HTMLVideoElement

Returns the instance of HTMLVideoElement +used by this overlay.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setOpacity(<Number> opacity)this

Sets the opacity of the overlay.

+
bringToFront()this

Brings the layer to the top of all overlays.

+
bringToBack()this

Brings the layer to the bottom of all overlays.

+
setUrl(<String> url)this

Changes the URL of the image.

+
setBounds(<LatLngBounds> bounds)this

Update the bounds that this ImageOverlay covers

+
setZIndex(<Number> value)this

Changes the zIndex of the image overlay.

+
getBounds()LatLngBounds

Get the bounds that this ImageOverlay covers

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Path

An abstract class that contains options and constants shared between vector +overlays (Polygon, Polyline, Circle). Do not use it directly. Extends Layer.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polyline

A class for drawing polyline overlays on a map. Extends Path.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polyline from an array of LatLng points
+var latlngs = [
+    [45.51, -122.68],
+    [37.77, -122.43],
+    [34.04, -118.2]
+];
+var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polyline
+map.fitBounds(polyline.getBounds());
+
+

You can also pass a multi-dimensional array to represent a MultiPolyline shape:

+
// create a red polyline from an array of arrays of LatLng points
+var latlngs = [
+    [[45.51, -122.68],
+     [37.77, -122.43],
+     [34.04, -118.2]],
+    [[40.78, -73.91],
+     [41.83, -87.62],
+     [32.76, -96.72]]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polyline(<LatLng[]> latlngs, <Polyline options> options?)Instantiates a polyline object given an array of geographical points and +optionally an options object. You can create a Polyline object with +multiple separate lines (MultiPolyline) by passing an array of arrays +of geographic points.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polyline (as a GeoJSON LineString or MultiLineString Feature).

+
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint(<Point> p)Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Polygon

A class for drawing polygon overlays on a map. Extends Polyline. +Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.

+ +
+

Usage example

+ +
+ + + + + +
// create a red polygon from an array of LatLng points
+var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
+var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
+// zoom the map to the polygon
+map.fitBounds(polygon.getBounds());
+
+

You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:

+
var latlngs = [
+  [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+  [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+];
+
+

Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.

+
var latlngs = [
+  [ // first polygon
+    [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring
+    [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole
+  ],
+  [ // second polygon
+    [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]
+  ]
+];
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.polygon(<LatLng[]> latlngs, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint(<Point> p)Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Rectangle

A class for drawing rectangle overlays on a map. Extends Polygon.

+ +
+

Usage example

+ +
+ + + + + +
// define rectangle geographical bounds
+var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];
+// create an orange rectangle
+L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
+// zoom the map to the rectangle bounds
+map.fitBounds(bounds);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.rectangle(<LatLngBounds> latLngBounds, <Polyline options> options?)
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
smoothFactorNumber + 1.0How much to simplify the polyline on each zoom level. More means +better performance and smoother look, and less means more accurate representation.
noClipBoolean + falseDisable polyline clipping.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
setBounds(<LatLngBounds> latLngBounds)this

Redraws the rectangle with the passed bounds.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the polygon (as a GeoJSON Polygon or MultiPolygon Feature).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getLatLngs()LatLng[]

Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.

+
setLatLngs(<LatLng[]> latlngs)this

Replaces all the points in the polyline with the given array of geographical points.

+
isEmpty()Boolean

Returns true if the Polyline has no LatLngs.

+
closestLayerPoint(<Point> p)Point

Returns the point closest to p on the Polyline.

+
getCenter()LatLng

Returns the center (centroid) of the polyline.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
addLatLng(<LatLng> latlng)this

Adds a given point to the polyline. By default, adds to the first ring of +the polyline in case of a multi-polyline, but can be overridden by passing +a specific ring as a LatLng array (that you can earlier access with getLatLngs).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Circle

A class for drawing circle overlays on a map. Extends CircleMarker. +It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).

+ +
+

Usage example

+ +
+ + + + + +
L.circle([50.5, 30.5], {radius: 200}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.circle(<LatLng> latlng, <Circle options> options?)Instantiates a circle object given a geographical point, and an options object +which contains the circle radius.
L.circle(<LatLng> latlng, <Number> radius, <Circle options> options?)Obsolete way of instantiating a circle, for compatibility with 0.7.x code. +Do not use in new applications or plugins.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + Radius of the circle, in meters.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setRadius(<Number> radius)this

Sets the radius of a circle. Units are in meters.

+
getRadius()Number

Returns the current radius of a circle. Units are in meters.

+
getBounds()LatLngBounds

Returns the LatLngBounds of the path.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

CircleMarker

A circle of a fixed size with radius specified in pixels. Extends Path.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.circleMarker(<LatLng> latlng, <CircleMarker options> options?)Instantiates a circle marker object given a geographical point, and an optional options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
radiusNumber + 10Radius of the circle marker, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
strokeBoolean + trueWhether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
colorString + '#3388ff'Stroke color
weightNumber + 3Stroke width in pixels
opacityNumber + 1.0Stroke opacity
lineCapString + 'round'A string that defines shape to be used at the end of the stroke.
lineJoinString + 'round'A string that defines shape to be used at the corners of the stroke.
dashArrayString + nullA string that defines the stroke dash pattern. Doesn't work on Canvas-powered layers in some old browsers.
dashOffsetString + nullA string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas-powered layers in some old browsers.
fillBoolean + dependsWhether to fill the path with color. Set it to false to disable filling on polygons or circles.
fillColorString + *Fill color. Defaults to the value of the color option
fillOpacityNumber + 0.2Fill opacity.
fillRuleString + 'evenodd'A string that defines how the inside of a shape is determined.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this path will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
rendererRenderer + Use this specific instance of Renderer for this path. Takes +precedence over the map's default renderer.
classNameString + nullCustom class name set on an element. Only for SVG renderer.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the circle marker (as a GeoJSON Point Feature).

+
setLatLng(<LatLng> latLng)this

Sets the position of a circle marker to a new location.

+
getLatLng()LatLng

Returns the current geographical position of the circle marker

+
setRadius(<Number> radius)this

Sets the radius of a circle marker. Units are in pixels.

+
getRadius()Number

Returns the current radius of the circle

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
redraw()this

Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

+
setStyle(<Path options> style)this

Changes the appearance of a Path based on the options in the Path options object.

+
bringToFront()this

Brings the layer to the top of all path layers.

+
bringToBack()this

Brings the layer to the bottom of all path layers.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

SVG

Allows vector layers to be displayed with SVG. +Inherits Renderer. +Due to technical limitations, SVG is not +available in all web browsers, notably Android 2.x and 3.x. +Although SVG is not available on IE7 and IE8, these browsers support +VML +(a now deprecated technology), and the SVG renderer will fall back to VML in +this case. +Although SVG is not available on IE7 and IE8, these browsers support VML, and the SVG renderer will fall back to VML in this case. +VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility +with old versions of Internet Explorer.

+ +
+

Usage example

+ +
+ + + + + +

Use SVG by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.svg()
+});
+
+

Use a SVG renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.svg({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.svg(<Renderer options> options?)Creates a SVG renderer with the given options.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.SVG:
+ + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
create(<String> name)SVGElementReturns a instance of SVGElement, +corresponding to the class name passed. For example, using 'line' will return +an instance of SVGLineElement.
pointsToPath(<Point[]> rings, <Boolean> closed)StringGenerates a SVG path string for multiple rings, with each ring turning +into "M..L..L.." instructions
+ +
+ + +

Canvas

Allows vector layers to be displayed with <canvas>. +Inherits Renderer. +Due to technical limitations, Canvas is not +available in all web browsers, notably IE8, and overlapping geometries might +not display properly in some edge cases.

+ +
+

Usage example

+ +
+ + + + + +

Use Canvas by default for all paths in the map:

+
var map = L.map('map', {
+    renderer: L.canvas()
+});
+
+

Use a Canvas renderer with extra padding for specific vector geometries:

+
var map = L.map('map');
+var myRenderer = L.canvas({ padding: 0.5 });
+var line = L.polyline( coordinates, { renderer: myRenderer } );
+var circle = L.circle( center, { renderer: myRenderer } );
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.canvas(<Renderer options> options?)Creates a Canvas renderer with the given options.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LayerGroup

Used to group several layers and handle them as one. If you add it to the map, +any layers added or removed from the group will be added/removed on the map as +well. Extends Layer.

+ +
+

Usage example

+ +
+ + + + + +
L.layerGroup([marker1, marker2])
+    .addLayer(polyline)
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.layerGroup(<Layer[]> layers?, <Object> options?)Create a layer group, optionally given an initial set of layers and an options object.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

FeatureGroup

Extended LayerGroup that makes it easier to do the same thing to all its member layers:

+
    +
  • bindPopup binds a popup to all of the layers at once (likewise with bindTooltip)
  • +
  • Events are propagated to the FeatureGroup, so if the group has an event +handler, it will handle events from any of the layers. This includes mouse events +and custom events.
  • +
  • Has layeradd and layerremove events
  • +
+ +
+

Usage example

+ +
+ + + + + +
L.featureGroup([marker1, marker2, polyline])
+    .bindPopup('Hello world!')
+    .on('click', function() { alert('Clicked on a member of the group!'); })
+    .addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.featureGroup(<Layer[]> layers)Create a feature group, optionally given an initial set of layers.
+ +
+ + +
+

Options

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setStyle(<Path options> style)this

Sets the given path options to each layer of the group that has a setStyle method.

+
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

GeoJSON

Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse +GeoJSON data and display it on the map. Extends FeatureGroup.

+ +
+

Usage example

+ +
+ + + + + +
L.geoJSON(data, {
+    style: function (feature) {
+        return {color: feature.properties.color};
+    }
+}).bindPopup(function (layer) {
+    return layer.feature.properties.description;
+}).addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.geoJSON(<Object> geojson?, <GeoJSON options> options?)Creates a GeoJSON layer. Optionally accepts an object in +GeoJSON format to display on the map +(you can alternatively add it later with addData method) and an options object.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
pointToLayerFunction + *A Function defining how GeoJSON points spawn Leaflet layers. It is internally +called when data is added, passing the GeoJSON point feature and its LatLng. +The default is to spawn a default Marker: +
function(geoJsonPoint, latlng) {
+    return L.marker(latlng);
+}
+
styleFunction + *A Function defining the Path options for styling GeoJSON lines and polygons, +called internally when data is added. +The default value is to not override any defaults: +
function (geoJsonFeature) {
+    return {}
+}
+
onEachFeatureFunction + *A Function that will be called once for each created Feature, after it has +been created and styled. Useful for attaching events and popups to features. +The default is to do nothing with the newly created layers: +
function (feature, layer) {}
+
filterFunction + *A Function that will be used to decide whether to include a feature or not. +The default is to include all features: +
function (geoJsonFeature) {
+    return true;
+}
+
+

Note: dynamically changing the filter option will have effect only on newly +added data. It will not re-evaluate already included features.

coordsToLatLngFunction + *A Function that will be used for converting GeoJSON coordinates to LatLngs. +The default is the coordsToLatLng static method.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
layeradd + LayerEventFired when a layer is added to this FeatureGroup
layerremove + LayerEventFired when a layer is removed from this FeatureGroup
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addData(data)this

Adds a GeoJSON object to the layer.

+
resetStyle(layer)this

Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.

+
setStyle(style)this

Changes styles of GeoJSON vector layers with the given style function.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the layer group to the top of all other layers

+
bringToBack()this

Brings the layer group to the back of all other layers

+
getBounds()LatLngBounds

Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
toGeoJSON()Object

Returns a GeoJSON representation of the layer group (as a GeoJSON FeatureCollection, GeometryCollection, or MultiPoint).

+
addLayer(<Layer> layer)this

Adds the given layer to the group.

+
removeLayer(<Layer> layer)this

Removes the given layer from the group.

+
removeLayer(<Number> id)this

Removes the layer with the given internal ID from the group.

+
hasLayer(<Layer> layer)Boolean

Returns true if the given layer is currently added to the group.

+
hasLayer(<Number> id)Boolean

Returns true if the given internal ID is currently added to the group.

+
clearLayers()this

Removes all the layers from the group.

+
invoke(<String> methodName, )this

Calls methodName on every layer contained in this group, passing any +additional parameters. Has no effect if the layers contained do not +implement methodName.

+
eachLayer(<Function> fn, <Object> context?)this

Iterates over the layers of the group, optionally specifying context of the iterator function.

+
group.eachLayer(function (layer) {
+    layer.bindPopup('Hello');
+});
+
+
getLayer(<Number> id)Layer

Returns the layer with the given internal ID.

+
getLayers()Layer[]

Returns an array of all the layers added to the group.

+
setZIndex(<Number> zIndex)this

Calls setZIndex on every layer contained in this group, passing the z-index.

+
getLayerId(<Layer> layer)Number

Returns the internal ID for a layer

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +
+

Functions

+ +
+ + + +
There are several static functions which can be called without instantiating L.GeoJSON:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
geometryToLayer(<Object> featureData, <GeoJSON options> options?)LayerCreates a Layer from a given GeoJSON feature. Can use a custom +pointToLayer and/or coordsToLatLng +functions if provided as options.
coordsToLatLng(<Array> coords)LatLngCreates a LatLng object from an array of 2 numbers (longitude, latitude) +or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.
coordsToLatLngs(<Array> coords, <Number> levelsDeep?, <Function> coordsToLatLng?)ArrayCreates a multidimensional array of LatLngs from a GeoJSON coordinates array. +levelsDeep specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default). +Can use a custom coordsToLatLng function.
latLngToCoords(<LatLng> latlng, <Number> precision?)ArrayReverse of coordsToLatLng
latLngsToCoords(<Array> latlngs, <Number> levelsDeep?, <Boolean> closed?)ArrayReverse of coordsToLatLngs +closed determines whether the first point should be appended to the end of the array to close the feature, only used when levelsDeep is 0. False by default.
asFeature(<Object> geojson)ObjectNormalize GeoJSON geometries/features into GeoJSON features.
+ +
+ + +

GridLayer

Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces TileLayer.Canvas. +GridLayer can be extended to create a tiled grid of HTML elements like <canvas>, <img> or <div>. GridLayer will handle creating and animating these DOM elements for you.

+ +
+

Usage example

+ +
+ +

Synchronous usage

+ + + +

To create a custom layer, extend GridLayer and implement the createTile() method, which will be passed a Point object with the x, y, and z (zoom level) coordinates to draw your tile.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords){
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // get a canvas context and draw something on it using coords.x, coords.y and coords.z
+        var ctx = tile.getContext('2d');
+        // return the tile so it can be rendered on screen
+        return tile;
+    }
+});
+
+ + + +
+ +

Asynchronous usage

+ + + +

Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the done() callback.

+
var CanvasLayer = L.GridLayer.extend({
+    createTile: function(coords, done){
+        var error;
+        // create a <canvas> element for drawing
+        var tile = L.DomUtil.create('canvas', 'leaflet-tile');
+        // setup tile width and height according to the options
+        var size = this.getTileSize();
+        tile.width = size.x;
+        tile.height = size.y;
+        // draw something asynchronously and pass the tile to the done() callback
+        setTimeout(function() {
+            done(error, tile);
+        }, 1000);
+        return tile;
+    }
+});
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.gridLayer(<GridLayer options> options?)Creates a new instance of GridLayer with the supplied options.
+ +
+ + +
+

Options

+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
tileSizeNumber|Point + 256Width and height of tiles in the grid. Use a number if width and height are equal, or L.point(width, height) otherwise.
opacityNumber + 1.0Opacity of the tiles. Can be used in the createTile() function.
updateWhenIdleBoolean + (depends)Load new tiles only when panning ends. +true by default on mobile browsers, in order to avoid too many requests and keep smooth navigation. +false otherwise in order to display new tiles during panning, since it is easy to pan outside the +keepBuffer option in desktop browsers.
updateWhenZoomingBoolean + trueBy default, a smooth zoom animation (during a touch zoom or a flyTo()) will update grid layers every integer zoom level. Setting this option to false will update the grid layer only when the smooth animation ends.
updateIntervalNumber + 200Tiles will not update more than once every updateInterval milliseconds when panning.
zIndexNumber + 1The explicit zIndex of the tile layer.
boundsLatLngBounds + undefinedIf set, tiles will only be loaded inside the set LatLngBounds.
minZoomNumber + 0The minimum zoom level down to which this layer will be displayed (inclusive).
maxZoomNumber + undefinedThe maximum zoom level up to which this layer will be displayed (inclusive).
maxNativeZoomNumber + undefinedMaximum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels higher than maxNativeZoom will be loaded +from maxNativeZoom level and auto-scaled.
minNativeZoomNumber + undefinedMinimum zoom number the tile source has available. If it is specified, +the tiles on all zoom levels lower than minNativeZoom will be loaded +from minNativeZoom level and auto-scaled.
noWrapBoolean + falseWhether the layer is wrapped around the antimeridian. If true, the +GridLayer will only be displayed once at low zoom levels. Has no +effect when the map CRS doesn't wrap around. Can be used +in combination with bounds to prevent requesting +tiles outside the CRS limits.
paneString + 'tilePane'Map pane where the grid layer will be added.
classNameString + ''A custom class name to assign to the tile layer. Empty by default.
keepBufferNumber + 2When panning the map, keep this many rows and columns of tiles before unloading them.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
loading + EventFired when the grid layer starts loading tiles.
tileunload + TileEventFired when a tile is removed (e.g. when a tile goes off the screen).
tileloadstart + TileEventFired when a tile is requested and starts loading.
tileerror + TileErrorEventFired when there is an error loading a tile.
tileload + TileEventFired when a tile loads.
load + EventFired when the grid layer loaded all visible tiles.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bringToFront()this

Brings the tile layer to the top of all tile layers.

+
bringToBack()this

Brings the tile layer to the bottom of all tile layers.

+
getContainer()HTMLElement

Returns the HTML element that contains the tiles for this layer.

+
setOpacity(<Number> opacity)this

Changes the opacity of the grid layer.

+
setZIndex(<Number> zIndex)this

Changes the zIndex of the grid layer.

+
isLoading()Boolean

Returns true if any tile in the grid layer has not finished loading.

+
redraw()this

Causes the layer to clear all the tiles and request them again.

+
getTileSize()Point

Normalizes the tileSize option into a point. Used by the createTile() method.

+
+ +
+ +

Extension methods

+ +
Layers extending GridLayer shall reimplement the following method.
+ + + + + + + + + + + + + +
MethodReturnsDescription
createTile(<Object> coords, <Function> done?)HTMLElement

Called only internally, must be overridden by classes extending GridLayer. +Returns the HTMLElement corresponding to the given coords. If the done callback +is specified, it must be called when the tile has finished loading and drawing.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

LatLng

Represents a geographical point with a certain latitude and longitude.

+ +
+

Usage example

+ +
+ + + + + +
var latlng = L.latLng(50.5, 30.5);
+

All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:

+
map.panTo([50, 30]);
+map.panTo({lon: 30, lat: 50});
+map.panTo({lat: 50, lng: 30});
+map.panTo(L.latLng(50, 30));
+

Note that LatLng does not inherit from Leaflet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLng(<Number> latitude, <Number> longitude, <Number> altitude?)Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).
L.latLng(<Array> coords)Expects an array of the form [Number, Number] or [Number, Number, Number] instead.
L.latLng(<Object> coords)Expects an plain object of the form {lat: Number, lng: Number} or {lat: Number, lng: Number, alt: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
equals(<LatLng> otherLatLng, <Number> maxMargin?)Boolean

Returns true if the given LatLng point is at the same position (within a small margin of error). The margin of error can be overridden by setting maxMargin to a small number.

+
toString()String

Returns a string representation of the point (for debugging purposes).

+
distanceTo(<LatLng> otherLatLng)Number

Returns the distance (in meters) to the given LatLng calculated using the Spherical Law of Cosines.

+
wrap()LatLng

Returns a new LatLng object with the longitude wrapped so it's always between -180 and +180 degrees.

+
toBounds(<Number> sizeInMeters)LatLngBounds

Returns a new LatLngBounds object in which each boundary is sizeInMeters/2 meters apart from the LatLng.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lat + NumberLatitude in degrees
lng + NumberLongitude in degrees
alt + NumberAltitude in meters (optional)
+ +
+ + +

LatLngBounds

Represents a rectangular geographical area on a map.

+ +
+

Usage example

+ +
+ + + + + +
var corner1 = L.latLng(40.712, -74.227),
+corner2 = L.latLng(40.774, -74.125),
+bounds = L.latLngBounds(corner1, corner2);
+
+

All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
map.fitBounds([
+    [40.712, -74.227],
+    [40.774, -74.125]
+]);
+
+

Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners outside the [-180, 180] degrees longitude range. +Note that LatLngBounds does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.latLngBounds(<LatLng> corner1, <LatLng> corner2)Creates a LatLngBounds object by defining two diagonally opposite corners of the rectangle.
L.latLngBounds(<LatLng[]> latlngs)Creates a LatLngBounds object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with fitBounds.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<LatLng> latlng)this

Extend the bounds to contain the given point

+
extend(<LatLngBounds> otherBounds)this

Extend the bounds to contain the given bounds

+
pad(<Number> bufferRatio)LatLngBounds

Returns bounds created by extending or retracting the current bounds by a given ratio in each direction. +For example, a ratio of 0.5 extends the bounds by 50% in each direction. +Negative values will retract the bounds.

+
getCenter()LatLng

Returns the center point of the bounds.

+
getSouthWest()LatLng

Returns the south-west point of the bounds.

+
getNorthEast()LatLng

Returns the north-east point of the bounds.

+
getNorthWest()LatLng

Returns the north-west point of the bounds.

+
getSouthEast()LatLng

Returns the south-east point of the bounds.

+
getWest()Number

Returns the west longitude of the bounds

+
getSouth()Number

Returns the south latitude of the bounds

+
getEast()Number

Returns the east longitude of the bounds

+
getNorth()Number

Returns the north latitude of the bounds

+
contains(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<LatLng> latlng)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<LatLngBounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.

+
toBBoxString()String

Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.

+
equals(<LatLngBounds> otherBounds, <Number> maxMargin?)Boolean

Returns true if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting maxMargin to a small number.

+
isValid()Boolean

Returns true if the bounds are properly initialized.

+
+ +
+ + +

Point

Represents a point with x and y coordinates in pixels.

+ +
+

Usage example

+ +
+ + + + + +
var point = L.point(200, 300);
+
+

All Leaflet methods and options that accept Point objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:

+
map.panBy([200, 300]);
+map.panBy(L.point(200, 300));
+
+

Note that Point does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
FactoryDescription
L.point(<Number> x, <Number> y, <Boolean> round?)Creates a Point object with the given x and y coordinates. If optional round is set to true, rounds the x and y values.
L.point(<Number[]> coords)Expects an array of the form [x, y] instead.
L.point(<Object> coords)Expects a plain object of the form {x: Number, y: Number} instead.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
clone()Point

Returns a copy of the current point.

+
add(<Point> otherPoint)Point

Returns the result of addition of the current and the given points.

+
subtract(<Point> otherPoint)Point

Returns the result of subtraction of the given point from the current.

+
divideBy(<Number> num)Point

Returns the result of division of the current point by the given number.

+
multiplyBy(<Number> num)Point

Returns the result of multiplication of the current point by the given number.

+
scaleBy(<Point> scale)Point

Multiply each coordinate of the current point by each coordinate of +scale. In linear algebra terms, multiply the point by the +scaling matrix +defined by scale.

+
unscaleBy(<Point> scale)Point

Inverse of scaleBy. Divide each coordinate of the current point by +each coordinate of scale.

+
round()Point

Returns a copy of the current point with rounded coordinates.

+
floor()Point

Returns a copy of the current point with floored coordinates (rounded down).

+
ceil()Point

Returns a copy of the current point with ceiled coordinates (rounded up).

+
trunc()Point

Returns a copy of the current point with truncated coordinates (rounded towards zero).

+
distanceTo(<Point> otherPoint)Number

Returns the cartesian distance between the current and the given points.

+
equals(<Point> otherPoint)Boolean

Returns true if the given point has the same coordinates.

+
contains(<Point> otherPoint)Boolean

Returns true if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).

+
toString()String

Returns a string representation of the point for debugging purposes.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
x + NumberThe x coordinate of the point
y + NumberThe y coordinate of the point
+ +
+ + +

Bounds

Represents a rectangular area in pixel coordinates.

+ +
+

Usage example

+ +
+ + + + + +
var p1 = L.point(10, 10),
+p2 = L.point(40, 60),
+bounds = L.bounds(p1, p2);
+
+

All Leaflet methods that accept Bounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:

+
otherBounds.intersects([[10, 10], [40, 60]]);
+
+

Note that Bounds does not inherit from Leafet's Class object, +which means new classes can't inherit from it, and new methods +can't be added to it with the include function.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.bounds(<Point> corner1, <Point> corner2)Creates a Bounds object from two corners coordinate pairs.
L.bounds(<Point[]> points)Creates a Bounds object from the given array of points.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
extend(<Point> point)this

Extends the bounds to contain the given point.

+
getCenter(<Boolean> round?)Point

Returns the center point of the bounds.

+
getBottomLeft()Point

Returns the bottom-left point of the bounds.

+
getTopRight()Point

Returns the top-right point of the bounds.

+
getTopLeft()Point

Returns the top-left point of the bounds (i.e. this.min).

+
getBottomRight()Point

Returns the bottom-right point of the bounds (i.e. this.max).

+
getSize()Point

Returns the size of the given bounds

+
contains(<Bounds> otherBounds)Boolean

Returns true if the rectangle contains the given one.

+
contains(<Point> point)Boolean

Returns true if the rectangle contains the given point.

+
intersects(<Bounds> otherBounds)Boolean

Returns true if the rectangle intersects the given bounds. Two bounds +intersect if they have at least one point in common.

+
overlaps(<Bounds> otherBounds)Boolean

Returns true if the rectangle overlaps the given bounds. Two bounds +overlap if their intersection is an area.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
min + PointThe top left corner of the rectangle.
max + PointThe bottom right corner of the rectangle.
+ +
+ + +

Icon

Represents an icon to provide when creating a marker.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.icon({
+    iconUrl: 'my-icon.png',
+    iconSize: [38, 95],
+    iconAnchor: [22, 94],
+    popupAnchor: [-3, -76],
+    shadowUrl: 'my-icon-shadow.png',
+    shadowSize: [68, 95],
+    shadowAnchor: [22, 94]
+});
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

L.Icon.Default extends L.Icon and is the blue icon Leaflet uses for markers by default.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.icon(<Icon options> options)Creates an icon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + [0, 0]The coordinates of the point from which popups will "open", relative to the icon anchor.
tooltipAnchorPoint + [0, 0]The coordinates of the point from which tooltips will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+ + +
+ +
+

Icon.Default

+ +
+ + + +
A trivial subclass of Icon, represents the icon to use in Markers when +no icon is specified. Points to the blue marker image distributed with Leaflet +releases. +In order to customize the default icon, just change the properties of L.Icon.Default.prototype.options +(which is a set of Icon options). +If you want to completely replace the default icon, override the +L.Marker.prototype.options.icon with your own icon instead.
+ + + + + + + + + + + + + + +
OptionTypeDefaultDescription
imagePathString + Icon.Default will try to auto-detect the location of the +blue icon images. If you are placing these images in a non-standard +way, set this option to point to the right path.
+ +
+ + +

DivIcon

Represents a lightweight icon for markers that uses a simple <div> +element instead of an image. Inherits from Icon but ignores the iconUrl and shadow options.

+ +
+

Usage example

+ +
+ + + + + +
var myIcon = L.divIcon({className: 'my-div-icon'});
+// you can set .my-div-icon styles in CSS
+L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
+
+

By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.

+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.divIcon(<DivIcon options> options)Creates a DivIcon instance with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
htmlString + ''Custom HTML code to put inside the div element, empty by default.
bgPosPoint + [0, 0]Optional relative position of the background, in pixels
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
iconUrlString + null(required) The URL to the icon image (absolute or relative to your script path).
iconRetinaUrlString + nullThe URL to a retina sized version of the icon image (absolute or relative to your +script path). Used for Retina screen devices.
iconSizePoint + nullSize of the icon image in pixels.
iconAnchorPoint + nullThe coordinates of the "tip" of the icon (relative to its top left corner). The icon +will be aligned so that this point is at the marker's geographical location. Centered +by default if size is specified, also can be set in CSS with negative margins.
popupAnchorPoint + [0, 0]The coordinates of the point from which popups will "open", relative to the icon anchor.
tooltipAnchorPoint + [0, 0]The coordinates of the point from which tooltips will "open", relative to the icon anchor.
shadowUrlString + nullThe URL to the icon shadow image. If not specified, no shadow image will be created.
shadowRetinaUrlString + null
shadowSizePoint + nullSize of the shadow image in pixels.
shadowAnchorPoint + nullThe coordinates of the "tip" of the shadow (relative to its top left corner) (the same +as iconAnchor if not specified).
classNameString + ''A custom class name to assign to both icon and shadow images. Empty by default.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
createIcon(<HTMLElement> oldIcon?)HTMLElement

Called internally when the icon has to be shown, returns a <img> HTML element +styled according to the options.

+
createShadow(<HTMLElement> oldIcon?)HTMLElement

As createIcon, but for the shadow beneath it.

+
+ +
+
+
+ +

Control.Zoom

A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its zoomControl option to false. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.zoom(<Control.Zoom options> options)Creates a zoom control
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
zoomInTextString + '+'The text set on the 'zoom in' button.
zoomInTitleString + 'Zoom in'The title set on the 'zoom in' button.
zoomOutTextString + '&#x2212' +The text set on the 'zoom out' button.
zoomOutTitleString + 'Zoom out'The title set on the 'zoom out' button.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Attribution

The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its attributionControl option to false, and it fetches attribution texts from layers with the getAttribution method automatically. Extends Control.

+ +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.attribution(<Control.Attribution options> options)Creates an attribution control.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
prefixString + 'Leaflet'The HTML text shown before the attributions. Pass false to disable.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
setPrefix(<String> prefix)this

Sets the text before the attributions.

+
addAttribution(<String> text)this

Adds an attribution text (e.g. 'Vector data &copy; Mapbox').

+
removeAttribution(<String> text)this

Removes an attribution text.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Layers

The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the detailed example). Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
var baseLayers = {
+    "Mapbox": mapbox,
+    "OpenStreetMap": osm
+};
+var overlays = {
+    "Marker": marker,
+    "Roads": roadsLayer
+};
+L.control.layers(baseLayers, overlays).addTo(map);
+
+

The baseLayers and overlays parameters are object literals with layer names as keys and Layer objects as values:

+
{
+    "<someName1>": layer1,
+    "<someName2>": layer2
+}
+
+

The layer names can contain HTML, which allows you to add additional styling to the items:

+
{"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>": myLayer}
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.layers(<Object> baselayers?, <Object> overlays?, <Control.Layers options> options?)Creates an attribution control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
collapsedBoolean + trueIf true, the control will be collapsed into an icon and expanded on mouse hover or touch.
autoZIndexBoolean + trueIf true, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.
hideSingleBaseBoolean + falseIf true, the base layers in the control will be hidden when there is only one.
sortLayersBoolean + falseWhether to sort the layers. When false, layers will keep the order +in which they were added to the control.
sortFunctionFunction + *A compare function +that will be used for sorting the layers, when sortLayers is true. +The function receives both the L.Layer instances and their names, as in +sortFunction(layerA, layerB, nameA, nameB). +By default, it sorts layers alphabetically by their name.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addBaseLayer(<Layer> layer, <String> name)this

Adds a base layer (radio button entry) with the given name to the control.

+
addOverlay(<Layer> layer, <String> name)this

Adds an overlay (checkbox entry) with the given name to the control.

+
removeLayer(<Layer> layer)this

Remove the given layer from the control.

+
expand()this

Expand the control container if collapsed.

+
collapse()this

Collapse the control container if expanded.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Control.Scale

A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends Control.

+ +
+

Usage example

+ +
+ + + + + +
L.control.scale().addTo(map);
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + +
FactoryDescription
L.control.scale(<Control.Scale options> options?)Creates an scale control with the given options.
+ +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
maxWidthNumber + 100Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).
metricBoolean + TrueWhether to show the metric scale line (m/km).
imperialBoolean + TrueWhether to show the imperial scale line (mi/ft).
updateWhenIdleBoolean + falseIf true, the control is updated on moveend, otherwise it's always up-to-date (updated on move).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+
+
+ +

Browser

A namespace with static properties for browser/feature detection used by Leaflet internally.

+ +
+

Usage example

+ +
+ + + + + +
if (L.Browser.ielt9) {
+  alert('Upgrade your browser, dude!');
+}
+
+ + + +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
ie + Booleantrue for all Internet Explorer versions (not Edge).
ielt9 + Booleantrue for Internet Explorer versions less than 9.
edge + Booleantrue for the Edge web browser.
webkit + Booleantrue for webkit-based browsers like Chrome and Safari (including mobile versions).
android + Booleantrue for any browser running on an Android platform.
android23 + Booleantrue for browsers running on Android 2 or Android 3.
androidStock + Booleantrue for the Android stock browser (i.e. not Chrome)
opera + Booleantrue for the Opera browser
chrome + Booleantrue for the Chrome browser.
gecko + Booleantrue for gecko-based browsers like Firefox.
safari + Booleantrue for the Safari browser.
opera12 + Booleantrue for the Opera browser supporting CSS transforms (version 12 or later).
win + Booleantrue when the browser is running in a Windows platform
ie3d + Booleantrue for all Internet Explorer versions supporting CSS transforms.
webkit3d + Booleantrue for webkit-based browsers supporting CSS transforms.
gecko3d + Booleantrue for gecko-based browsers supporting CSS transforms.
any3d + Booleantrue for all browsers supporting CSS transforms.
mobile + Booleantrue for all browsers running in a mobile device.
mobileWebkit + Booleantrue for all webkit-based browsers in a mobile device.
mobileWebkit3d + Booleantrue for all webkit-based browsers in a mobile device supporting CSS transforms.
msPointer + Booleantrue for browsers implementing the Microsoft touch events model (notably IE10).
pointer + Booleantrue for all browsers supporting pointer events.
touch + Booleantrue for all browsers supporting touch events. +This does not necessarily mean that the browser is running in a computer with +a touchscreen, it only means that the browser is capable of understanding +touch events.
mobileOpera + Booleantrue for the Opera browser in a mobile device.
mobileGecko + Booleantrue for gecko-based browsers running in a mobile device.
retina + Booleantrue for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%.
canvas + Booleantrue when the browser supports <canvas>.
svg + Booleantrue when the browser supports SVG.
vml + Booleantrue if the browser supports VML.
+ +
+ + +

Util

Various utility functions, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> dest, <Object> src?)ObjectMerges the properties of the src object (or multiple objects) into dest object and returns the latter. Has an L.extend shortcut.
create(<Object> proto, <Object> properties?)ObjectCompatibility polyfill for Object.create
bind(<Function> fn, )FunctionReturns a new function bound to the arguments passed, like Function.prototype.bind. +Has a L.bind() shortcut.
stamp(<Object> obj)NumberReturns the unique ID of an object, assigning it one if it doesn't have it.
throttle(<Function> fn, <Number> time, <Object> context)FunctionReturns a function which executes function fn with the given scope context +(so that the this keyword refers to context inside fn's code). The function +fn will be called no more than one time per given amount of time. The arguments +received by the bound function will be any arguments passed when binding the +function, followed by any arguments passed when invoking the bound function. +Has an L.throttle shortcut.
wrapNum(<Number> num, <Number[]> range, <Boolean> includeMax?)NumberReturns the number num modulo range in such a way so it lies within +range[0] and range[1]. The returned value will be always smaller than +range[1] unless includeMax is set to true.
falseFn()FunctionReturns a function which always returns false.
formatNum(<Number> num, <Number> digits?)NumberReturns the number num rounded to digits decimals, or to 6 decimals by default.
trim(<String> str)StringCompatibility polyfill for String.prototype.trim
splitWords(<String> str)String[]Trims and splits the string on whitespace and returns the array of parts.
setOptions(<Object> obj, <Object> options)ObjectMerges the given properties to the options of the obj object, returning the resulting options. See Class options. Has an L.setOptions shortcut.
getParamString(<Object> obj, <String> existingUrl?, <Boolean> uppercase?)StringConverts an object into a parameter URL string, e.g. {a: "foo", b: "bar"} +translates to '?a=foo&b=bar'. If existingUrl is set, the parameters will +be appended at the end. If uppercase is true, the parameter names will +be uppercased (e.g. '?A=foo&B=bar')
template(<String> str, <Object> data)StringSimple templating facility, accepts a template string of the form 'Hello {a}, {b}' +and a data object like {a: 'foo', b: 'bar'}, returns evaluated string +('Hello foo, bar'). You can also specify functions instead of strings for +data values — they will be evaluated passing data as an argument.
isArray(obj)BooleanCompatibility polyfill for Array.isArray
indexOf(<Array> array, <Object> el)NumberCompatibility polyfill for Array.prototype.indexOf
requestAnimFrame(<Function> fn, <Object> context?, <Boolean> immediate?)NumberSchedules fn to be executed when the browser repaints. fn is bound to +context if given. When immediate is set, fn is called immediately if +the browser doesn't have native support for +window.requestAnimationFrame, +otherwise it's delayed. Returns a request ID that can be used to cancel the request.
cancelAnimFrame(<Number> id)undefinedCancels a previous requestAnimFrame. See also window.cancelAnimationFrame.
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
lastId + NumberLast unique ID used by stamp()
emptyImageUrl + StringData URI string containing a base64-encoded empty GIF image. +Used as a hack to free memory from unused images on WebKit-powered +mobile devices (by setting image src to this string).
+ +
+ + +

Transformation

Represents an affine transformation: a set of coefficients a, b, c, d +for transforming a point of a form (x, y) into (a*x + b, c*y + d) and doing +the reverse. Used by Leaflet in its projections code.

+ +
+

Usage example

+ +
+ + + + + +
var transformation = L.transformation(2, 5, -1, 10),
+    p = L.point(1, 2),
+    p2 = transformation.transform(p), //  L.point(7, 8)
+    p3 = transformation.untransform(p2); //  L.point(1, 2)
+
+ + + +
+ + +
+

Creation

+ +
+ + + + + + + + + + + + + + + + + + +
FactoryDescription
L.transformation(<Number> a, <Number> b, <Number> c, <Number> d)Instantiates a Transformation object with the given coefficients.
L.transformation(<Array> coefficients)Expects an coefficients array of the form +[a: Number, b: Number, c: Number, d: Number].
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
transform(<Point> point, <Number> scale?)Point

Returns a transformed point, optionally multiplied by the given scale. +Only accepts actual L.Point instances, not arrays.

+
untransform(<Point> point, <Number> scale?)Point

Returns the reverse transformation of the given point, optionally divided +by the given scale. Only accepts actual L.Point instances, not arrays.

+
+ +
+ + +

LineUtil

Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
simplify(<Point[]> points, <Number> tolerance)Point[]Dramatically reduces the number of points in a polyline while retaining +its shape and returns a new array of simplified points, using the +Douglas-Peucker algorithm. +Used for a huge performance boost when processing/displaying Leaflet polylines for +each zoom level and also reducing visual noise. tolerance affects the amount of +simplification (lesser value means higher quality but slower and with more points). +Also released as a separated micro-library Simplify.js.
pointToSegmentDistance(<Point> p, <Point> p1, <Point> p2)NumberReturns the distance between point p and segment p1 to p2.
closestPointOnSegment(<Point> p, <Point> p1, <Point> p2)NumberReturns the closest point from a point p on a segment p1 to p2.
clipSegment(<Point> a, <Point> b, <Bounds> bounds, <Boolean> useLastCode?, <Boolean> round?)Point[]|BooleanClips the segment a to b by rectangular bounds with the +Cohen-Sutherland algorithm +(modifying the segment points directly!). Used by Leaflet to only show polyline +points that are on the screen or near, increasing performance.
isFlat(<LatLng[]> latlngs)BooleanReturns true if latlngs is a flat array, false is nested.
+ +
+ + +

PolyUtil

Various utility functions for polygon geometries.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + +
FunctionReturnsDescription
clipPolygon(<Point[]> points, <Bounds> bounds, <Boolean> round?)Point[]Clips the polygon geometry defined by the given points by the given bounds (using the Sutherland-Hodgman algorithm). +Used by Leaflet to only show polygon points that are on the screen or near, increasing +performance. Note that polygon points needs different algorithm for clipping +than polyline, so there's a separate method for it.
+ +
+ + +

DomEvent

Utility functions to work with the DOM events, used by Leaflet internally.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
on(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisAdds a listener function (fn) to a particular DOM event type of the +element el. You can optionally specify the context of the listener +(object the this keyword will point to). You can also pass several +space-separated types (e.g. 'click dblclick').
on(<HTMLElement> el, <Object> eventMap, <Object> context?)thisAdds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
off(<HTMLElement> el, <String> types, <Function> fn, <Object> context?)thisRemoves a previously added listener function. +Note that if you passed a custom context to on, you must pass the same +context to off in order to remove the listener.
off(<HTMLElement> el, <Object> eventMap, <Object> context?)thisRemoves a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}
stopPropagation(<DOMEvent> ev)thisStop the given event from propagation to parent elements. Used inside the listener functions: +
L.DomEvent.on(div, 'click', function (ev) {
+    L.DomEvent.stopPropagation(ev);
+});
+
disableScrollPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'mousewheel' events (plus browser variants).
disableClickPropagation(<HTMLElement> el)thisAdds stopPropagation to the element's 'click', 'doubleclick', +'mousedown' and 'touchstart' events (plus browser variants).
preventDefault(<DOMEvent> ev)thisPrevents the default action of the DOM Event ev from happening (such as +following a link in the href of the a element, or doing a POST request +with page reload when a <form> is submitted). +Use it inside listener functions.
stop(<DOMEvent> ev)thisDoes stopPropagation and preventDefault at the same time.
getMousePosition(<DOMEvent> ev, <HTMLElement> container?)PointGets normalized mouse position from a DOM event relative to the +container (border excluded) or to the whole page if not specified.
getWheelDelta(<DOMEvent> ev)NumberGets normalized wheel delta from a mousewheel DOM event, in vertical +pixels scrolled (negative if scrolling down). +Events from pointing devices without precise scrolling are mapped to +a best guess of 60 pixels.
addListener()thisAlias to L.DomEvent.on
removeListener()thisAlias to L.DomEvent.off
+ +
+ + +

DomUtil

Utility functions to work with the DOM +tree, used by Leaflet internally. +Most functions expecting or returning a HTMLElement also work for +SVG elements. The only difference is that classes refer to CSS classes +in HTML and SVG classes in SVG.

+ +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
get(<String|HTMLElement> id)HTMLElementReturns an element given its DOM id, or returns the element itself +if it was passed directly.
getStyle(<HTMLElement> el, <String> styleAttrib)StringReturns the value for a certain style attribute on an element, +including computed values or values set through CSS.
create(<String> tagName, <String> className?, <HTMLElement> container?)HTMLElementCreates an HTML element with tagName, sets its class to className, and optionally appends it to container element.
remove(<HTMLElement> el)Removes el from its parent element
empty(<HTMLElement> el)Removes all of el's children elements from el
toFront(<HTMLElement> el)Makes el the last child of its parent, so it renders in front of the other children.
toBack(<HTMLElement> el)Makes el the first child of its parent, so it renders behind the other children.
hasClass(<HTMLElement> el, <String> name)BooleanReturns true if the element's class attribute contains name.
addClass(<HTMLElement> el, <String> name)Adds name to the element's class attribute.
removeClass(<HTMLElement> el, <String> name)Removes name from the element's class attribute.
setClass(<HTMLElement> el, <String> name)Sets the element's class.
getClass(<HTMLElement> el)StringReturns the element's class.
setOpacity(<HTMLElement> el, <Number> opacity)Set the opacity of an element (including old IE support). +opacity must be a number from 0 to 1.
testProp(<String[]> props)String|falseGoes through the array of style names and returns the first name +that is a valid style name for an element. If no such name is found, +it returns false. Useful for vendor-prefixed styles like transform.
setTransform(<HTMLElement> el, <Point> offset, <Number> scale?)Resets the 3D CSS transform of el so it is translated by offset pixels +and optionally scaled by scale. Does not have an effect if the +browser doesn't support 3D CSS transforms.
setPosition(<HTMLElement> el, <Point> position)Sets the position of el to coordinates specified by position, +using CSS translate or top/left positioning depending on the browser +(used by Leaflet internally to position its layers).
getPosition(<HTMLElement> el)PointReturns the coordinates of an element previously positioned with setPosition.
disableTextSelection()Prevents the user from generating selectstart DOM events, usually generated +when the user drags the mouse through a page with text. Used internally +by Leaflet to override the behaviour of any click-and-drag interaction on +the map. Affects drag interactions on the whole document.
enableTextSelection()Cancels the effects of a previous L.DomUtil.disableTextSelection.
disableImageDrag()As L.DomUtil.disableTextSelection, but +for dragstart DOM events, usually generated when the user drags an image.
enableImageDrag()Cancels the effects of a previous L.DomUtil.disableImageDrag.
preventOutline(<HTMLElement> el)Makes the outline +of the element el invisible. Used internally by Leaflet to prevent +focusable elements from displaying an outline when the user performs a +drag interaction on them.
restoreOutline()Cancels the effects of a previous L.DomUtil.preventOutline.
getSizedParentNode(<HTMLElement> el)HTMLElementFinds the closest parent node which size (width and height) is not null.
getScale(<HTMLElement> el)ObjectComputes the CSS scale currently applied on the element. +Returns an object with x and y members as horizontal and vertical scales respectively, +and boundingClientRect as the result of getBoundingClientRect().
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
TRANSFORM + StringVendor-prefixed transform style name (e.g. 'webkitTransform' for WebKit).
TRANSITION + StringVendor-prefixed transition style name.
TRANSITION_END + StringVendor-prefixed transitionend event name.
+ +
+ + +

PosAnimation

Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.

+ +
+

Usage example

+ +
+ + + + + +
var fx = new L.PosAnimation();
+fx.run(el, [300, 500], 0.5);
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.PosAnimation()Creates a PosAnimation object.
+ + +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
start + EventFired when the animation starts
step + EventFired continuously during the animation.
end + EventFired when the animation ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
run(<HTMLElement> el, <Point> newPos, <Number> duration?, <Number> easeLinearity?)

Run an animation of a given element to a new position, optionally setting +duration in seconds (0.25 by default) and easing linearity factor (3rd +argument of the cubic bezier curve, +0.5 by default).

+
stop()

Stops the animation (if currently running).

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Draggable

A class for making DOM elements draggable (including touch support). +Used internally for map and marker dragging. Only works for elements +that were positioned with L.DomUtil.setPosition.

+ +
+

Usage example

+ +
+ + + + + +
var draggable = new L.Draggable(elementToDrag);
+draggable.enable();
+
+ + + +
+ + +
+

Constructor

+ +
+ + + + + + + + + + + + + + +
ConstructorDescription
L.Draggable(<HTMLElement> el, <HTMLElement> dragHandle?, <Boolean> preventOutline?, <Draggable options> options?)Creates a Draggable object for moving el when you start dragging the dragHandle element (equals el itself by default).
+ + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
clickToleranceNumber + 3The max number of pixels a user can shift the mouse pointer during a click +for it to be considered a valid click (as opposed to a mouse drag).
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
down + EventFired when a drag is about to start.
dragstart + EventFired when a drag starts
predrag + EventFired continuously during dragging before each corresponding +update of the element's position.
drag + EventFired continuously during dragging.
dragend + DragEndEventFired when the drag ends.
+ +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()

Enables the dragging ability

+
disable()

Disables the dragging ability

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Class

L.Class powers the OOP facilities of Leaflet and is used to create almost all of the Leaflet classes documented here. +In addition to implementing a simple classical inheritance model, it introduces several special properties for convenient code organization — options, includes and statics.

+ +
+

Usage example

+ +
+ + + + + +
var MyClass = L.Class.extend({
+initialize: function (greeter) {
+    this.greeter = greeter;
+    // class constructor
+},
+greet: function (name) {
+    alert(this.greeter + ', ' + name)
+    }
+});
+// create instance of MyClass, passing "Hello" to the constructor
+var a = new MyClass("Hello");
+// call greet method, alerting "Hello, World"
+a.greet("World");
+
+ + + +
+ +

Class Factories

+ + + +

You may have noticed that Leaflet objects are created without using +the new keyword. This is achieved by complementing each class with a +lowercase factory method:

+
new L.Map('map'); // becomes:
+L.map('map');
+
+

The factories are implemented very easily, and you can do this for your own classes:

+
L.map = function (id, options) {
+    return new L.Map(id, options);
+};
+
+ + + +
+ +

Inheritance

+ + + +

You use L.Class.extend to define new classes, but you can use the same method on any class to inherit from it:

+
var MyChildClass = MyClass.extend({
+    // ... new properties and methods
+});
+
+

This will create a class that inherits all methods and properties of the parent class (through a proper prototype chain), adding or overriding the ones you pass to extend. It will also properly react to instanceof:

+
var a = new MyChildClass();
+a instanceof MyChildClass; // true
+a instanceof MyClass; // true
+
+

You can call parent methods (including constructor) from corresponding child ones (as you do with super calls in other languages) by accessing parent class prototype and using JavaScript's call or apply:

+
var MyChildClass = MyClass.extend({
+    initialize: function () {
+        MyClass.prototype.initialize.call(this, "Yo");
+    },
+    greet: function (name) {
+        MyClass.prototype.greet.call(this, 'bro ' + name + '!');
+    }
+});
+var a = new MyChildClass();
+a.greet('Jason'); // alerts "Yo, bro Jason!"
+
+ + +
+ +

Options

+ + + +

options is a special property that unlike other objects that you pass +to extend will be merged with the parent one instead of overriding it +completely, which makes managing configuration of objects and default +values convenient:

+
var MyClass = L.Class.extend({
+    options: {
+        myOption1: 'foo',
+        myOption2: 'bar'
+    }
+});
+var MyChildClass = MyClass.extend({
+    options: {
+        myOption1: 'baz',
+        myOption3: 5
+    }
+});
+var a = new MyChildClass();
+a.options.myOption1; // 'baz'
+a.options.myOption2; // 'bar'
+a.options.myOption3; // 5
+
+

There's also L.Util.setOptions, a method for +conveniently merging options passed to constructor with the defaults +defines in the class:

+
var MyClass = L.Class.extend({
+    options: {
+        foo: 'bar',
+        bla: 5
+    },
+    initialize: function (options) {
+        L.Util.setOptions(this, options);
+        ...
+    }
+});
+var a = new MyClass({bla: 10});
+a.options; // {foo: 'bar', bla: 10}
+
+

Note that the options object allows any keys, not just +the options defined by the class and its base classes. +This means you can use the options object to store +application specific information, as long as you avoid +keys that are already used by the class in question.

+ + + +
+ +

Includes

+ + + +

includes is a special class property that merges all specified objects into the class (such objects are called mixins).

+
 var MyMixin = {
+    foo: function () { ... },
+    bar: 5
+};
+var MyClass = L.Class.extend({
+    includes: MyMixin
+});
+var a = new MyClass();
+a.foo();
+
+

You can also do such includes in runtime with the include method:

+
MyClass.include(MyMixin);
+
+

statics is just a convenience property that injects specified object properties as the static properties of the class, useful for defining constants:

+
var MyClass = L.Class.extend({
+    statics: {
+        FOO: 'bar',
+        BLA: 5
+    }
+});
+MyClass.FOO; // 'bar'
+
+ + + +
+ +

Constructor hooks

+ + + +

If you're a plugin developer, you often need to add additional initialization code to existing classes (e.g. editing hooks for L.Polyline). Leaflet comes with a way to do it easily using the addInitHook method:

+
MyClass.addInitHook(function () {
+    // ... do something in constructor additionally
+    // e.g. add event listeners, set custom properties etc.
+});
+
+

You can also use the following shortcut when you just need to make one additional method call:

+
MyClass.addInitHook('methodName', arg1, arg2, …);
+
+ + + +
+ + +
+

Functions

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionReturnsDescription
extend(<Object> props)FunctionExtends the current class given the properties to be included. +Returns a Javascript function that is a class constructor (to be called with new).
include(<Object> properties)thisIncludes a mixin into the current class.
mergeOptions(<Object> options)thisMerges options into the defaults of the class.
addInitHook(<Function> fn)thisAdds a constructor hook to the class.
+ +
+ + +

Evented

A set of methods shared between event-powered classes (like Map and Marker). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire 'click' event).

+ +
+

Usage example

+ +
+ + + + + +
map.on('click', function(e) {
+    alert(e.latlng);
+} );
+
+

Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:

+
function onClick(e) { ... }
+map.on('click', onClick);
+map.off('click', onClick);
+
+ + + +
+ + +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+ + +

Layer

A set of methods from the Layer base class that all Leaflet layers use. +Inherits all methods, options and events from L.Evented.

+ +
+

Usage example

+ +
+ + + + + +
var layer = L.Marker(latlng).addTo(map);
+layer.addTo(map);
+layer.remove();
+
+ + + +
+ + +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+ + +
+

Events

+ +
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+ +

Popup events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+ +

Tooltip events

+ + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Layer will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+ +

Extension methods

+ +
Every layer should extend from L.Layer and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)this

Should contain code that creates DOM elements for the layer, adds them to map panes where they should belong and puts listeners on relevant map events. Called on map.addLayer(layer).

+
onRemove(<Map> map)this

Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in onAdd. Called on map.removeLayer(layer).

+
getEvents()Object

This optional method should return an object like { viewreset: this._reset } for addEventListener. The event handlers in this object will be automatically added and removed from the map with your layer.

+
getAttribution()String

This optional method should return a string containing HTML to be shown on the Attribution control whenever the layer is visible.

+
beforeAdd(<Map> map)this

Optional method. Called on map.addLayer(layer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.

+
+ +
+ +

Popup methods

+ +
All layers share a set of methods convenient for binding popups to it. +
var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);
+layer.openPopup();
+layer.closePopup();
+
+

Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+ +

Tooltip methods

+ +
All layers share a set of methods convenient for binding tooltips to it. +
var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);
+layer.openTooltip();
+layer.closeTooltip();
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Interactive layer

Some Layers can be made interactive - when the user interacts +with such a layer, mouse events like click and mouseover can be handled. +Use the event handling methods to handle these events.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
interactiveBoolean + trueIf false, the layer will not emit mouse events and will act as a part of the underlying map.
bubblingMouseEventsBoolean + trueWhen true, a mouse event on this layer will trigger the same event on the map +(unless L.DomEvent.stopPropagation is used).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ +

Mouse events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EventDataDescription
click + MouseEventFired when the user clicks (or taps) the layer.
dblclick + MouseEventFired when the user double-clicks (or double-taps) the layer.
mousedown + MouseEventFired when the user pushes the mouse button on the layer.
mouseup + MouseEventFired when the user releases the mouse button pushed on the layer.
mouseover + MouseEventFired when the mouse enters the layer.
mouseout + MouseEventFired when the mouse leaves the layer.
contextmenu + MouseEventFired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Control

L.Control is a base class for implementing map controls. Handles positioning. +All other controls extend from this class.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
positionString + 'topright'The position of the control (one of the map corners). Possible values are 'topleft', +'topright', 'bottomleft' or 'bottomright'
+ +
+ + +
+

Methods

+ +
+ + + +
Classes extending L.Control will inherit the following methods:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
getPosition()string

Returns the position of the control.

+
setPosition(<string> position)this

Sets the position of the control.

+
getContainer()HTMLElement

Returns the HTMLElement that contains the control.

+
addTo(<Map> map)this

Adds the control to the given map.

+
remove()this

Removes the control from the map it is currently active on.

+
+ +
+ +

Extension methods

+ +
Every control should extend from L.Control and (re-)implement the following methods.
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
onAdd(<Map> map)HTMLElement

Should return the container DOM element for the control and add listeners on relevant map events. Called on control.addTo(map).

+
onRemove(<Map> map)

Optional method. Should contain all clean up code that removes the listeners previously added in onAdd. Called on control.remove().

+
+ +
+ + +

Handler

Abstract class for map interaction handlers

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
enable()this

Enables the handler

+
disable()this

Disables the handler

+
enabled()Boolean

Returns true if the handler is enabled

+
+ +
+ +

Extension methods

+ +
Classes inheriting from Handler must implement the two following methods:
+ + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addHooks()

Called when the handler is enabled, should add event hooks.

+
removeHooks()

Called when the handler is disabled, should remove the event hooks added previously.

+
+ +
+ + +
+

Functions

+ +
+ +

There is static function which can be called without instantiating L.Handler:

+ + + + + + + + + + + + + + +
FunctionReturnsDescription
addTo(<Map> map, <String> name)thisAdds a new Handler to the given map with the given name.
+ +
+ + +

Projection

An object with methods for projecting geographical coordinates of the world onto +a flat surface (and back). See Map projection.

+ +
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
project(<LatLng> latlng)Point

Projects geographical coordinates into a 2D point. +Only accepts actual L.LatLng instances, not arrays.

+
unproject(<Point> point)LatLng

The inverse of project. Projects a 2D point into a geographical location. +Only accepts actual L.Point instances, not arrays. +Note that the projection instances do not inherit from Leafet's Class object, +and can't be instantiated. Also, new classes can't inherit from them, +and methods can't be added to them with the include function.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
bounds + BoundsThe bounds (specified in CRS units) where the projection is valid
+ +
+ + +
+

Defined projections

+ +
+ + + +
Leaflet comes with a set of already defined Projections out of the box:
+ + + + + + + + + + + + + + + + + + + +
ProjectionDescription
L.Projection.LonLatEquirectangular, or Plate Carree projection — the most simple projection, +mostly used by GIS enthusiasts. Directly maps x as longitude, and y as +latitude. Also suitable for flat worlds, e.g. game maps. Used by the +EPSG:4326 and Simple CRS.
L.Projection.MercatorElliptical Mercator projection — more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS.
L.Projection.SphericalMercatorSpherical Mercator projection — the most common projection for online maps, +used by almost all free and commercial tile providers. Assumes that Earth is +a sphere. Used by the EPSG:3857 CRS.
+ +
+ + +

CRS

+
+

Methods

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
latLngToPoint(<LatLng> latlng, <Number> zoom)Point

Projects geographical coordinates into pixel coordinates for a given zoom.

+
pointToLatLng(<Point> point, <Number> zoom)LatLng

The inverse of latLngToPoint. Projects pixel coordinates on a given +zoom into geographical coordinates.

+
project(<LatLng> latlng)Point

Projects geographical coordinates into coordinates in units accepted for +this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).

+
unproject(<Point> point)LatLng

Given a projected coordinate returns the corresponding LatLng. +The inverse of project.

+
scale(<Number> zoom)Number

Returns the scale used when transforming projected coordinates into +pixel coordinates for a particular zoom. For example, it returns +256 * 2^zoom for Mercator-based CRS.

+
zoom(<Number> scale)Number

Inverse of scale(), returns the zoom level corresponding to a scale +factor of scale.

+
getProjectedBounds(<Number> zoom)Bounds

Returns the projection's bounds scaled and transformed for the provided zoom.

+
distance(<LatLng> latlng1, <LatLng> latlng2)Number

Returns the distance between two geographical coordinates.

+
wrapLatLng(<LatLng> latlng)LatLng

Returns a LatLng where lat and lng has been wrapped according to the +CRS's wrapLat and wrapLng properties, if they are outside the CRS's bounds.

+
wrapLatLngBounds(<LatLngBounds> bounds)LatLngBounds

Returns a LatLngBounds with the same size as the given one, ensuring +that its center is within the CRS's bounds. +Only accepts actual L.LatLngBounds instances, not arrays.

+
+ +
+ + +
+

Properties

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
code + StringStandard code name of the CRS passed into WMS services (e.g. 'EPSG:3857')
wrapLng + Number[]An array of two numbers defining whether the longitude (horizontal) coordinate +axis wraps around a given range and how. Defaults to [-180, 180] in most +geographical CRSs. If undefined, the longitude axis does not wrap around.
wrapLat + Number[]Like wrapLng, but for the latitude (vertical) axis.
infinite + BooleanIf true, the coordinate space will be unbounded (infinite in both axes)
+ +
+ + +
+

Defined CRSs

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CRSDescription
L.CRS.EarthServes as the base for CRS that are global such that they cover the earth. +Can only be used as the base for other CRS and cannot be used directly, +since it does not have a code, projection or transformation. distance() returns +meters.
L.CRS.EPSG3395Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.
L.CRS.EPSG3857The most common CRS for online maps, used by almost all free and commercial +tile providers. Uses Spherical Mercator projection. Set in by default in +Map's crs option.
L.CRS.EPSG4326A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. +Leaflet 1.0.x complies with the TMS coordinate scheme for EPSG:4326, +which is a breaking change from 0.7.x behaviour. If you are using a TileLayer +with this CRS, ensure that there are two 256x256 pixel tiles covering the +whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), +or (-180,-90) for TileLayers with the tms option set.
L.CRS.BaseObject that defines coordinate reference systems for projecting +geographical points into pixel (screen) coordinates and back (and to +coordinates in other units for WMS services). See +spatial reference system. +Leaflet defines the most usual CRSs by default. If you want to use a +CRS not defined by default, take a look at the +Proj4Leaflet plugin. +Note that the CRS instances do not inherit from Leafet's Class object, +and can't be instantiated. Also, new classes can't inherit from them, +and methods can't be added to them with the include function.
L.CRS.SimpleA simple CRS that maps longitude and latitude into x and y directly. +May be used for maps of flat surfaces (e.g. game maps). Note that the y +axis should still be inverted (going from bottom to top). distance() returns +simple euclidean distance.
+ +
+ + +

Renderer

Base class for vector renderer implementations (SVG, Canvas). Handles the +DOM container of the renderer, its bounds, and its zoom animation. +A Renderer works as an implicit layer group for all Paths - the renderer +itself can be added or removed to the map. All paths use a renderer, which can +be implicit (the map will decide the type of renderer and use it automatically) +or explicit (using the renderer option of the path). +Do not use this class directly, use SVG and Canvas instead.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paddingNumber + 0.1How much to extend the clip area around the map view (relative to its size) +e.g. 0.1 would be 10% of map view in each direction
toleranceNumber + 0How much to extend click tolerance round a path/object on the map
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
paneString + 'overlayPane'By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ +
+ + + + + + + + + + + + + + + +
EventDataDescription
update + EventFired when the renderer updates its bounds, center and zoom, for example when +its map has moved
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Event objects

Whenever a class inheriting from Evented fires an event, a listener function +will be called with an event argument, which is a plain object containing +information about the event. For example:

+
map.on('click', function(ev) {
+    alert(ev.latlng); // ev is an event object (MouseEvent in this case)
+});
+
+

The information available depends on the event type:

+ + + +
+

Event

+ +
+ + + +
The base event object. All other event objects contain these properties too.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+ + +
+ +
+

KeyboardEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
originalEvent + DOMEventThe original DOM KeyboardEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

MouseEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngThe geographical point where the mouse event occured.
layerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map layer.
containerPoint + PointPixel coordinates of the point where the mouse event occured relative to the map сontainer.
originalEvent + DOMEventThe original DOM MouseEvent or DOM TouchEvent that triggered this Leaflet event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

LocationEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
latlng + LatLngDetected geographical location of the user.
bounds + LatLngBoundsGeographical bounds of the area user is located in (with respect to the accuracy of location).
accuracy + NumberAccuracy of location in meters.
altitude + NumberHeight of the position above the WGS84 ellipsoid in meters.
altitudeAccuracy + NumberAccuracy of altitude in meters.
heading + NumberThe direction of travel in degrees counting clockwise from true North.
speed + NumberCurrent velocity in meters per second.
timestamp + NumberThe time when the position was acquired.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
message + StringError message.
code + NumberError code (if applicable).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

LayerEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

LayersControlEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer that was added or removed.
name + StringThe name of the layer that was added or removed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

TileEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

TileErrorEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
tile + HTMLElementThe tile element (image).
coords + PointPoint object with the tile's x, y, and z (zoom level) coordinates.
error + *Error passed to the tile's done() callback.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ResizeEvent

+ +
+ + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
oldSize + PointThe old size before resize event.
newSize + PointThe new size after the resize event.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

GeoJSONEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
layer + LayerThe layer for the GeoJSON feature that is being added to the map.
properties + ObjectGeoJSON properties of the feature.
geometryType + StringGeoJSON geometry type of the feature.
id + StringGeoJSON ID of the feature (if present).
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
+ +
+
+
+ +
+ +
+

PopupEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
popup + PopupThe popup that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

TooltipEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
tooltip + TooltipThe tooltip that was opened or closed.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

DragEndEvent

+ +
+ + + + + + + + + + + + + + + +
PropertyTypeDescription
distance + NumberThe distance in pixels the draggable element was moved by.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +
+ +
+

ZoomAnimEvent

+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
center + LatLngThe current center of the map
zoom + NumberThe current zoom level of the map
noUpdate + BooleanWhether layers should update their contents due to this event
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PropertyTypeDescription
type + StringThe event type (e.g. 'click').
target + ObjectThe object that fired the event. For propagated events, the last object in +the propagation chain that fired the event.
sourceTarget + ObjectThe object that originally fired the event. For non-propagated events, this will +be the same as the target.
propagatedFrom + ObjectFor propagated events, the last object that propagated the event to its +event parent.
layer + ObjectDeprecated. The same as propagatedFrom.
+ +
+
+
+ +

DivOverlay

Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins.

+ +
+

Options

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
offsetPoint + Point(0, 7)The offset of the popup position. Useful to control the anchor +of the popup when opening it on some overlays.
classNameString + ''A custom CSS class name to assign to the popup.
paneString + 'popupPane'Map pane where the popup will be added.
+ +
+ + +
+ +
+
+ + + + + + + + + + + + + + + + + +
OptionTypeDefaultDescription
attributionString + nullString to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".
+ +
+
+
+ +
+

Events

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
add + EventFired after the layer is added to a map
remove + EventFired after the layer is removed from a map
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
popupopen + PopupEventFired when a popup bound to this layer is opened
popupclose + PopupEventFired when a popup bound to this layer is closed
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
EventDataDescription
tooltipopen + TooltipEventFired when a tooltip bound to this layer is opened.
tooltipclose + TooltipEventFired when a tooltip bound to this layer is closed.
+ +
+
+
+ +
+

Methods

+ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
addTo(<Map|LayerGroup> map)this

Adds the layer to the given map or layer group.

+
remove()this

Removes the layer from the map it is currently active on.

+
removeFrom(<Map> map)this

Removes the layer from the given map

+
getPane(<String> name?)HTMLElement

Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

+
getAttribution()String

Used by the attribution control, returns the attribution option.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindPopup(<String|HTMLElement|Function|Popup> content, <Popup options> options?)this

Binds a popup to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindPopup()this

Removes the popup previously bound with bindPopup.

+
openPopup(<LatLng> latlng?)this

Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

+
closePopup()this

Closes the popup bound to this layer if it is open.

+
togglePopup()this

Opens or closes the popup bound to this layer depending on its current state.

+
isPopupOpen()boolean

Returns true if the popup bound to this layer is currently open.

+
setPopupContent(<String|HTMLElement|Popup> content)this

Sets the content of the popup bound to this layer.

+
getPopup()Popup

Returns the popup bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
bindTooltip(<String|HTMLElement|Function|Tooltip> content, <Tooltip options> options?)this

Binds a tooltip to the layer with the passed content and sets up the +necessary event listeners. If a Function is passed it will receive +the layer as the first argument and should return a String or HTMLElement.

+
unbindTooltip()this

Removes the tooltip previously bound with bindTooltip.

+
openTooltip(<LatLng> latlng?)this

Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

+
closeTooltip()this

Closes the tooltip bound to this layer if it is open.

+
toggleTooltip()this

Opens or closes the tooltip bound to this layer depending on its current state.

+
isTooltipOpen()boolean

Returns true if the tooltip bound to this layer is currently open.

+
setTooltipContent(<String|HTMLElement|Tooltip> content)this

Sets the content of the tooltip bound to this layer.

+
getTooltip()Tooltip

Returns the tooltip bound to this layer.

+
+ +
+
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodReturnsDescription
on(<String> type, <Function> fn, <Object> context?)this

Adds a listener function (fn) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick').

+
on(<Object> eventMap)this

Adds a set of type/listener pairs, e.g. {click: onClick, mousemove: onMouseMove}

+
off(<String> type, <Function> fn?, <Object> context?)this

Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on, you must pass the same context to off in order to remove the listener.

+
off(<Object> eventMap)this

Removes a set of type/listener pairs.

+
off()this

Removes all listeners to all events on the object.

+
fire(<String> type, <Object> data?, <Boolean> propagate?)this

Fires an event of the specified type. You can optionally provide an data +object — the first argument of the listener function will contain its +properties. The event can optionally be propagated to event parents.

+
listens(<String> type)Boolean

Returns true if a particular event type has any listeners attached to it.

+
once()this

Behaves as on(…), except the listener will only get fired once and then removed.

+
addEventParent(<Evented> obj)this

Adds an event parent - an Evented that will receive propagated events

+
removeEventParent(<Evented> obj)this

Removes an event parent, so it will stop receiving propagated events

+
addEventListener()this

Alias to on(…)

+
removeEventListener()this

Alias to off(…)

+
clearAllEventListeners()this

Alias to off()

+
addOneTimeEventListener()this

Alias to once(…)

+
fireEvent()this

Alias to fire(…)

+
hasEventListeners()Boolean

Alias to listens(…)

+
+ +
+
+
+ +

Global Switches

Global switches are created for rare cases and generally make +Leaflet to not detect a particular browser feature even if it's +there. You need to set the switch as a global variable to true +before including Leaflet on the page, like this:

+
<script>L_NO_TOUCH = true;</script>
+<script src="leaflet.js"></script>
+
+ + + + + + + + + + + + + + + + + +
SwitchDescription
L_NO_TOUCHForces Leaflet to not use touch events even if it detects them.
L_DISABLE_3DForces Leaflet to not use hardware-accelerated CSS 3D transforms for positioning (which may cause glitches in some rare environments) even if they're supported.
+ +

noConflict

This method restores the L global variable to the original value +it had before Leaflet inclusion, and returns the real Leaflet +namespace so you can put it elsewhere, like this:

+
<script src='libs/l.js'>
+<!-- L points to some other library -->
+<script src='leaflet.js'>
+<!-- you include Leaflet, it replaces the L variable to Leaflet namespace -->
+<script>
+var Leaflet = L.noConflict();
+// now L points to that other library again, and you can use Leaflet.Map etc.
+</script>
+
+ +

version

A constant that represents the Leaflet version in use.

+
L.version; // contains "1.0.0" (or whatever version is currently in use)
+
+ + + + + + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-tpl.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-tpl.html new file mode 100644 index 000000000..8c789bf70 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-tpl.html @@ -0,0 +1,89 @@ + + + + +<Foo> name + + + + +

[class-name]

+ +

[description]

+ +
[code-example]
+ + + + +

Constructor

+ + + + + + + + + + + + +
ConstructorUsageDescription
[constructor]( [arguments] ) + new L.Map()
+ L.map() +
[description]
+ + + + +

Methods

+ + + + + + + + + + + +
MethodReturnsDescription
[method](<type> argument, <type> argument)[return-type][description]
+ + + + +

Options

+ + + + + + + + + + + + + + +
OptionTypeDefault valueDescription
[name][type][default][description]
+ + + +

Events

+ + + + + + + + + + + + +
EventDataDescription
[name][type][description]
diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-versions.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-versions.html new file mode 100644 index 000000000..a135deda9 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference-versions.html @@ -0,0 +1,21 @@ +--- +layout: v2 +title: Documentation +bodyclass: api-page +--- + +

Available API References

+ +

This page lists the API references for several Leaflet versions.

+ +

diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference.html b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference.html new file mode 100644 index 000000000..ea4e99bf1 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/docs/reference.html @@ -0,0 +1,4 @@ +--- +layout: redirected +redirect_to: reference-1.3.4.html +--- \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/package.json b/vendor/assets/javascripts/Leaflet-1.4.0/package.json new file mode 100644 index 000000000..c7159a539 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/package.json @@ -0,0 +1,104 @@ +{ + "name": "leaflet", + "version": "1.4.0", + "description": "JavaScript library for mobile-friendly interactive maps", + "devDependencies": { + "eslint": "^4.5.0", + "eslint-config-mourner": "^2.0.1", + "git-rev-sync": "^1.8.0", + "happen": "~0.3.2", + "karma": "^1.3.0", + "karma-chrome-launcher": "^2.0.0", + "karma-coverage": "~1.1.1", + "karma-expect": "^1.1.3", + "karma-firefox-launcher": "~1.0.0", + "karma-mocha": "^1.2.0", + "karma-phantomjs-launcher": "^1.0.2", + "karma-rollup-preprocessor": "^5.0.1", + "karma-safari-launcher": "~1.0.0", + "karma-sinon": "^1.0.5", + "leafdoc": "^1.4.1", + "mocha": "^3.1.0", + "phantomjs-prebuilt": "^2.1.12", + "prosthetic-hand": "^1.3.1", + "rollup": "^0.51.8", + "rollup-plugin-git-version": "0.2.1", + "rollup-plugin-json": "^2.1.0", + "rollup-watch": "^4.3.1", + "sinon": "^1.6.0", + "source-map": "^0.5.6", + "ssri": "^5.2.2", + "uglify-js": "~3.0.26" + }, + "main": "dist/leaflet-src.js", + "style": "dist/leaflet.css", + "files": [ + "dist", + "src", + "!dist/leaflet.zip" + ], + "scripts": { + "docs": "node ./build/docs.js", + "pretest": "npm run lint && npm run lint-spec", + "test": "npm run test-nolint", + "test-nolint": "karma start ./spec/karma.conf.js", + "build": "npm run rollup && npm run uglify", + "release": "./build/publish.sh", + "lint": "eslint src", + "lint-spec": "eslint spec/suites", + "lintfix": "eslint src --fix; eslint spec/suites --fix;", + "rollup": "rollup -c build/rollup-config.js", + "watch": "rollup -w -c build/rollup-watch-config.js", + "uglify": "uglifyjs dist/leaflet-src.js -c -m -o dist/leaflet.js --source-map filename=dist/leaflet.js.map --in-source-map dist/leaflet-src.js.map --source-map-url leaflet.js.map --comments", + "integrity": "node ./build/integrity.js" + }, + "eslintConfig": { + "root": true, + "globals": { + "L": true + }, + "env": { + "commonjs": true, + "amd": true, + "node": false + }, + "extends": "mourner", + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "rules": { + "linebreak-style": [ + 0, + "unix" + ], + "no-mixed-spaces-and-tabs": [ + 2, + "smart-tabs" + ], + "indent": [ + 2, + "tab", + { + "VariableDeclarator": 0, + "flatTernaryExpressions": true + } + ], + "curly": 2, + "spaced-comment": 2, + "strict": 0, + "wrap-iife": 0, + "key-spacing": 0, + "consistent-return": 0 + } + }, + "repository": { + "type": "git", + "url": "git://github.com/Leaflet/Leaflet.git" + }, + "keywords": [ + "gis", + "map" + ], + "license": "BSD-2-Clause" +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/.eslintrc b/vendor/assets/javascripts/Leaflet-1.4.0/spec/.eslintrc new file mode 100644 index 000000000..a30f63e55 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/.eslintrc @@ -0,0 +1,20 @@ +{ + "rules": { + "no-unused-vars": 0, + "quotes": 0, + "no-shadow": 0, + "no-irregular-whitespace": 0, + "no-console": 0, + "no-extend-native": 0 + }, + "env": { + "mocha": true + }, + "globals": { + "expect": false, + "sinon": false, + "happen": false, + "Hand": false, + "takeScreenshot" + } +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/after.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/after.js new file mode 100644 index 000000000..63bd3ea33 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/after.js @@ -0,0 +1 @@ +L.Icon.Default.imagePath = '/base/dist/images/'; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/index.html b/vendor/assets/javascripts/Leaflet-1.4.0/spec/index.html new file mode 100644 index 000000000..5ae402a26 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/index.html @@ -0,0 +1,105 @@ + + + + + Leaflet Spec Runner + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/karma.conf.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/karma.conf.js new file mode 100644 index 000000000..c74c211e2 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/karma.conf.js @@ -0,0 +1,126 @@ +var json = require('rollup-plugin-json'); + +const outro = `var oldL = window.L; +exports.noConflict = function() { + window.L = oldL; + return this; +} + +// Always export us to window global (see #2364) +window.L = exports;`; + +// Karma configuration +module.exports = function (config) { + +// var libSources = require(__dirname + '/../build/build.js').getFiles(); + + var files = [ + "src/Leaflet.js", + "spec/after.js", + "node_modules/happen/happen.js", + "node_modules/prosthetic-hand/dist/prosthetic-hand.js", + "spec/suites/SpecHelper.js", + "spec/suites/**/*.js", + "dist/*.css", + {pattern: "dist/images/*.png", included: false, serve: true} + ]; + + var preprocessors = {}; + + if (config.cov) { + preprocessors['src/**/*.js'] = ['coverage']; + } + + preprocessors['src/Leaflet.js'] = ['rollup']; + + config.set({ + // base path, that will be used to resolve files and exclude + basePath: '../', + + plugins: [ + 'karma-rollup-preprocessor', + 'karma-mocha', + 'karma-sinon', + 'karma-expect', + 'karma-coverage', + 'karma-phantomjs-launcher', + 'karma-chrome-launcher', + 'karma-safari-launcher', + 'karma-firefox-launcher'], + + // frameworks to use + frameworks: ['mocha', 'sinon', 'expect'], + + // list of files / patterns to load in the browser + files: files, + proxies: { + '/base/dist/images/': 'dist/images/' + }, + exclude: [], + + // Rollup the ES6 Leaflet sources into just one file, before tests + preprocessors: preprocessors, + rollupPreprocessor: { + plugins: [ + json() + ], + format: 'umd', + name: 'L', + outro: outro + }, + + // test results reporter to use + // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' + reporters: config.cov ? ['dots', 'coverage'] : ['dots'], + + coverageReporter: config.cov ? {type : 'html', dir : 'coverage/'} : null, + + // web server port + port: 9876, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_WARN, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + // Start these browsers, currently available: + // - Chrome + // - ChromeCanary + // - Firefox + // - Opera + // - Safari (only Mac) + // - PhantomJS + // - IE (only Windows) + browsers: ['PhantomJSCustom'], + + customLaunchers: { + 'PhantomJSCustom': { + base: 'PhantomJS', + flags: ['--load-images=true'], + options: { + onCallback: function (data) { + if (data.render) { + page.render(data.render); + } + } + } + } + }, + + // If browser does not capture in given timeout [ms], kill it + captureTimeout: 5000, + + // Workaround for PhantomJS random DISCONNECTED error + browserDisconnectTimeout: 10000, // default 2000 + browserDisconnectTolerance: 1, // default 0 + + // Continuous Integration mode + // if true, it capture browsers, run tests and exit + singleRun: true + }); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/SpecHelper.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/SpecHelper.js new file mode 100644 index 000000000..900757c06 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/SpecHelper.js @@ -0,0 +1,70 @@ +if (!Array.prototype.map) { + Array.prototype.map = function (fun) { + "use strict"; + + if (this === undefined || this === null) { + throw new TypeError(); + } + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") { + throw new TypeError(); + } + + var res = new Array(len); + var thisp = arguments[1]; + for (var i = 0; i < len; i++) { + if (i in t) { + res[i] = fun.call(thisp, t[i], i, t); + } + } + + return res; + }; +} + +expect.Assertion.prototype.near = function (expected, delta) { + delta = delta || 1; + expect(this.obj.x).to + .be.within(expected.x - delta, expected.x + delta); + expect(this.obj.y).to + .be.within(expected.y - delta, expected.y + delta); +}; + +expect.Assertion.prototype.nearLatLng = function (expected, delta) { + delta = delta || 1e-4; + expect(this.obj.lat).to + .be.within(expected.lat - delta, expected.lat + delta); + expect(this.obj.lng).to + .be.within(expected.lng - delta, expected.lng + delta); +}; + +happen.at = function (what, x, y, props) { + this.once(document.elementFromPoint(x, y), L.Util.extend({ + type: what, + clientX: x, + clientY: y, + screenX: x, + screenY: y, + which: 1, + button: 0 + }, props || {})); +}; + +// We'll want to skip a couple of things when in PhantomJS, due to lack of CSS animations +it.skipInPhantom = L.Browser.any3d ? it : it.skip; + +// Viceversa: some tests we want only to run in browsers without CSS animations. +it.skipInNonPhantom = L.Browser.any3d ? it.skip : it; + +// A couple of tests need the browser to be touch-capable +it.skipIfNotTouch = window.TouchEvent ? it : it.skip; + +// A couple of tests need the browser to be pointer-capable +it.skipIfNotEdge = window.PointerEvent ? it : it.skip; + + +function takeScreenshot(path) { + window.top.callPhantom({'render': path || 'screenshot.png'}); +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.AttributionSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.AttributionSpec.js new file mode 100644 index 000000000..c81303a16 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.AttributionSpec.js @@ -0,0 +1,126 @@ +describe("Control.Attribution", function () { + + var map, control, container; + + beforeEach(function () { + map = L.map(document.createElement('div')); + control = new L.Control.Attribution({ + prefix: 'prefix' + }).addTo(map); + map.setView([0, 0], 1); + container = control.getContainer(); + }); + + function dummyLayer() { + var layer = new L.Layer(); + layer.onAdd = function () { }; + layer.onRemove = function () { }; + return layer; + } + + it("contains just prefix if no attributions added", function () { + expect(container.innerHTML).to.eql('prefix'); + }); + + describe('#addAttribution', function () { + it('adds one attribution correctly', function () { + control.addAttribution('foo'); + expect(container.innerHTML).to.eql('prefix | foo'); + }); + + it('adds no duplicate attributions', function () { + control.addAttribution('foo'); + control.addAttribution('foo'); + expect(container.innerHTML).to.eql('prefix | foo'); + }); + + it('adds several attributions listed with comma', function () { + control.addAttribution('foo'); + control.addAttribution('bar'); + expect(container.innerHTML).to.eql('prefix | foo, bar'); + }); + }); + + describe('#removeAttribution', function () { + it('removes attribution correctly', function () { + control.addAttribution('foo'); + control.addAttribution('bar'); + control.removeAttribution('foo'); + expect(container.innerHTML).to.eql('prefix | bar'); + }); + it('does nothing if removing attribution that was not present', function () { + control.addAttribution('foo'); + control.addAttribution('baz'); + control.removeAttribution('bar'); + control.removeAttribution('baz'); + control.removeAttribution('baz'); + control.removeAttribution(''); + expect(container.innerHTML).to.eql('prefix | foo'); + }); + }); + + describe('#setPrefix', function () { + it('changes prefix', function () { + control.setPrefix('bla'); + expect(container.innerHTML).to.eql('bla'); + }); + }); + + describe('control.attribution factory', function () { + it('creates Control.Attribution instance', function () { + var options = {prefix: 'prefix'}; + expect(L.control.attribution(options)).to.eql(new L.Control.Attribution(options)); + }); + }); + + describe('on layer add/remove', function () { + it('changes text', function () { + var fooLayer = dummyLayer(); + var barLayer = dummyLayer(); + var bazLayer = dummyLayer(); + fooLayer.getAttribution = function () { return 'foo'; }; + barLayer.getAttribution = function () { return 'bar'; }; + bazLayer.getAttribution = function () { return 'baz'; }; + + expect(container.innerHTML).to.eql('prefix'); + map.addLayer(fooLayer); + expect(container.innerHTML).to.eql('prefix | foo'); + map.addLayer(barLayer); + expect(container.innerHTML).to.eql('prefix | foo, bar'); + map.addLayer(bazLayer); + expect(container.innerHTML).to.eql('prefix | foo, bar, baz'); + + map.removeLayer(fooLayer); + expect(container.innerHTML).to.eql('prefix | bar, baz'); + map.removeLayer(barLayer); + expect(container.innerHTML).to.eql('prefix | baz'); + map.removeLayer(bazLayer); + expect(container.innerHTML).to.eql('prefix'); + }); + + it('keeps count of duplicated attributions', function () { + var fooLayer = dummyLayer(); + var fo2Layer = dummyLayer(); + var fo3Layer = dummyLayer(); + fooLayer.getAttribution = function () { return 'foo'; }; + fo2Layer.getAttribution = function () { return 'foo'; }; + fo3Layer.getAttribution = function () { return 'foo'; }; + + expect(container.innerHTML).to.eql('prefix'); + map.addLayer(fooLayer); + expect(container.innerHTML).to.eql('prefix | foo'); + map.addLayer(fo2Layer); + expect(container.innerHTML).to.eql('prefix | foo'); + map.addLayer(fo3Layer); + expect(container.innerHTML).to.eql('prefix | foo'); + + map.removeLayer(fooLayer); + expect(container.innerHTML).to.eql('prefix | foo'); + map.removeLayer(fo2Layer); + expect(container.innerHTML).to.eql('prefix | foo'); + map.removeLayer(fo3Layer); + expect(container.innerHTML).to.eql('prefix'); + }); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.LayersSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.LayersSpec.js new file mode 100644 index 000000000..c1653aaca --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.LayersSpec.js @@ -0,0 +1,370 @@ +describe("Control.Layers", function () { + var map; + + beforeEach(function () { + map = L.map(document.createElement('div')); + }); + afterEach(function () { + map.remove(); + }); + + describe("baselayerchange event", function () { + beforeEach(function () { + map.setView([0, 0], 14); + }); + + it("is fired on input that changes the base layer", function () { + var baseLayers = {"Layer 1": L.tileLayer(''), "Layer 2": L.tileLayer('')}, + layers = L.control.layers(baseLayers).addTo(map), + spy = sinon.spy(); + + map.on('baselayerchange', spy); + happen.click(layers._baseLayersList.getElementsByTagName("input")[0]); + expect(spy.called).to.be.ok(); + expect(spy.args[0][0].name).to.be("Layer 1"); + expect(spy.args[0][0].layer).to.be(baseLayers["Layer 1"]); + happen.click(layers._baseLayersList.getElementsByTagName("input")[1]); + expect(spy.calledTwice).to.be.ok(); + expect(spy.args[1][0].name).to.be("Layer 2"); + expect(spy.args[1][0].layer).to.be(baseLayers["Layer 2"]); + }); + + it("works after removing and readding the Control.Layers to the map", function () { + var baseLayers = {"Layer 1": L.tileLayer(''), "Layer 2": L.tileLayer('')}, + layers = L.control.layers(baseLayers).addTo(map), + spy = sinon.spy(); + + map.on('baselayerchange', spy); + + map.removeControl(layers); + map.addControl(layers); + + happen.click(layers._baseLayersList.getElementsByTagName("input")[0]); + expect(spy.called).to.be.ok(); + expect(spy.args[0][0].name).to.be("Layer 1"); + expect(spy.args[0][0].layer).to.be(baseLayers["Layer 1"]); + happen.click(layers._baseLayersList.getElementsByTagName("input")[1]); + expect(spy.calledTwice).to.be.ok(); + expect(spy.args[1][0].name).to.be("Layer 2"); + expect(spy.args[1][0].layer).to.be(baseLayers["Layer 2"]); + }); + + it("is not fired on input that doesn't change the base layer", function () { + var overlays = {"Marker 1": L.marker([0, 0]), "Marker 2": L.marker([0, 0])}, + layers = L.control.layers({}, overlays).addTo(map), + spy = sinon.spy(); + + map.on('baselayerchange', spy); + happen.click(layers._overlaysList.getElementsByTagName("input")[0]); + + expect(spy.called).to.not.be.ok(); + }); + }); + + describe("updates", function () { + beforeEach(function () { + map.setView([0, 0], 14); + }); + + it("when an included layer is added or removed from the map", function () { + var baseLayer = L.tileLayer(), + overlay = L.marker([0, 0]), + layers = L.control.layers({"Base": baseLayer}, {"Overlay": overlay}).addTo(map); + + var spy = sinon.spy(layers, '_update'); + + map.addLayer(overlay); + map.removeLayer(overlay); + + expect(spy.called).to.be.ok(); + expect(spy.callCount).to.eql(2); + }); + + it("when an included layer is added or removed from the map, it's (un)checked", function () { + document.body.appendChild(map._container); + var baseLayer = L.tileLayer(), + overlay = L.marker([0, 0]), + layers = L.control.layers({"Baselayer": baseLayer}, {"Overlay": overlay}).addTo(map); + + function isChecked() { + return !!(map._container.querySelector('.leaflet-control-layers-overlays input').checked); + } + + expect(isChecked()).to.not.be.ok(); + map.addLayer(overlay); + expect(isChecked()).to.be.ok(); + map.removeLayer(overlay); + expect(isChecked()).to.not.be.ok(); + }); + + it("not when a non-included layer is added or removed", function () { + var baseLayer = L.tileLayer(), + overlay = L.marker([0, 0]), + layers = L.control.layers({"Base": baseLayer}).addTo(map); + + var spy = sinon.spy(layers, '_update'); + + map.addLayer(overlay); + map.removeLayer(overlay); + + expect(spy.called).to.not.be.ok(); + }); + + it("updates when an included layer is removed from the control", function () { + document.body.appendChild(map._container); + var baseLayer = L.tileLayer(), + overlay = L.marker([0, 0]), + layers = L.control.layers({"Base": baseLayer}, {"Overlay": overlay}).addTo(map); + + layers.removeLayer(overlay); + expect(map._container.querySelector('.leaflet-control-layers-overlays').children.length) + .to.be.equal(0); + }); + + it('silently returns when trying to remove a non-existing layer from the control', function () { + var layers = L.control.layers({'base': L.tileLayer()}).addTo(map); + + expect(function () { + layers.removeLayer(L.marker([0, 0])); + }).to.not.throwException(); + + expect(layers._layers.length).to.be.equal(1); + }); + + it("having repeated layers works as expected", function () { + document.body.appendChild(map._container); + var layerA = L.tileLayer(''), layerB = L.tileLayer(''), + baseLayers = {"Layer 1": layerA, "Layer 2": layerB, "Layer 3": layerA}, + layers = L.control.layers(baseLayers).addTo(map); + + function checkInputs(idx) { + var inputs = map._container.querySelectorAll('.leaflet-control-layers-base input'); + for (var i = 0; i < inputs.length; i++) { + expect(inputs[i].checked === (idx === i)).to.be.ok(); + } + } + + happen.click(layers._baseLayersList.getElementsByTagName("input")[1]); + checkInputs(1); + expect(map._layers[L.Util.stamp(layerB)]).to.be.equal(layerB); + expect(map._layers[L.Util.stamp(layerA)]).to.be.equal(undefined); + happen.click(layers._baseLayersList.getElementsByTagName("input")[0]); + checkInputs(0); + expect(map._layers[L.Util.stamp(layerA)]).to.be.equal(layerA); + expect(map._layers[L.Util.stamp(layerB)]).to.be.equal(undefined); + happen.click(layers._baseLayersList.getElementsByTagName("input")[2]); + checkInputs(2); + expect(map._layers[L.Util.stamp(layerA)]).to.be.equal(layerA); + expect(map._layers[L.Util.stamp(layerB)]).to.be.equal(undefined); + }); + }); + + describe("is removed cleanly", function () { + beforeEach(function () { + map.setView([0, 0], 14); + }); + + it("and layers in the control can still be removed", function () { + var baseLayer = L.tileLayer('').addTo(map); + var layersCtrl = L.control.layers({'Base': baseLayer}).addTo(map); + map.removeControl(layersCtrl); + + expect(function () { + map.removeLayer(baseLayer); + }).to.not.throwException(); + }); + + it("and layers in the control can still be removed when added after removing control from map", function () { + var baseLayer = L.tileLayer('').addTo(map); + var layersCtrl = L.control.layers().addTo(map); + map.removeControl(layersCtrl); + layersCtrl.addBaseLayer(baseLayer, 'Base'); + + expect(function () { + map.removeLayer(baseLayer); + }).to.not.throwException(); + }); + }); + + describe("is created with an expand link", function () { + it("when collapsed", function () { + var layersCtrl = L.control.layers(null, null, {collapsed: true}).addTo(map); + expect(map._container.querySelector('.leaflet-control-layers-toggle')).to.be.ok(); + }); + + it("when not collapsed", function () { + var layersCtrl = L.control.layers(null, null, {collapsed: false}).addTo(map); + expect(map._container.querySelector('.leaflet-control-layers-toggle')).to.be.ok(); + }); + }); + + describe("collapse when collapsed: true", function () { + it('expands when mouse is over', function () { + var layersCtrl = L.control.layers(null, null, {collapsed: true}).addTo(map); + happen.once(layersCtrl._container, {type:'mouseover'}); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.be.ok(); + }); + it('collapses when mouse is out', function () { + var layersCtrl = L.control.layers(null, null, {collapsed: true}).addTo(map); + happen.once(layersCtrl._container, {type:'mouseover'}); + happen.once(layersCtrl._container, {type:'mouseout'}); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.not.be.ok(); + }); + it('collapses when map is clicked', function () { + var layersCtrl = L.control.layers(null, null, {collapsed: true}).addTo(map); + map.setView([0, 0], 0); + happen.once(layersCtrl._container, {type:'mouseover'}); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.be.ok(); + happen.click(map._container); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.not.be.ok(); + }); + }); + + describe("does not collapse when collapsed: false", function () { + it('does not collapse when mouse enters or leaves', function () { + var layersCtrl = L.control.layers(null, null, {collapsed: false}).addTo(map); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.be.ok(); + happen.once(layersCtrl._container, {type:'mouseover'}); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.be.ok(); + happen.once(layersCtrl._container, {type:'mouseout'}); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.be.ok(); + }); + it('does not collapse when map is clicked', function () { + var layersCtrl = L.control.layers(null, null, {collapsed: false}).addTo(map); + map.setView([0, 0], 0); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.be.ok(); + happen.click(map._container); + expect(map._container.querySelector('.leaflet-control-layers-expanded')).to.be.ok(); + }); + it('is scrollable if necessary when added on map', function () { + var layersCtrl = L.control.layers(null, null, {collapsed: false}), + div = document.createElement('div'), + i = 0; + + // Need to create a DIV with specified height and insert it into DOM, so that the browser + // gives it an actual size. + map.remove(); + div.style.height = div.style.width = '200px'; + document.body.appendChild(div); + map = L.map(div); + + for (; i < 20; i += 1) { + // Default text size: 12px => 12 * 20 = 240px height (not even considering padding/margin). + layersCtrl.addOverlay(L.marker([0, 0]), i); + } + + layersCtrl.addTo(map); + + expect(div.clientHeight).to.be.greaterThan(0); // Make sure first that the map container has a height, otherwise this test is useless. + expect(div.clientHeight).to.be.greaterThan(layersCtrl._container.clientHeight); + expect(layersCtrl._section.classList.contains('leaflet-control-layers-scrollbar')).to.be(true); + }); + it('becomes scrollable if necessary when too many layers are added while it is already on map', function () { + var layersCtrl = L.control.layers(null, null, {collapsed: false}), + div = document.createElement('div'), + i = 0; + + // Need to create a DIV with specified height and insert it into DOM, so that the browser + // gives it an actual size. + map.remove(); + div.style.height = div.style.width = '200px'; + document.body.appendChild(div); + map = L.map(div); + + layersCtrl.addTo(map); + expect(layersCtrl._section.classList.contains('leaflet-control-layers-scrollbar')).to.be(false); + + for (; i < 20; i += 1) { + // Default text size: 12px => 12 * 20 = 240px height (not even considering padding/margin). + layersCtrl.addOverlay(L.marker([0, 0]), i); + } + + expect(div.clientHeight).to.be.greaterThan(layersCtrl._container.clientHeight); + expect(layersCtrl._section.classList.contains('leaflet-control-layers-scrollbar')).to.be(true); + }); + }); + + describe("sortLayers", function () { + beforeEach(function () { + map.setView([0, 0], 14); + }); + + it("keeps original order by default", function () { + var baseLayerOne = L.tileLayer('').addTo(map); + var baseLayerTwo = L.tileLayer('').addTo(map); + var markerC = L.marker([0, 2]).addTo(map); + var markerB = L.marker([0, 1]).addTo(map); + var markerA = L.marker([0, 0]).addTo(map); + + var layersCtrl = L.control.layers({ + 'Base One': baseLayerOne, + 'Base Two': baseLayerTwo + }, { + 'Marker C': markerC, + 'Marker B': markerB, + 'Marker A': markerA + }).addTo(map); + + var elems = map.getContainer().querySelectorAll('div.leaflet-control-layers label span'); + expect(elems[0].innerHTML.trim()).to.be.equal('Base One'); + expect(elems[1].innerHTML.trim()).to.be.equal('Base Two'); + expect(elems[2].innerHTML.trim()).to.be.equal('Marker C'); + expect(elems[3].innerHTML.trim()).to.be.equal('Marker B'); + expect(elems[4].innerHTML.trim()).to.be.equal('Marker A'); + }); + + it("sorts alphabetically if no function is specified", function () { + var baseLayerOne = L.tileLayer('').addTo(map); + var baseLayerTwo = L.tileLayer('').addTo(map); + var markerA = L.marker([0, 0]).addTo(map); + var markerB = L.marker([0, 1]).addTo(map); + var markerC = L.marker([0, 2]).addTo(map); + + var layersCtrl = L.control.layers({ + 'Base Two': baseLayerTwo, + 'Base One': baseLayerOne + }, { + 'Marker A': markerA, + 'Marker C': markerC, + 'Marker B': markerB + }, { + sortLayers: true + }).addTo(map); + + var elems = map.getContainer().querySelectorAll('div.leaflet-control-layers label span'); + expect(elems[0].innerHTML.trim()).to.be.equal('Base One'); + expect(elems[1].innerHTML.trim()).to.be.equal('Base Two'); + expect(elems[2].innerHTML.trim()).to.be.equal('Marker A'); + expect(elems[3].innerHTML.trim()).to.be.equal('Marker B'); + expect(elems[4].innerHTML.trim()).to.be.equal('Marker C'); + }); + + it("uses the compare function to sort layers", function () { + var baseLayerOne = L.tileLayer('', {customOption: 999}).addTo(map); + var baseLayerTwo = L.tileLayer('', {customOption: 998}).addTo(map); + var markerA = L.marker([0, 0], {customOption: 102}).addTo(map); + var markerB = L.marker([0, 1], {customOption: 100}).addTo(map); + var markerC = L.marker([0, 2], {customOption: 101}).addTo(map); + + var layersCtrl = L.control.layers({ + 'Base One': baseLayerOne, + 'Base Two': baseLayerTwo + }, { + 'Marker A': markerA, + 'Marker B': markerB, + 'Marker C': markerC + }, { + sortLayers: true, + sortFunction: function (a, b) { return a.options.customOption - b.options.customOption; } + }).addTo(map); + + var elems = map.getContainer().querySelectorAll('div.leaflet-control-layers label span'); + expect(elems[0].innerHTML.trim()).to.be.equal('Base Two'); + expect(elems[1].innerHTML.trim()).to.be.equal('Base One'); + expect(elems[2].innerHTML.trim()).to.be.equal('Marker B'); + expect(elems[3].innerHTML.trim()).to.be.equal('Marker C'); + expect(elems[4].innerHTML.trim()).to.be.equal('Marker A'); + }); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.ScaleSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.ScaleSpec.js new file mode 100644 index 000000000..0981700fe --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/Control.ScaleSpec.js @@ -0,0 +1,6 @@ +describe("Control.Scale", function () { + it("can be added to an unloaded map", function () { + var map = L.map(document.createElement('div')); + new L.Control.Scale().addTo(map); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/ControlSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/ControlSpec.js new file mode 100644 index 000000000..6d2770b80 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/control/ControlSpec.js @@ -0,0 +1,51 @@ +describe("Control", function () { + var map; + + beforeEach(function () { + map = L.map(document.createElement('div')); + }); + + function onAdd() { + return L.DomUtil.create('div', 'leaflet-test-control'); + } + + describe("#addTo", function () { + it("adds the container to the map", function () { + var control = new L.Control(); + control.onAdd = onAdd; + control.addTo(map); + expect(map.getContainer().querySelector('.leaflet-test-control')).to.equal(control.getContainer()); + }); + + it("removes the control from any existing map", function () { + var control = new L.Control(); + control.onAdd = onAdd; + control.addTo(map); + control.addTo(map); + expect(map.getContainer().querySelectorAll('.leaflet-test-control').length).to.equal(1); + expect(map.getContainer().querySelector('.leaflet-test-control')).to.equal(control.getContainer()); + }); + }); + + describe("#remove", function () { + it("removes the container from the map", function () { + var control = new L.Control(); + control.onAdd = onAdd; + control.addTo(map).remove(); + expect(map.getContainer().querySelector('.leaflet-test-control')).to.equal(null); + }); + + it("calls onRemove if defined", function () { + var control = new L.Control(); + control.onAdd = onAdd; + control.onRemove = sinon.spy(); + control.addTo(map).remove(); + expect(control.onRemove.called).to.be(true); + }); + + it("is a no-op if the control has not been added", function () { + var control = new L.Control(); + expect(control.remove()).to.equal(control); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/ClassSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/ClassSpec.js new file mode 100644 index 000000000..e202a6b37 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/ClassSpec.js @@ -0,0 +1,200 @@ +describe("Class", function () { + + describe("#extend", function () { + var Klass, + constructor, + method; + + beforeEach(function () { + constructor = sinon.spy(); + method = sinon.spy(); + + Klass = L.Class.extend({ + statics: {bla: 1}, + includes: {mixin: true}, + + initialize: constructor, + foo: 5, + bar: method + }); + }); + + it("creates a class with the given constructor & properties", function () { + var a = new Klass(); + + expect(constructor.called).to.be.ok(); + expect(a.foo).to.eql(5); + + a.bar(); + + expect(method.called).to.be.ok(); + }); + + it("inherits parent classes' constructor & properties", function () { + var Klass2 = Klass.extend({baz: 2}); + + var b = new Klass2(); + + expect(b instanceof Klass).to.be.ok(); + expect(b instanceof Klass2).to.be.ok(); + + expect(constructor.called).to.be.ok(); + expect(b.baz).to.eql(2); + + b.bar(); + + expect(method.called).to.be.ok(); + }); + + it("supports static properties", function () { + expect(Klass.bla).to.eql(1); + }); + + it("inherits parent static properties", function () { + var Klass2 = Klass.extend({}); + + expect(Klass2.bla).to.eql(1); + }); + + it("overrides parent static properties", function () { + var Klass2 = Klass.extend({statics: {bla: 2}}); + + expect(Klass2.bla).to.eql(2); + }); + + it("includes the given mixin", function () { + var a = new Klass(); + expect(a.mixin).to.be.ok(); + }); + + it("includes multiple mixins", function () { + var Klass2 = L.Class.extend({ + includes: [{mixin: true}, {mixin2: true}] + }); + var a = new Klass2(); + + expect(a.mixin).to.be.ok(); + expect(a.mixin2).to.be.ok(); + }); + + it("grants the ability to include the given mixin", function () { + Klass.include({mixin2: true}); + + var a = new Klass(); + expect(a.mixin2).to.be.ok(); + }); + + it("merges options instead of replacing them", function () { + var KlassWithOptions1 = L.Class.extend({ + options: { + foo1: 1, + foo2: 2 + } + }); + var KlassWithOptions2 = KlassWithOptions1.extend({ + options: { + foo2: 3, + foo3: 4 + } + }); + + var a = new KlassWithOptions2(); + expect(a.options.foo1).to.eql(1); + expect(a.options.foo2).to.eql(3); + expect(a.options.foo3).to.eql(4); + }); + + it("gives new classes a distinct options object", function () { + var K1 = L.Class.extend({options: {}}); + var K2 = K1.extend({}); + expect(K2.prototype.options).not.to.equal(K1.prototype.options); + }); + + it("inherits options prototypally", function () { + var K1 = L.Class.extend({options: {}}); + var K2 = K1.extend({options: {}}); + K1.prototype.options.foo = 'bar'; + expect(K2.prototype.options.foo).to.eql('bar'); + }); + + it("adds constructor hooks correctly", function () { + var spy1 = sinon.spy(); + + Klass.addInitHook(spy1); + Klass.addInitHook('bar', 1, 2, 3); + + var a = new Klass(); + + expect(spy1.called).to.be.ok(); + expect(method.calledWith(1, 2, 3)); + }); + + it("inherits constructor hooks", function () { + var spy1 = sinon.spy(), + spy2 = sinon.spy(); + + var Klass2 = Klass.extend({}); + + Klass.addInitHook(spy1); + Klass2.addInitHook(spy2); + + var a = new Klass2(); + + expect(spy1.called).to.be.ok(); + expect(spy2.called).to.be.ok(); + }); + + it("does not call child constructor hooks", function () { + var spy1 = sinon.spy(), + spy2 = sinon.spy(); + + var Klass2 = Klass.extend({}); + + Klass.addInitHook(spy1); + Klass2.addInitHook(spy2); + + var a = new Klass(); + + expect(spy1.called).to.be.ok(); + expect(spy2.called).to.eql(false); + }); + + it("calls parent constructor hooks when child has none", function () { + var spy1 = sinon.spy(); + + Klass.addInitHook(spy1); + + var Klass2 = Klass.extend({}); + var a = new Klass2(); + + expect(spy1.called).to.be.ok(); + }); + }); + + + describe("#include", function () { + var Klass; + + beforeEach(function () { + Klass = L.Class.extend({}); + }); + + it("returns the class with the extra methods", function () { + + var q = sinon.spy(); + + var Qlass = Klass.include({quux: q}); + + var a = new Klass(); + var b = new Qlass(); + + a.quux(); + expect(q.called).to.be.ok(); + + b.quux(); + expect(q.called).to.be.ok(); + }); + }); + + // TODO Class.mergeOptions +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/EventsSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/EventsSpec.js new file mode 100644 index 000000000..5f46fa68c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/EventsSpec.js @@ -0,0 +1,654 @@ +describe('Events', function () { + + describe('#fireEvent', function () { + + it('fires all listeners added through #addEventListener', function () { + var obj = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(), + spy3 = sinon.spy(), + spy4 = sinon.spy(), + spy5 = sinon.spy(), + spy6 = sinon.spy(); + + obj.addEventListener('test', spy1); + obj.addEventListener('test', spy2); + obj.addEventListener('other', spy3); + obj.addEventListener({test: spy4, other: spy5}); + // obj.addEventListener({'test other': spy6 }); + + expect(spy1.called).to.be(false); + expect(spy2.called).to.be(false); + expect(spy3.called).to.be(false); + expect(spy4.called).to.be(false); + expect(spy5.called).to.be(false); + // expect(spy6.called).to.be(false); + + obj.fireEvent('test'); + + expect(spy1.called).to.be(true); + expect(spy2.called).to.be(true); + expect(spy3.called).to.be(false); + expect(spy4.called).to.be(true); + expect(spy5.called).to.be(false); + // expect(spy6.called).to.be(true); + // expect(spy6.callCount).to.be(1); + }); + + it('fires all listeners in the order they are added', function () { + var obj = new L.Evented(), + ctx1 = new L.Class(), + ctx2 = new L.Class(), + count = {one: 0, two: 0, three: 0, four: 0}; + + function listener1(e) { + count.one++; + expect(count.two).to.eql(0); + } + + function listener2(e) { + count.two++; + expect(count.one).to.eql(1); + expect(count.three).to.eql(0); + if (count.two === 1) { + expect(this).to.eql(ctx2); + } else if (count.two === 2) { + expect(this).to.eql(ctx1); + } else { + expect(this).to.eql(obj); + } + } + + function listener3(e) { + count.three++; + expect(count.two).to.eql(3); + expect(count.four).to.eql(0); + if (count.three === 1) { + expect(this).to.eql(ctx1); + } else if (count.three === 2) { + expect(this).to.eql(ctx2); + } + } + + function listener4(e) { + count.four++; + expect(count.three).to.eql(2); + } + + obj.on('test', listener1, ctx1); + obj.on('test', listener2, ctx2); + obj.on('test', listener2, ctx1); // Same listener but with different context. + obj.on('test', listener2); // Same listener but without context. + obj.on('test', listener3, ctx1); + obj.on('test', listener3, ctx2); + obj.on('test', listener4, ctx2); + + obj.fireEvent('test'); + + expect(count.one).to.be(1); + expect(count.two).to.be(3); + expect(count.three).to.be(2); + expect(count.four).to.be(1); + }); + + it('provides event object to listeners and executes them in the right context', function () { + var obj = new L.Evented(), + obj2 = new L.Evented(), + obj3 = new L.Evented(), + obj4 = new L.Evented(), + foo = {}; + + function listener1(e) { + expect(e.type).to.eql('test'); + expect(e.target).to.eql(obj); + expect(this).to.eql(obj); + expect(e.baz).to.eql(1); + } + + function listener2(e) { + expect(e.type).to.eql('test'); + expect(e.target).to.eql(obj2); + expect(this).to.eql(foo); + expect(e.baz).to.eql(2); + } + + function listener3(e) { + expect(e.type).to.eql('test'); + expect(e.target).to.eql(obj3); + expect(this).to.eql(obj3); + expect(e.baz).to.eql(3); + } + + function listener4(e) { + expect(e.type).to.eql('test'); + expect(e.target).to.eql(obj4); + expect(this).to.eql(foo); + expect(e.baz).to.eql(4); + } + + obj.addEventListener('test', listener1); + obj2.addEventListener('test', listener2, foo); + obj3.addEventListener({test: listener3}); + obj4.addEventListener({test: listener4}, foo); + + obj.fireEvent('test', {baz: 1}); + obj2.fireEvent('test', {baz: 2}); + obj3.fireEvent('test', {baz: 3}); + obj4.fireEvent('test', {baz: 4}); + }); + + it('calls no listeners removed through #removeEventListener', function () { + var obj = new L.Evented(), + spy = sinon.spy(), + spy2 = sinon.spy(), + spy3 = sinon.spy(), + spy4 = sinon.spy(), + spy5 = sinon.spy(); + + obj.addEventListener('test', spy); + obj.removeEventListener('test', spy); + + obj.fireEvent('test'); + + expect(spy.called).to.be(false); + + obj.addEventListener('test2', spy2); + obj.addEventListener('test2', spy3); + obj.removeEventListener('test2'); + + obj.fireEvent('test2'); + + expect(spy2.called).to.be(false); + expect(spy3.called).to.be(false); + + obj.addEventListener('test3', spy4); + obj.addEventListener('test4', spy5); + obj.removeEventListener({ + test3: spy4, + test4: spy5 + }); + + obj.fireEvent('test3'); + obj.fireEvent('test4'); + + expect(spy4.called).to.be(false); + expect(spy5.called).to.be(false); + }); + + it('can handle calls to #removeEventListener on objects with no registered event listeners', function () { + var obj = new L.Evented(); + var removeNonExistentListener = function () { + obj.removeEventListener('test'); + }; + expect(removeNonExistentListener).to.not.throwException(); + }); + + // added due to context-sensitive removeListener optimization + it('fires multiple listeners with the same context with id', function () { + var obj = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(), + foo = {}; + + L.Util.stamp(foo); + + obj.addEventListener('test', spy1, foo); + obj.addEventListener('test', spy2, foo); + + obj.fireEvent('test'); + + expect(spy1.called).to.be(true); + expect(spy2.called).to.be(true); + }); + + it('removes listeners with stamped contexts', function () { + var obj = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(), + foo = {}; + + L.Util.stamp(foo); + + obj.addEventListener('test', spy1, foo); + obj.addEventListener('test', spy2, foo); + + obj.removeEventListener('test', spy1, foo); + + obj.fireEvent('test'); + + expect(spy1.called).to.be(false); + expect(spy2.called).to.be(true); + }); + + it('removes listeners with a stamp originally added without one', function () { + var obj = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(), + foo = {}; + + obj.addEventListener('test', spy1, foo); + L.Util.stamp(foo); + obj.addEventListener('test', spy2, foo); + + obj.removeEventListener('test', spy1, foo); + obj.removeEventListener('test', spy2, foo); + + obj.fireEvent('test'); + + expect(spy1.called).to.be(false); + expect(spy2.called).to.be(false); + }); + + it('removes listeners with context == this and a stamp originally added without one', function () { + var obj = new L.Evented(), + obj2 = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(), + spy3 = sinon.spy(); + + obj.addEventListener('test', spy1, obj); + L.Util.stamp(obj); + obj.addEventListener('test', spy2, obj); + obj.addEventListener('test', spy3, obj2); // So that there is a contextId based listener, otherwise removeEventListener will do correct behaviour anyway + + obj.removeEventListener('test', spy1, obj); + obj.removeEventListener('test', spy2, obj); + obj.removeEventListener('test', spy3, obj2); + + obj.fireEvent('test'); + + expect(spy1.called).to.be(false); + expect(spy2.called).to.be(false); + expect(spy3.called).to.be(false); + }); + + it('doesnt lose track of listeners when removing non existent ones', function () { + var obj = new L.Evented(), + spy = sinon.spy(), + spy2 = sinon.spy(), + foo = {}, + foo2 = {}; + + L.Util.stamp(foo); + L.Util.stamp(foo2); + + obj.addEventListener('test', spy, foo2); + + obj.removeEventListener('test', spy, foo); // Decrements test_idx to 0, even though event listener isn't registered with foo's _leaflet_id + obj.removeEventListener('test', spy, foo2); // Doesn't get removed + + obj.addEventListener('test', spy2, foo); + + obj.fireEvent('test'); + + expect(spy.called).to.be(false); + }); + + it('correctly removes all listeners if given no fn', function () { + var obj = new L.Evented(), + spy = sinon.spy(), + foo = {}, + foo2 = {}, + foo3 = {}; + + obj.addEventListener('test', spy, foo2); + obj.addEventListener('test', spy, foo3); + + obj.removeEventListener('test'); // Removes both of the above listeners + + expect(obj.listens('test')).to.be(false); + + // Add and remove a listener + obj.addEventListener('test', spy, foo2); + obj.removeEventListener('test', spy, foo2); + + expect(obj.listens('test')).to.be(false); + + // Add and remove a listener without context + obj.addEventListener('test', spy); + obj.removeEventListener('test', spy); + + expect(obj.listens('test')).to.be(false); + }); + + it('makes sure an event is not triggered if a listener is removed during dispatch', function () { + var obj = new L.Evented(), + spy = sinon.spy(), + spy2 = sinon.spy(), + spy3 = sinon.spy(), + foo = {}; + + /* without context */ + obj.addEventListener('test', function () { obj.removeEventListener('test', spy); }); + obj.addEventListener('test', spy); + obj.fireEvent('test'); + + expect(spy.called).to.be(false); + + /* with context */ + obj.addEventListener('test2', function () { obj.removeEventListener('test2', spy2, foo); }, foo); + obj.addEventListener('test2', spy2, foo); + obj.fireEvent('test2'); + }); + + it('makes sure an event is not triggered if all listeners are removed during dispatch', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + obj.addEventListener('test', function () { obj.removeEventListener('test'); }); + obj.addEventListener('test', spy); + obj.fire('test'); + + expect(spy.called).to.be(false); + }); + + it('handles reentrant event firing', function () { + var obj = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(); + + obj + .addEventListener('test1', function () { + obj.fire('test2'); + }) + .addEventListener('test2', spy1) + .addEventListener('test1', function () { + obj.removeEventListener('test1', spy2); + }) + .addEventListener('test1', spy2); + + obj.fireEvent('test1'); + expect(spy1.called).to.be(true); + expect(spy2.called).to.be(false); + }); + + it('can remove an event listener while firing', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + var removeSpy = function () { + obj.removeEventListener('test', spy); + }; + + obj.addEventListener('test', spy); + obj.addEventListener('test', removeSpy); + + obj.fire('test'); + + obj.removeEventListener('test', removeSpy); + + expect(obj.listens('test')).to.be(false); + }); + }); + + describe('#on, #off & #fire', function () { + + it('works like #addEventListener && #removeEventListener', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + obj.on('test', spy); + obj.fire('test'); + + expect(spy.called).to.be(true); + + obj.off('test', spy); + obj.fireEvent('test'); + + expect(spy.callCount).to.be.lessThan(2); + }); + + it('does not override existing methods with the same name', function () { + var spy1 = sinon.spy(), + spy2 = sinon.spy(), + spy3 = sinon.spy(); + + var Klass = L.Evented.extend({ + on: spy1, + off: spy2, + fire: spy3 + }); + + var obj = new Klass(); + + obj.on(); + expect(spy1.called).to.be(true); + + obj.off(); + expect(spy2.called).to.be(true); + + obj.fire(); + expect(spy3.called).to.be(true); + }); + + it('does not add twice the same function', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + /* register without context */ + obj.on("test", spy); + obj.on("test", spy); + + /* Should be called once */ + obj.fire("test"); + + expect(spy.callCount).to.eql(1); + }); + }); + + describe("#clearEventListeners", function () { + it("clears all registered listeners on an object", function () { + var spy = sinon.spy(), + obj = new L.Evented(), + otherObj = new L.Evented(); + + obj.on('test', spy, obj); + obj.on('testTwo', spy); + obj.on('test', spy, otherObj); + obj.off(); + + obj.fire('test'); + + expect(spy.called).to.be(false); + }); + }); + + describe('#once', function () { + it('removes event listeners after first trigger', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + obj.once('test', spy, obj); + obj.fire('test'); + + expect(spy.called).to.be(true); + + obj.fire('test'); + + expect(spy.callCount).to.be.lessThan(2); + }); + + it('works with an object hash', function () { + var obj = new L.Evented(), + spy = sinon.spy(), + otherSpy = sinon.spy(); + + obj.once({ + 'test': spy, + otherTest: otherSpy + }, obj); + + obj.fire('test'); + obj.fire('otherTest'); + + expect(spy.called).to.be(true); + expect(otherSpy.called).to.be(true); + + obj.fire('test'); + obj.fire('otherTest'); + + expect(spy.callCount).to.be.lessThan(2); + expect(otherSpy.callCount).to.be.lessThan(2); + }); + + it("doesn't call listeners to events that have been removed", function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + obj.once('test', spy, obj); + obj.off('test', spy, obj); + + obj.fire('test'); + + expect(spy.called).to.be(false); + }); + + it('works if called from a context that doesnt implement #Events', function () { + var obj = new L.Evented(), + spy = sinon.spy(), + foo = {}; + + obj.once('test', spy, foo); + + obj.fire('test'); + + expect(spy.called).to.be(true); + }); + }); + + describe('addEventParent && removeEventParent', function () { + it('makes the object propagate events with to the given one if fired with propagate=true', function () { + var obj = new L.Evented(), + parent1 = new L.Evented(), + parent2 = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(); + + parent1.on('test', spy1); + parent2.on('test', spy2); + + obj.addEventParent(parent1).addEventParent(parent2); + + obj.fire('test'); + + expect(spy1.called).to.be(false); + expect(spy2.called).to.be(false); + + obj.fire('test', null, true); + + expect(spy1.called).to.be(true); + expect(spy2.called).to.be(true); + + obj.removeEventParent(parent1); + + obj.fire('test', null, true); + + expect(spy1.callCount).to.be(1); + expect(spy2.callCount).to.be(2); + }); + + it('can fire event where child has no listeners', function () { + var obj = new L.Evented(), + parent = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(); + + /* register without context */ + obj.on('test', spy1); + parent.on('test2', spy2); + + obj.addEventParent(parent); + + /* Should be called once */ + obj.fire('test2', null, true); + + expect(spy1.callCount).to.eql(0); + expect(spy2.callCount).to.eql(1); + }); + + it('sets target, sourceTarget and layer correctly', function () { + var obj = new L.Evented(), + parent = new L.Evented(), + spy1 = sinon.spy(), + spy2 = sinon.spy(); + + /* register without context */ + obj.on('test2', spy1); + parent.on('test2', spy2); + + obj.addEventParent(parent); + + /* Should be called once */ + obj.fire('test2', null, true); + + expect(spy1.calledWith({ + type: 'test2', + target: obj, + sourceTarget: obj + })).to.be.ok(); + expect(spy2.calledWith({ + type: 'test2', + target: parent, + // layer should be deprecated in the future + // in favor of sourceTarget + layer: obj, + sourceTarget: obj, + propagatedFrom: obj + })).to.be.ok(); + }); + }); + + describe('#listens', function () { + it('is false if there is no event handler', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + expect(obj.listens('test')).to.be(false); + }); + + it('is true if there is an event handler', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + obj.on('test', spy); + expect(obj.listens('test')).to.be(true); + }); + + it('is false if event handler has been removed', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + obj.on('test', spy); + obj.off('test', spy); + expect(obj.listens('test')).to.be(false); + }); + + it('changes for a "once" handler', function () { + var obj = new L.Evented(), + spy = sinon.spy(); + + obj.once('test', spy); + expect(obj.listens('test')).to.be(true); + + obj.fire('test'); + expect(obj.listens('test')).to.be(false); + }); + }); + + describe('#L.Mixin.Events', function () { + it('can be used from includes', function () { + var EventClass = L.Class.extend({ + includes: L.Mixin.Events + }); + var obj = new EventClass(); + var spy = sinon.spy(); + + obj.on('test', spy); + + obj.fire('test'); + + expect(spy.called).to.be(true); + }); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/GeneralSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/GeneralSpec.js new file mode 100644 index 000000000..fce1f215a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/GeneralSpec.js @@ -0,0 +1,19 @@ +describe('General', function () { + describe('noConflict', function () { + var leaflet = L; + + after(function () { + L = leaflet; + }); + + expect(L.noConflict()).to.eql(leaflet); + }); + + describe('namespace extension', function () { + L.Util.foo = 'bar'; + L.Foo = 'Bar'; + + expect(L.Util.foo).to.eql('bar'); + expect(L.Foo).to.eql('Bar'); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/UtilSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/UtilSpec.js new file mode 100644 index 000000000..979dcdca6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/core/UtilSpec.js @@ -0,0 +1,245 @@ +describe('Util', function () { + + describe('#extend', function () { + var a; + + beforeEach(function () { + a = { + foo: 5, + bar: 'asd' + }; + }); + + it('extends the first argument with the properties of the second', function () { + L.Util.extend(a, { + bar: 7, + baz: 3 + }); + + expect(a).to.eql({ + foo: 5, + bar: 7, + baz: 3 + }); + }); + + it('accepts more than 2 arguments', function () { + L.Util.extend(a, {bar: 7}, {baz: 3}); + + expect(a).to.eql({ + foo: 5, + bar: 7, + baz: 3 + }); + }); + }); + + describe('#bind', function () { + it('returns the given function with the given context', function () { + var fn = function () { + return this; + }; + + var fn2 = L.Util.bind(fn, {foo: 'bar'}); + + expect(fn2()).to.eql({foo: 'bar'}); + }); + + it('passes additional arguments to the bound function', function () { + var fn = sinon.spy(), + foo = {}, + a = {}, + b = {}, + c = {}; + + var fn2 = L.Util.bind(fn, foo, a, b); + + fn2(c); + + expect(fn.calledWith(a, b, c)).to.be.ok(); + }); + }); + + describe('#stamp', function () { + it('sets a unique id on the given object and returns it', function () { + var a = {}, + id = L.Util.stamp(a); + + expect(typeof id).to.eql('number'); + expect(L.Util.stamp(a)).to.eql(id); + + var b = {}, + id2 = L.Util.stamp(b); + + expect(id2).not.to.eql(id); + }); + }); + + describe('#falseFn', function () { + it('returns false', function () { + expect(L.Util.falseFn()).to.be(false); + }); + }); + + describe('#formatNum', function () { + it('formats numbers with a given precision', function () { + expect(L.Util.formatNum(13.12325555, 3)).to.eql(13.123); + expect(L.Util.formatNum(13.12325555)).to.eql(13.123256); + expect(L.Util.formatNum(13.12325555, 0)).to.eql(13); + }); + }); + + + describe('#getParamString', function () { + it('creates a valid query string for appending depending on url input', function () { + var a = { + url: 'http://example.com/get', + obj: {bar: 7, baz: 3}, + result: '?bar=7&baz=3' + }; + + expect(L.Util.getParamString(a.obj, a.url)).to.eql(a.result); + + var b = { + url: 'http://example.com/get?justone=qs', + obj: {bar: 7, baz: 3}, + result: '&bar=7&baz=3' + }; + + expect(L.Util.getParamString(b.obj, b.url)).to.eql(b.result); + + var c = { + url: undefined, + obj: {bar: 7, baz: 3}, + result: '?bar=7&baz=3' + }; + + expect(L.Util.getParamString(c.obj, c.url)).to.eql(c.result); + }); + }); + + describe('#requestAnimFrame', function () { + it('calles a function on next frame, unless canceled', function (done) { + var spy = sinon.spy(), + foo = {}; + + L.Util.requestAnimFrame(spy); + + L.Util.requestAnimFrame(function () { + expect(this).to.eql(foo); + done(); + }, foo); + + L.Util.cancelAnimFrame(spy); + }); + }); + + describe('#throttle', function () { + it('limits execution to not more often than specified time interval', function (done) { + var spy = sinon.spy(); + + var fn = L.Util.throttle(spy, 20); + + fn(); + fn(); + fn(); + + expect(spy.callCount).to.eql(1); + + setTimeout(function () { + expect(spy.callCount).to.eql(2); + done(); + }, 30); + }); + }); + + describe('#splitWords', function () { + it('splits words into an array', function () { + expect(L.Util.splitWords('foo bar baz')).to.eql(['foo', 'bar', 'baz']); + }); + }); + + describe('#setOptions', function () { + it('sets specified options on object', function () { + var o = {}; + L.Util.setOptions(o, {foo: 'bar'}); + expect(o.options.foo).to.eql('bar'); + }); + + it('returns options', function () { + var o = {}; + var r = L.Util.setOptions(o, {foo: 'bar'}); + expect(r).to.equal(o.options); + }); + + it('accepts undefined', function () { + var o = {}; + L.Util.setOptions(o, undefined); + expect(o.options).to.eql({}); + }); + + it('creates a distinct options object', function () { + var opts = {}, + o = L.Util.create({options: opts}); + L.Util.setOptions(o, {}); + expect(o.options).not.to.equal(opts); + }); + + it("doesn't create a distinct options object if object already has own options", function () { + var opts = {}, + o = {options: opts}; + L.Util.setOptions(o, {}); + expect(o.options).to.equal(opts); + }); + + it('inherits options prototypally', function () { + var opts = {}, + o = L.Util.create({options: opts}); + L.Util.setOptions(o, {}); + opts.foo = 'bar'; + expect(o.options.foo).to.eql('bar'); + }); + }); + + describe('#template', function () { + it('evaluates templates with a given data object', function () { + var tpl = 'Hello {foo} and {bar}!'; + + var str = L.Util.template(tpl, { + foo: 'Vlad', + bar: 'Dave' + }); + + expect(str).to.eql('Hello Vlad and Dave!'); + }); + + it('does not modify text without a token variable', function () { + expect(L.Util.template('foo', {})).to.eql('foo'); + }); + + it('supports templates with double quotes', function () { + expect(L.Util.template('He said: "{foo}"!', { + foo: 'Hello' + })).to.eql('He said: "Hello"!'); + }); + + it('throws when a template token is not given', function () { + expect(function () { + L.Util.template(undefined, {foo: 'bar'}); + }).to.throwError(); + }); + + it('allows underscores and dashes in placeholders', function () { + expect(L.Util.template('{nice_stuff}', {'nice_stuff': 'foo'})).to.eql('foo'); + expect(L.Util.template('{-y}', {'-y': 1})).to.eql('1'); + }); + }); + + describe('#isArray', function () { + expect(L.Util.isArray([1, 2, 3])).to.be(true); + /* eslint no-array-constructor: 0 */ + expect(L.Util.isArray(new Array(1, 2, 3))).to.be(true); + expect(L.Util.isArray('blabla')).to.be(false); + expect(L.Util.isArray({0: 1, 1: 2})).to.be(false); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/dom/DomEventSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/dom/DomEventSpec.js new file mode 100644 index 000000000..7d784e553 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/dom/DomEventSpec.js @@ -0,0 +1,112 @@ +describe('DomEvent', function () { + var el; + + function simulateClick(el) { + if (document.createEvent) { + var e = document.createEvent('MouseEvents'); + e.initMouseEvent('click', true, true, window, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + return el.dispatchEvent(e); + } else if (el.fireEvent) { + return el.fireEvent('onclick'); + } + } + + beforeEach(function () { + el = document.createElement('div'); + el.style.position = 'absolute'; + el.style.top = el.style.left = '-10000px'; + document.body.appendChild(el); + }); + + afterEach(function () { + document.body.removeChild(el); + }); + + describe('#addListener', function () { + it('adds a listener and calls it on event', function () { + var listener1 = sinon.spy(), + listener2 = sinon.spy(); + + L.DomEvent.addListener(el, 'click', listener1); + L.DomEvent.addListener(el, 'click', listener2); + + simulateClick(el); + + expect(listener1.called).to.be.ok(); + expect(listener2.called).to.be.ok(); + }); + + it('binds "this" to the given context', function () { + var obj = {foo: 'bar'}, + result; + + L.DomEvent.addListener(el, 'click', function () { + result = this; + }, obj); + + simulateClick(el); + + expect(result).to.eql(obj); + }); + + it('passes an event object to the listener', function () { + var type; + + L.DomEvent.addListener(el, 'click', function (e) { + type = e && e.type; + }); + simulateClick(el); + + expect(type).to.eql('click'); + }); + + it('is chainable', function () { + var res = L.DomEvent.addListener(el, 'click', function () {}); + expect(res.addListener).to.be.a('function'); + }); + }); + + describe('#removeListener', function () { + it('removes a previously added listener', function () { + var listener = sinon.spy(); + + L.DomEvent.addListener(el, 'click', listener); + L.DomEvent.removeListener(el, 'click', listener); + + simulateClick(el); + + expect(listener.called).to.not.be.ok(); + }); + + it('is chainable', function () { + var res = L.DomEvent.removeListener(el, 'click', function () {}); + expect(res.removeListener).to.be.a('function'); + }); + }); + + describe('#stopPropagation', function () { + it('stops propagation of the given event', function () { + var child = document.createElement('div'), + listener = sinon.spy(); + + el.appendChild(child); + + L.DomEvent.addListener(child, 'click', L.DomEvent.stopPropagation); + L.DomEvent.addListener(el, 'click', listener); + + simulateClick(child); + + expect(listener.called).to.not.be.ok(); + + el.removeChild(child); + }); + }); + describe('#preventDefault', function () { + it('prevents the default action of event', function () { + L.DomEvent.addListener(el, 'click', L.DomEvent.preventDefault); + + expect(simulateClick(el)).to.be(false); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/dom/DomUtilSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/dom/DomUtilSpec.js new file mode 100644 index 000000000..77aa7a1a8 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/dom/DomUtilSpec.js @@ -0,0 +1,59 @@ +describe('DomUtil', function () { + var el; + + beforeEach(function () { + el = document.createElement('div'); + el.style.position = 'absolute'; + el.style.top = el.style.left = '-10000px'; + document.body.appendChild(el); + }); + + afterEach(function () { + document.body.removeChild(el); + }); + + describe('#get', function () { + it('gets element by id if the given argument is string', function () { + el.id = 'testId'; + expect(L.DomUtil.get(el.id)).to.eql(el); + }); + + it('returns the element if it is given as an argument', function () { + expect(L.DomUtil.get(el)).to.eql(el); + }); + }); + + describe('#addClass, #removeClass, #hasClass', function () { + it('has defined class for test element', function () { + el.className = 'bar foo baz '; + expect(L.DomUtil.hasClass(el, 'foo')).to.be.ok(); + expect(L.DomUtil.hasClass(el, 'bar')).to.be.ok(); + expect(L.DomUtil.hasClass(el, 'baz')).to.be.ok(); + expect(L.DomUtil.hasClass(el, 'boo')).to.not.be.ok(); + }); + + it('adds or removes the class', function () { + el.className = ''; + L.DomUtil.addClass(el, 'foo'); + + expect(el.className).to.eql('foo'); + expect(L.DomUtil.hasClass(el, 'foo')).to.be.ok(); + + L.DomUtil.addClass(el, 'bar'); + expect(el.className).to.eql('foo bar'); + expect(L.DomUtil.hasClass(el, 'foo')).to.be.ok(); + + L.DomUtil.removeClass(el, 'foo'); + expect(el.className).to.eql('bar'); + expect(L.DomUtil.hasClass(el, 'foo')).to.not.be.ok(); + + el.className = 'foo bar barz'; + L.DomUtil.removeClass(el, 'bar'); + expect(el.className).to.eql('foo barz'); + }); + }); + + // describe('#setPosition', noSpecs); + + // describe('#getStyle', noSpecs); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/CRSSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/CRSSpec.js new file mode 100644 index 000000000..aa5cdc05b --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/CRSSpec.js @@ -0,0 +1,276 @@ +describe("CRS.EPSG3857", function () { + var crs = L.CRS.EPSG3857; + + describe("#latLngToPoint", function () { + it("projects a center point", function () { + expect(crs.latLngToPoint(L.latLng(0, 0), 0)).near(new L.Point(128, 128), 0.01); + }); + + it("projects the northeast corner of the world", function () { + expect(crs.latLngToPoint(L.latLng(85.0511287798, 180), 0)).near(new L.Point(256, 0)); + }); + }); + + describe("#pointToLatLng", function () { + it("reprojects a center point", function () { + expect(crs.pointToLatLng(new L.Point(128, 128), 0)).nearLatLng(L.latLng(0, 0), 0.01); + }); + + it("reprojects the northeast corner of the world", function () { + expect(crs.pointToLatLng(new L.Point(256, 0), 0)).nearLatLng(L.latLng(85.0511287798, 180)); + }); + }); + + describe("project", function () { + it('projects geo coords into meter coords correctly', function () { + expect(crs.project(new L.LatLng(50, 30))).near(new L.Point(3339584.7238, 6446275.84102)); + expect(crs.project(new L.LatLng(85.0511287798, 180))).near(new L.Point(20037508.34279, 20037508.34278)); + expect(crs.project(new L.LatLng(-85.0511287798, -180))).near(new L.Point(-20037508.34279, -20037508.34278)); + }); + }); + + describe("unproject", function () { + it('unprojects meter coords into geo coords correctly', function () { + expect(crs.unproject(new L.Point(3339584.7238, 6446275.84102))).nearLatLng(new L.LatLng(50, 30)); + expect(crs.unproject(new L.Point(20037508.34279, 20037508.34278))).nearLatLng(new L.LatLng(85.051129, 180)); + expect(crs.unproject(new L.Point(-20037508.34279, -20037508.34278))).nearLatLng(new L.LatLng(-85.051129, -180)); + }); + }); + + describe("#getProjectedBounds", function () { + it("gives correct size", function () { + var i, + worldSize = 256, + crsSize; + for (i = 0; i <= 22; i++) { + crsSize = crs.getProjectedBounds(i).getSize(); + expect(crsSize.x).equal(worldSize); + expect(crsSize.y).equal(worldSize); + worldSize *= 2; + } + }); + }); + + describe('#wrapLatLng', function () { + it("wraps longitude to lie between -180 and 180 by default", function () { + expect(crs.wrapLatLng(new L.LatLng(0, 190)).lng).to.eql(-170); + expect(crs.wrapLatLng(new L.LatLng(0, 360)).lng).to.eql(0); + expect(crs.wrapLatLng(new L.LatLng(0, 380)).lng).to.eql(20); + expect(crs.wrapLatLng(new L.LatLng(0, -190)).lng).to.eql(170); + expect(crs.wrapLatLng(new L.LatLng(0, -360)).lng).to.eql(0); + expect(crs.wrapLatLng(new L.LatLng(0, -380)).lng).to.eql(-20); + expect(crs.wrapLatLng(new L.LatLng(0, 90)).lng).to.eql(90); + expect(crs.wrapLatLng(new L.LatLng(0, 180)).lng).to.eql(180); + }); + + it("does not drop altitude", function () { + expect(crs.wrapLatLng(new L.LatLng(0, 190, 1234)).lng).to.eql(-170); + expect(crs.wrapLatLng(new L.LatLng(0, 190, 1234)).alt).to.eql(1234); + + expect(crs.wrapLatLng(new L.LatLng(0, 380, 1234)).lng).to.eql(20); + expect(crs.wrapLatLng(new L.LatLng(0, 380, 1234)).alt).to.eql(1234); + }); + }); + + describe('#wrapLatLngBounds', function () { + it("does not wrap bounds between -180 and 180 longitude", function () { + + var bounds1 = L.latLngBounds([-10, -10], [10, 10]); + var bounds2 = L.latLngBounds([-80, -180], [-70, -170]); + var bounds3 = L.latLngBounds([70, 170], [80, 180]); + + bounds1 = crs.wrapLatLngBounds(bounds1); + bounds2 = crs.wrapLatLngBounds(bounds2); + bounds3 = crs.wrapLatLngBounds(bounds3); + + expect(bounds1.getSouth()).to.eql(-10); + expect(bounds1.getWest()).to.eql(-10); + expect(bounds1.getNorth()).to.eql(10); + expect(bounds1.getEast()).to.eql(10); + + expect(bounds2.getSouth()).to.eql(-80); + expect(bounds2.getWest()).to.eql(-180); + expect(bounds2.getNorth()).to.eql(-70); + expect(bounds2.getEast()).to.eql(-170); + + expect(bounds3.getSouth()).to.eql(70); + expect(bounds3.getWest()).to.eql(170); + expect(bounds3.getNorth()).to.eql(80); + expect(bounds3.getEast()).to.eql(180); + + }); + + it("wraps bounds when center longitude is less than -180", function () { + var bounds1 = L.latLngBounds([0, -185], [10, -170]); + var bounds2 = L.latLngBounds([0, -190], [10, -175]); + + bounds1 = crs.wrapLatLngBounds(bounds1); + bounds2 = crs.wrapLatLngBounds(bounds2); + + expect(bounds1.getSouth()).to.eql(0); + expect(bounds1.getWest()).to.eql(-185); + expect(bounds1.getNorth()).to.eql(10); + expect(bounds1.getEast()).to.eql(-170); + + expect(bounds2.getSouth()).to.eql(0); + expect(bounds2.getWest()).to.eql(170); + expect(bounds2.getNorth()).to.eql(10); + expect(bounds2.getEast()).to.eql(185); + }); + + it("wraps bounds when center longitude is larger than +180", function () { + var bounds1 = L.latLngBounds([0, 185], [10, 170]); + var bounds2 = L.latLngBounds([0, 190], [10, 175]); + + bounds1 = crs.wrapLatLngBounds(bounds1); + bounds2 = crs.wrapLatLngBounds(bounds2); + + expect(bounds1.getSouth()).to.eql(0); + expect(bounds1.getWest()).to.eql(170); + expect(bounds1.getNorth()).to.eql(10); + expect(bounds1.getEast()).to.eql(185); + + expect(bounds2.getSouth()).to.eql(0); + expect(bounds2.getWest()).to.eql(-185); + expect(bounds2.getNorth()).to.eql(10); + expect(bounds2.getEast()).to.eql(-170); + }); + + }); + +}); + +describe("CRS.EPSG4326", function () { + var crs = L.CRS.EPSG4326; + + describe("#getSize", function () { + it("gives correct size", function () { + var i, + worldSize = 256, + crsSize; + for (i = 0; i <= 22; i++) { + crsSize = crs.getProjectedBounds(i).getSize(); + expect(crsSize.x).equal(worldSize * 2); + // Lat bounds are half as high (-90/+90 compared to -180/+180) + expect(crsSize.y).equal(worldSize); + worldSize *= 2; + } + }); + }); +}); + +describe("CRS.EPSG3395", function () { + var crs = L.CRS.EPSG3395; + + describe("#latLngToPoint", function () { + it("projects a center point", function () { + expect(crs.latLngToPoint(L.latLng(0, 0), 0)).near(new L.Point(128, 128), 0.01); + }); + + it("projects the northeast corner of the world", function () { + expect(crs.latLngToPoint(L.latLng(85.0840591556, 180), 0)).near(new L.Point(256, 0)); + }); + }); + + describe("#pointToLatLng", function () { + it("reprojects a center point", function () { + expect(crs.pointToLatLng(new L.Point(128, 128), 0)).nearLatLng(L.latLng(0, 0), 0.01); + }); + + it("reprojects the northeast corner of the world", function () { + expect(crs.pointToLatLng(new L.Point(256, 0), 0)).nearLatLng(L.latLng(85.0840591556, 180)); + }); + }); +}); + +describe("CRS.Simple", function () { + var crs = L.CRS.Simple; + + describe("#latLngToPoint", function () { + it("converts LatLng coords to pixels", function () { + expect(crs.latLngToPoint(L.latLng(0, 0), 0)).near(new L.Point(0, 0)); + expect(crs.latLngToPoint(L.latLng(700, 300), 0)).near(new L.Point(300, -700)); + expect(crs.latLngToPoint(L.latLng(-200, 1000), 1)).near(new L.Point(2000, 400)); + }); + }); + + describe("#pointToLatLng", function () { + it("converts pixels to LatLng coords", function () { + expect(crs.pointToLatLng(L.point(0, 0), 0)).nearLatLng(new L.LatLng(0, 0)); + expect(crs.pointToLatLng(L.point(300, -700), 0)).nearLatLng(new L.LatLng(700, 300)); + expect(crs.pointToLatLng(L.point(2000, 400), 1)).nearLatLng(new L.LatLng(-200, 1000)); + }); + }); + + describe("getProjectedBounds", function () { + it("returns nothing", function () { + expect(crs.getProjectedBounds(5)).to.be(null); + }); + }); + + describe("wrapLatLng", function () { + it("returns coords as is", function () { + expect(crs.wrapLatLng(new L.LatLng(270, 400)).equals(new L.LatLng(270, 400))).to.be(true); + }); + it("wraps coords if configured", function () { + var crs = L.extend({}, L.CRS.Simple, { + wrapLng: [-200, 200], + wrapLat: [-200, 200] + }); + + expect(crs.wrapLatLng(new L.LatLng(300, -250))).nearLatLng(new L.LatLng(-100, 150)); + }); + }); +}); + +describe("CRS", function () { + var crs = L.CRS; + + describe("#zoom && #scale", function () { + it("convert zoom to scale and viceversa and return the same values", function () { + var zoom = 2.5; + var scale = crs.scale(zoom); + expect(crs.zoom(scale)).to.eql(zoom); + }); + }); +}); + +describe("CRS.ZoomNotPowerOfTwo", function () { + var crs = L.extend({}, L.CRS, { + scale: function (zoom) { + return 256 * Math.pow(1.5, zoom); + }, + zoom: function (scale) { + return Math.log(scale / 256) / Math.log(1.5); + } + }); + + describe("#scale", function () { + it("of zoom levels are related by a power of 1.5", function () { + var zoom = 5; + var scale = crs.scale(zoom); + expect(crs.scale(zoom + 1)).to.eql(1.5 * scale); + expect(crs.zoom(1.5 * scale)).to.eql(zoom + 1); + }); + }); + + describe("#zoom && #scale", function () { + it("convert zoom to scale and viceversa and return the same values", function () { + var zoom = 2; + var scale = crs.scale(zoom); + expect(crs.zoom(scale)).to.eql(zoom); + }); + }); +}); + +describe("CRS.Earth", function () { + describe("#distance", function () { + // Test values from http://rosettacode.org/wiki/Haversine_formula, + // we assume using mean earth radius (https://en.wikipedia.org/wiki/Earth_radius#Mean_radius) + // is correct, since that's what International Union of Geodesy and Geophysics recommends, + // and that sounds serious. + var p1 = L.latLng(36.12, -86.67); + var p2 = L.latLng(33.94, -118.40); + expect(L.CRS.Earth.distance(p1, p2)).to.be.within(2886444.43, 2886444.45); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/LatLngBoundsSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/LatLngBoundsSpec.js new file mode 100644 index 000000000..c4d9686f6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/LatLngBoundsSpec.js @@ -0,0 +1,190 @@ +describe('LatLngBounds', function () { + var a, c; + + beforeEach(function () { + a = new L.LatLngBounds( + new L.LatLng(14, 12), + new L.LatLng(30, 40)); + c = new L.LatLngBounds(); + }); + + describe('constructor', function () { + it('instantiates either passing two latlngs or an array of latlngs', function () { + var b = new L.LatLngBounds([ + new L.LatLng(14, 12), + new L.LatLng(30, 40) + ]); + expect(b).to.eql(a); + expect(b.getNorthWest()).to.eql(new L.LatLng(30, 12)); + }); + + it('returns an empty bounds when not argument is given', function () { + var bounds = new L.LatLngBounds(); + expect(bounds instanceof L.LatLngBounds).to.be.ok(a); + }); + + it('returns an empty bounds when not argument is given to factory', function () { + var bounds = L.latLngBounds(); + expect(bounds instanceof L.LatLngBounds).to.be.ok(a); + }); + + }); + + describe('#extend', function () { + it('extends the bounds by a given point', function () { + a.extend(new L.LatLng(20, 50)); + expect(a.getNorthEast()).to.eql(new L.LatLng(30, 50)); + }); + + it('extends the bounds by given bounds', function () { + a.extend([[20, 50], [8, 40]]); + expect(a.getSouthEast()).to.eql(new L.LatLng(8, 50)); + }); + + it('extends the bounds by undefined', function () { + expect(a.extend()).to.eql(a); + }); + + it('extends the bounds by raw object', function () { + a.extend({lat: 20, lng: 50}); + expect(a.getNorthEast()).to.eql(new L.LatLng(30, 50)); + }); + + it('extend the bounds by an empty bounds object', function () { + expect(a.extend(new L.LatLngBounds())).to.eql(a); + }); + }); + + describe('#getCenter', function () { + it('returns the bounds center', function () { + expect(a.getCenter()).to.eql(new L.LatLng(22, 26)); + }); + }); + + describe('#pad', function () { + it('pads the bounds by a given ratio', function () { + var b = a.pad(0.5); + + expect(b).to.eql(L.latLngBounds([[6, -2], [38, 54]])); + }); + }); + + describe('#equals', function () { + it('returns true if bounds equal', function () { + expect(a.equals([[14, 12], [30, 40]])).to.eql(true); + expect(a.equals([[14, 13], [30, 40]])).to.eql(false); + expect(a.equals(null)).to.eql(false); + }); + + it("returns true if compared objects are equal within a certain margin", function () { + expect(a.equals([[15, 11], [29, 41]], 1)).to.eql(true); + }); + + it("returns false if compared objects are not equal within a certain margin", function () { + expect(a.equals([[15, 11], [29, 41]], 0.5)).to.eql(false); + }); + }); + + describe('#isValid', function () { + it('returns true if properly set up', function () { + expect(a.isValid()).to.be.ok(); + }); + it('returns false if is invalid', function () { + expect(c.isValid()).to.not.be.ok(); + }); + it('returns true if extended', function () { + c.extend([0, 0]); + expect(c.isValid()).to.be.ok(); + }); + }); + + describe('#getWest', function () { + it('returns a proper bbox west value', function () { + expect(a.getWest()).to.eql(12); + }); + }); + + describe('#getSouth', function () { + it('returns a proper bbox south value', function () { + expect(a.getSouth()).to.eql(14); + }); + + }); + + describe('#getEast', function () { + it('returns a proper bbox east value', function () { + expect(a.getEast()).to.eql(40); + }); + + }); + + describe('#getNorth', function () { + it('returns a proper bbox north value', function () { + expect(a.getNorth()).to.eql(30); + }); + + }); + + describe('#toBBoxString', function () { + it('returns a proper left,bottom,right,top bbox', function () { + expect(a.toBBoxString()).to.eql("12,14,40,30"); + }); + + }); + + describe('#getNorthWest', function () { + it('returns a proper north-west LatLng', function () { + expect(a.getNorthWest()).to.eql(new L.LatLng(a.getNorth(), a.getWest())); + }); + + }); + + describe('#getSouthEast', function () { + it('returns a proper south-east LatLng', function () { + expect(a.getSouthEast()).to.eql(new L.LatLng(a.getSouth(), a.getEast())); + }); + }); + + describe('#contains', function () { + it('returns true if contains latlng point as array', function () { + expect(a.contains([16, 20])).to.eql(true); + expect(L.latLngBounds(a).contains([5, 20])).to.eql(false); + }); + + it('returns true if contains latlng point as {lat:, lng:} object', function () { + expect(a.contains({lat: 16, lng: 20})).to.eql(true); + expect(L.latLngBounds(a).contains({lat: 5, lng: 20})).to.eql(false); + }); + + it('returns true if contains latlng point as L.LatLng instance', function () { + expect(a.contains(L.latLng([16, 20]))).to.eql(true); + expect(L.latLngBounds(a).contains(L.latLng([5, 20]))).to.eql(false); + }); + + it('returns true if contains bounds', function () { + expect(a.contains([[16, 20], [20, 40]])).to.eql(true); + expect(a.contains([[16, 50], [8, 40]])).to.eql(false); + }); + }); + + describe('#intersects', function () { + it('returns true if intersects the given bounds', function () { + expect(a.intersects([[16, 20], [50, 60]])).to.eql(true); + expect(a.contains([[40, 50], [50, 60]])).to.eql(false); + }); + + it('returns true if just touches the boundary of the given bounds', function () { + expect(a.intersects([[25, 40], [55, 50]])).to.eql(true); + }); + }); + + describe('#overlaps', function () { + it('returns true if overlaps the given bounds', function () { + expect(a.overlaps([[16, 20], [50, 60]])).to.eql(true); + }); + it('returns false if just touches the boundary of the given bounds', function () { + expect(a.overlaps([[25, 40], [55, 50]])).to.eql(false); + }); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/LatLngSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/LatLngSpec.js new file mode 100644 index 000000000..c0d125935 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/LatLngSpec.js @@ -0,0 +1,141 @@ +describe('LatLng', function () { + describe('constructor', function () { + it("sets lat and lng", function () { + var a = new L.LatLng(25, 74); + expect(a.lat).to.eql(25); + expect(a.lng).to.eql(74); + + var b = new L.LatLng(-25, -74); + expect(b.lat).to.eql(-25); + expect(b.lng).to.eql(-74); + }); + + it('throws an error if invalid lat or lng', function () { + expect(function () { + var a = new L.LatLng(NaN, NaN); + }).to.throwError(); + }); + + it('does not set altitude if undefined', function () { + var a = new L.LatLng(25, 74); + expect(typeof a.alt).to.eql('undefined'); + }); + + it('sets altitude', function () { + var a = new L.LatLng(25, 74, 50); + expect(a.alt).to.eql(50); + + var b = new L.LatLng(-25, -74, -50); + expect(b.alt).to.eql(-50); + }); + + }); + + describe('#equals', function () { + it("returns true if compared objects are equal within a certain margin", function () { + var a = new L.LatLng(10, 20); + var b = new L.LatLng(10 + 1.0E-10, 20 - 1.0E-10); + expect(a.equals(b)).to.eql(true); + }); + + it("returns false if compared objects are not equal within a certain margin", function () { + var a = new L.LatLng(10, 20); + var b = new L.LatLng(10, 23.3); + expect(a.equals(b)).to.eql(false); + }); + + it('returns false if passed non-valid object', function () { + var a = new L.LatLng(10, 20); + expect(a.equals(null)).to.eql(false); + }); + }); + + describe('#toString', function () { + it('formats a string', function () { + var a = new L.LatLng(10.333333333, 20.2222222); + expect(a.toString(3)).to.eql('LatLng(10.333, 20.222)'); + expect(a.toString()).to.eql('LatLng(10.333333, 20.222222)'); + }); + }); + + describe('#distanceTo', function () { + it('calculates distance in meters', function () { + var a = new L.LatLng(50.5, 30.5); + var b = new L.LatLng(50, 1); + + expect(Math.abs(Math.round(a.distanceTo(b) / 1000) - 2084) < 5).to.eql(true); + }); + it('does not return NaN if input points are equal', function () { + var a = new L.LatLng(50.5, 30.5); + var b = new L.LatLng(50.5, 30.5); + + expect(a.distanceTo(b)).to.eql(0); + }); + }); + + describe('L.latLng factory', function () { + it('returns LatLng instance as is', function () { + var a = new L.LatLng(50, 30); + + expect(L.latLng(a)).to.eql(a); + }); + + it('accepts an array of coordinates', function () { + expect(L.latLng([])).to.eql(null); + expect(L.latLng([50])).to.eql(null); + expect(L.latLng([50, 30])).to.eql(new L.LatLng(50, 30)); + expect(L.latLng([50, 30, 100])).to.eql(new L.LatLng(50, 30, 100)); + }); + + it('passes null or undefined as is', function () { + expect(L.latLng(undefined)).to.eql(undefined); + expect(L.latLng(null)).to.eql(null); + }); + + it('creates a LatLng object from two coordinates', function () { + expect(L.latLng(50, 30)).to.eql(new L.LatLng(50, 30)); + }); + + it('accepts an object with lat/lng', function () { + expect(L.latLng({lat: 50, lng: 30})).to.eql(new L.LatLng(50, 30)); + }); + + it('accepts an object with lat/lon', function () { + expect(L.latLng({lat: 50, lon: 30})).to.eql(new L.LatLng(50, 30)); + }); + + it('returns null if lng not specified', function () { + expect(L.latLng(50)).to.be(null); + }); + + it('accepts altitude as third parameter', function () { + expect(L.latLng(50, 30, 100)).to.eql(new L.LatLng(50, 30, 100)); + }); + + it('accepts an object with alt', function () { + expect(L.latLng({lat: 50, lng: 30, alt: 100})).to.eql(new L.LatLng(50, 30, 100)); + expect(L.latLng({lat: 50, lon: 30, alt: 100})).to.eql(new L.LatLng(50, 30, 100)); + }); + }); + + describe('#clone', function () { + + it('should clone attributes', function () { + var a = new L.LatLng(50.5, 30.5, 100); + var b = a.clone(); + + expect(b.lat).to.equal(50.5); + expect(b.lng).to.equal(30.5); + expect(b.alt).to.equal(100); + }); + + it('should create another reference', function () { + var a = new L.LatLng(50.5, 30.5, 100); + var b = a.clone(); + + expect(a === b).to.be(false); + }); + + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/ProjectionSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/ProjectionSpec.js new file mode 100644 index 000000000..f106562e3 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geo/ProjectionSpec.js @@ -0,0 +1,96 @@ +describe("Projection.Mercator", function () { + var p = L.Projection.Mercator; + + describe("#project", function () { + it("projects a center point", function () { + // edge cases + expect(p.project(new L.LatLng(0, 0))).near(new L.Point(0, 0)); + }); + + it("projects the northeast corner of the world", function () { + expect(p.project(new L.LatLng(85.0840591556, 180))).near(new L.Point(20037508, 20037508)); + }); + + it("projects the southwest corner of the world", function () { + expect(p.project(new L.LatLng(-85.0840591556, -180))).near(new L.Point(-20037508, -20037508)); + }); + + it("projects other points", function () { + expect(p.project(new L.LatLng(50, 30))).near(new L.Point(3339584, 6413524)); + + // from https://github.com/Leaflet/Leaflet/issues/1578 + expect(p.project(new L.LatLng(51.9371170300465, 80.11230468750001))) + .near(new L.Point(8918060.964088084, 6755099.410887127)); + }); + }); + + describe("#unproject", function () { + function pr(point) { + return p.project(p.unproject(point)); + } + + it("unprojects a center point", function () { + expect(pr(new L.Point(0, 0))).near(new L.Point(0, 0)); + }); + + it("unprojects pi points", function () { + expect(pr(new L.Point(-Math.PI, Math.PI))).near(new L.Point(-Math.PI, Math.PI)); + expect(pr(new L.Point(-Math.PI, -Math.PI))).near(new L.Point(-Math.PI, -Math.PI)); + + expect(pr(new L.Point(0.523598775598, 1.010683188683))).near(new L.Point(0.523598775598, 1.010683188683)); + }); + + it('unprojects other points', function () { + // from https://github.com/Leaflet/Leaflet/issues/1578 + expect(pr(new L.Point(8918060.964088084, 6755099.410887127))); + }); + }); +}); +describe("Projection.SphericalMercator", function () { + var p = L.Projection.SphericalMercator; + + describe("#project", function () { + it("projects a center point", function () { + // edge cases + expect(p.project(new L.LatLng(0, 0))).near(new L.Point(0, 0)); + }); + + it("projects the northeast corner of the world", function () { + expect(p.project(new L.LatLng(85.0511287798, 180))).near(new L.Point(20037508, 20037508)); + }); + + it("projects the southwest corner of the world", function () { + expect(p.project(new L.LatLng(-85.0511287798, -180))).near(new L.Point(-20037508, -20037508)); + }); + + it("projects other points", function () { + expect(p.project(new L.LatLng(50, 30))).near(new L.Point(3339584, 6446275)); + + // from https://github.com/Leaflet/Leaflet/issues/1578 + expect(p.project(new L.LatLng(51.9371170300465, 80.11230468750001))) + .near(new L.Point(8918060.96409, 6788763.38325)); + }); + }); + + describe("#unproject", function () { + function pr(point) { + return p.project(p.unproject(point)); + } + + it("unprojects a center point", function () { + expect(pr(new L.Point(0, 0))).near(new L.Point(0, 0)); + }); + + it("unprojects pi points", function () { + expect(pr(new L.Point(-Math.PI, Math.PI))).near(new L.Point(-Math.PI, Math.PI)); + expect(pr(new L.Point(-Math.PI, -Math.PI))).near(new L.Point(-Math.PI, -Math.PI)); + + expect(pr(new L.Point(0.523598775598, 1.010683188683))).near(new L.Point(0.523598775598, 1.010683188683)); + }); + + it('unprojects other points', function () { + // from https://github.com/Leaflet/Leaflet/issues/1578 + expect(pr(new L.Point(8918060.964088084, 6755099.410887127))); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/BoundsSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/BoundsSpec.js new file mode 100644 index 000000000..9eafba842 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/BoundsSpec.js @@ -0,0 +1,111 @@ +describe('Bounds', function () { + var a, b, c; + + beforeEach(function () { + a = new L.Bounds( + new L.Point(14, 12), // left, top + new L.Point(30, 40)); // right, bottom + b = new L.Bounds([ + new L.Point(20, 12), // center, top + new L.Point(14, 20), // left, middle + new L.Point(30, 40) // right, bottom + ]); + c = new L.Bounds(); + }); + + describe('constructor', function () { + it('creates bounds with proper min & max on (Point, Point)', function () { + expect(a.min).to.eql(new L.Point(14, 12)); + expect(a.max).to.eql(new L.Point(30, 40)); + }); + it('creates bounds with proper min & max on (Point[])', function () { + expect(b.min).to.eql(new L.Point(14, 12)); + expect(b.max).to.eql(new L.Point(30, 40)); + }); + }); + + describe('#extend', function () { + it('extends the bounds to contain the given point', function () { + a.extend(new L.Point(50, 20)); + expect(a.min).to.eql(new L.Point(14, 12)); + expect(a.max).to.eql(new L.Point(50, 40)); + + b.extend(new L.Point(25, 50)); + expect(b.min).to.eql(new L.Point(14, 12)); + expect(b.max).to.eql(new L.Point(30, 50)); + }); + }); + + describe('#getCenter', function () { + it('returns the center point', function () { + expect(a.getCenter()).to.eql(new L.Point(22, 26)); + }); + }); + + describe('#contains', function () { + it('contains other bounds or point', function () { + a.extend(new L.Point(50, 10)); + expect(a.contains(b)).to.be.ok(); + expect(b.contains(a)).to.not.be.ok(); + expect(a.contains(new L.Point(24, 25))).to.be.ok(); + expect(a.contains(new L.Point(54, 65))).to.not.be.ok(); + }); + }); + + describe('#isValid', function () { + it('returns true if properly set up', function () { + expect(a.isValid()).to.be.ok(); + }); + it('returns false if is invalid', function () { + expect(c.isValid()).to.not.be.ok(); + }); + it('returns true if extended', function () { + c.extend([0, 0]); + expect(c.isValid()).to.be.ok(); + }); + }); + + describe('#getSize', function () { + it('returns the size of the bounds as point', function () { + expect(a.getSize()).to.eql(new L.Point(16, 28)); + }); + }); + + describe('#intersects', function () { + it('returns true if bounds intersect', function () { + expect(a.intersects(b)).to.be(true); + expect(a.intersects(new L.Bounds(new L.Point(100, 100), new L.Point(120, 120)))).to.eql(false); + }); + }); + + describe('#getBottomLeft', function () { + it('returns the proper bounds bottom-left value', function () { + expect(a.getBottomLeft()).to.eql(new L.Point(14, 40)); // left, bottom + }); + }); + + describe('#getTopRight', function () { + it('returns the proper bounds top-right value', function () { + expect(a.getTopRight()).to.eql(new L.Point(30, 12)); // right, top + }); + }); + + describe('#getTopLeft', function () { + it('returns the proper bounds top-left value', function () { + expect(a.getTopLeft()).to.eql(new L.Point(14, 12)); // left, top + }); + }); + + describe('#getBottomRight', function () { + it('returns the proper bounds bottom-right value', function () { + expect(a.getBottomRight()).to.eql(new L.Point(30, 40)); // left, bottom + }); + }); + + describe('L.bounds factory', function () { + it('creates bounds from array of number arrays', function () { + var bounds = L.bounds([[14, 12], [30, 40]]); + expect(bounds).to.eql(a); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/LineUtilSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/LineUtilSpec.js new file mode 100644 index 000000000..c09ac7617 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/LineUtilSpec.js @@ -0,0 +1,90 @@ +describe('LineUtil', function () { + + describe('#clipSegment', function () { + + var bounds; + + beforeEach(function () { + bounds = L.bounds([5, 0], [15, 10]); + }); + + it('clips a segment by bounds', function () { + var a = new L.Point(0, 0); + var b = new L.Point(15, 15); + + var segment = L.LineUtil.clipSegment(a, b, bounds); + + expect(segment[0]).to.eql(new L.Point(5, 5)); + expect(segment[1]).to.eql(new L.Point(10, 10)); + + var c = new L.Point(5, -5); + var d = new L.Point(20, 10); + + var segment2 = L.LineUtil.clipSegment(c, d, bounds); + + expect(segment2[0]).to.eql(new L.Point(10, 0)); + expect(segment2[1]).to.eql(new L.Point(15, 5)); + }); + + it('uses last bit code and reject segments out of bounds', function () { + var a = new L.Point(15, 15); + var b = new L.Point(25, 20); + var segment = L.LineUtil.clipSegment(a, b, bounds, true); + + expect(segment).to.be(false); + }); + + it('can round numbers in clipped bounds', function () { + var a = new L.Point(4, 5); + var b = new L.Point(8, 6); + + var segment1 = L.LineUtil.clipSegment(a, b, bounds); + + expect(segment1[0]).to.eql(new L.Point(5, 5.25)); + expect(segment1[1]).to.eql(b); + + var segment2 = L.LineUtil.clipSegment(a, b, bounds, false, true); + + expect(segment2[0]).to.eql(new L.Point(5, 5)); + expect(segment2[1]).to.eql(b); + }); + }); + + describe('#pointToSegmentDistance & #closestPointOnSegment', function () { + + var p1 = new L.Point(0, 10); + var p2 = new L.Point(10, 0); + var p = new L.Point(0, 0); + + it('calculates distance from point to segment', function () { + expect(L.LineUtil.pointToSegmentDistance(p, p1, p2)).to.eql(Math.sqrt(200) / 2); + }); + + it('calculates point closest to segment', function () { + expect(L.LineUtil.closestPointOnSegment(p, p1, p2)).to.eql(new L.Point(5, 5)); + }); + }); + + describe('#simplify', function () { + it('simplifies polylines according to tolerance', function () { + var points = [ + new L.Point(0, 0), + new L.Point(0.01, 0), + new L.Point(0.5, 0.01), + new L.Point(0.7, 0), + new L.Point(1, 0), + new L.Point(1.999, 0.999), + new L.Point(2, 1) + ]; + + var simplified = L.LineUtil.simplify(points, 0.1); + + expect(simplified).to.eql([ + new L.Point(0, 0), + new L.Point(1, 0), + new L.Point(2, 1) + ]); + }); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/PointSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/PointSpec.js new file mode 100644 index 000000000..ea53ad735 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/PointSpec.js @@ -0,0 +1,116 @@ +describe("Point", function () { + + describe('constructor', function () { + + it("creates a point with the given x and y", function () { + var p = new L.Point(1.5, 2.5); + expect(p.x).to.eql(1.5); + expect(p.y).to.eql(2.5); + }); + + it("rounds the given x and y if the third argument is true", function () { + var p = new L.Point(1.3, 2.7, true); + expect(p.x).to.eql(1); + expect(p.y).to.eql(3); + }); + }); + + describe('#subtract', function () { + it('subtracts the given point from this one', function () { + var a = new L.Point(50, 30), + b = new L.Point(20, 10); + expect(a.subtract(b)).to.eql(new L.Point(30, 20)); + }); + }); + + describe('#add', function () { + it('adds given point to this one', function () { + expect(new L.Point(50, 30).add(new L.Point(20, 10))).to.eql(new L.Point(70, 40)); + }); + }); + + describe('#divideBy', function () { + it('divides this point by the given amount', function () { + expect(new L.Point(50, 30).divideBy(5)).to.eql(new L.Point(10, 6)); + }); + }); + + describe('#multiplyBy', function () { + it('multiplies this point by the given amount', function () { + expect(new L.Point(50, 30).multiplyBy(2)).to.eql(new L.Point(100, 60)); + }); + }); + + describe('#floor', function () { + it('returns a new point with floored coordinates', function () { + expect(new L.Point(50.56, 30.123).floor()).to.eql(new L.Point(50, 30)); + expect(new L.Point(-50.56, -30.123).floor()).to.eql(new L.Point(-51, -31)); + }); + }); + + describe('#trunc', function () { + it('returns a new point with truncated coordinates', function () { + expect(new L.Point(50.56, 30.123).trunc()).to.eql(new L.Point(50, 30)); + expect(new L.Point(-50.56, -30.123).trunc()).to.eql(new L.Point(-50, -30)); + }); + }); + + describe('#distanceTo', function () { + it('calculates distance between two points', function () { + var p1 = new L.Point(0, 30); + var p2 = new L.Point(40, 0); + expect(p1.distanceTo(p2)).to.eql(50.0); + }); + }); + + describe('#equals', function () { + it('returns true if points are equal', function () { + var p1 = new L.Point(20.4, 50.12); + var p2 = new L.Point(20.4, 50.12); + var p3 = new L.Point(20.5, 50.13); + + expect(p1.equals(p2)).to.be(true); + expect(p1.equals(p3)).to.be(false); + }); + }); + + describe('#contains', function () { + it('returns true if the point is bigger in absolute dimensions than the passed one', function () { + var p1 = new L.Point(50, 30), + p2 = new L.Point(-40, 20), + p3 = new L.Point(60, -20), + p4 = new L.Point(-40, -40); + + expect(p1.contains(p2)).to.be(true); + expect(p1.contains(p3)).to.be(false); + expect(p1.contains(p4)).to.be(false); + }); + }); + + describe('#toString', function () { + it('formats a string out of point coordinates', function () { + expect(new L.Point(50, 30) + '').to.eql('Point(50, 30)'); + expect(new L.Point(50.1234567, 30.1234567) + '').to.eql('Point(50.123457, 30.123457)'); + }); + }); + + describe('L.point factory', function () { + it('leaves L.Point instances as is', function () { + var p = new L.Point(50, 30); + expect(L.point(p)).to.be(p); + }); + it('creates a point out of three arguments', function () { + expect(L.point(50.1, 30.1, true)).to.eql(new L.Point(50, 30)); + }); + it('creates a point from an array of coordinates', function () { + expect(L.point([50, 30])).to.eql(new L.Point(50, 30)); + }); + it("creates a point from an object with x and y properties", function () { + expect(L.point({x: 50, y: 30})).to.eql(new L.Point(50, 30)); + }); + it('does not fail on invalid arguments', function () { + expect(L.point(undefined)).to.be(undefined); + expect(L.point(null)).to.be(null); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/PolyUtilSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/PolyUtilSpec.js new file mode 100644 index 000000000..d4bc35907 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/PolyUtilSpec.js @@ -0,0 +1,42 @@ +describe('PolyUtil', function () { + + describe('#clipPolygon', function () { + it('clips polygon by bounds', function () { + var bounds = L.bounds([0, 0], [10, 10]); + + var points = [ + new L.Point(5, 5), + new L.Point(15, 10), + new L.Point(10, 15) + ]; + + // check clip without rounding + var clipped = L.PolyUtil.clipPolygon(points, bounds); + + for (var i = 0, len = clipped.length; i < len; i++) { + delete clipped[i]._code; + } + + expect(clipped).to.eql([ + new L.Point(7.5, 10), + new L.Point(5, 5), + new L.Point(10, 7.5), + new L.Point(10, 10) + ]); + + // check clip with rounding + var clippedRounded = L.PolyUtil.clipPolygon(points, bounds, true); + + for (i = 0, len = clippedRounded.length; i < len; i++) { + delete clippedRounded[i]._code; + } + + expect(clippedRounded).to.eql([ + new L.Point(8, 10), + new L.Point(5, 5), + new L.Point(10, 8), + new L.Point(10, 10) + ]); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/TransformationSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/TransformationSpec.js new file mode 100644 index 000000000..35e6e9719 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/geometry/TransformationSpec.js @@ -0,0 +1,41 @@ +describe("Transformation", function () { + var t, p; + + beforeEach(function () { + t = new L.Transformation(1, 2, 3, 4); + p = new L.Point(10, 20); + }); + + describe('#transform', function () { + it("performs a transformation", function () { + var p2 = t.transform(p, 2); + expect(p2).to.eql(new L.Point(24, 128)); + }); + it('assumes a scale of 1 if not specified', function () { + var p2 = t.transform(p); + expect(p2).to.eql(new L.Point(12, 64)); + }); + }); + + describe('#untransform', function () { + it("performs a reverse transformation", function () { + var p2 = t.transform(p, 2); + var p3 = t.untransform(p2, 2); + expect(p3).to.eql(p); + }); + it('assumes a scale of 1 if not specified', function () { + var p2 = t.transform(p); + expect(t.untransform(new L.Point(12, 64))).to.eql(new L.Point(10, 20)); + }); + }); + + describe('#constructor', function () { + it("allows an array property for a", function () { + var t2 = L.transformation([1, 2, 3, 4]); + expect(t._a).to.eql(t2._a); + expect(t._b).to.eql(t2._b); + expect(t._c).to.eql(t2._c); + expect(t._d).to.eql(t2._d); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/FeatureGroupSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/FeatureGroupSpec.js new file mode 100644 index 000000000..06df8a8da --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/FeatureGroupSpec.js @@ -0,0 +1,86 @@ +describe('FeatureGroup', function () { + var map; + beforeEach(function () { + map = L.map(document.createElement('div')); + map.setView([0, 0], 1); + }); + describe("#_propagateEvent", function () { + var marker; + beforeEach(function () { + marker = L.marker([0, 0]); + }); + describe("when a Marker is added to multiple FeatureGroups ", function () { + it("e.propagatedFrom should be the Marker", function () { + var fg1 = L.featureGroup(), + fg2 = L.featureGroup(); + + fg1.addLayer(marker); + fg2.addLayer(marker); + + var wasClicked1, + wasClicked2; + + fg2.on('click', function (e) { + expect(e.propagatedFrom).to.be(marker); + expect(e.target).to.be(fg2); + wasClicked2 = true; + }); + + fg1.on('click', function (e) { + expect(e.propagatedFrom).to.be(marker); + expect(e.target).to.be(fg1); + wasClicked1 = true; + }); + + marker.fire('click', {type: 'click'}, true); + + expect(wasClicked1).to.be(true); + expect(wasClicked2).to.be(true); + }); + }); + }); + describe('addLayer', function () { + it('adds the layer', function () { + var fg = L.featureGroup(), + marker = L.marker([0, 0]); + + expect(fg.hasLayer(marker)).to.be(false); + + fg.addLayer(marker); + + expect(fg.hasLayer(marker)).to.be(true); + }); + it('supports non-evented layers', function () { + var fg = L.featureGroup(), + g = L.layerGroup(); + + expect(fg.hasLayer(g)).to.be(false); + + fg.addLayer(g); + + expect(fg.hasLayer(g)).to.be(true); + }); + }); + describe('removeLayer', function () { + it('removes the layer passed to it', function () { + var fg = L.featureGroup(), + marker = L.marker([0, 0]); + + fg.addLayer(marker); + expect(fg.hasLayer(marker)).to.be(true); + + fg.removeLayer(marker); + expect(fg.hasLayer(marker)).to.be(false); + }); + it('removes the layer passed to it by id', function () { + var fg = L.featureGroup(), + marker = L.marker([0, 0]); + + fg.addLayer(marker); + expect(fg.hasLayer(marker)).to.be(true); + + fg.removeLayer(L.stamp(marker)); + expect(fg.hasLayer(marker)).to.be(false); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/GeoJSONSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/GeoJSONSpec.js new file mode 100644 index 000000000..944e9edc5 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/GeoJSONSpec.js @@ -0,0 +1,473 @@ +describe("L.GeoJSON", function () { + + describe("addData", function () { + var geojson = { + type: 'Feature', + properties: {}, + geometry: { + type: 'Point', + coordinates: [20, 10, 5] + } + }, geojsonEmpty = { + type: 'Feature', + properties: {}, + geometry: null + }; + + it("sets feature property on member layers", function () { + var layer = new L.GeoJSON(); + layer.addData(geojson); + expect(layer.getLayers()[0].feature).to.eql(geojson); + }); + + it("normalizes a geometry to a Feature", function () { + var layer = new L.GeoJSON(); + layer.addData(geojson.geometry); + expect(layer.getLayers()[0].feature).to.eql(geojson); + }); + + it("accepts geojson with null geometry", function () { + var layer = new L.GeoJSON(); + layer.addData(geojsonEmpty); + expect(layer.getLayers().length).to.eql(0); + }); + }); + + describe('resetStyle', function () { + + it('should reset init options', function () { + var feature = { + type: 'Feature', + geometry: { + type: 'LineString', + coordinates:[[-2.35, 51.38], [-2.38, 51.38]] + } + }; + var geojson = L.geoJSON(feature, {weight: 7, color: 'chocolate'}); + geojson.setStyle({weight: 22, color: 'coral'}); + var layer = geojson.getLayers()[0]; + expect(layer.options.weight).to.be(22); + expect(layer.options.color).to.be('coral'); + geojson.resetStyle(layer); + expect(layer.options.weight).to.be(7); + expect(layer.options.color).to.be('chocolate'); + }); + + }); + +}); + +describe("L.Marker#toGeoJSON", function () { + it("returns a 2D Point object", function () { + var marker = new L.Marker([10, 20]); + expect(marker.toGeoJSON().geometry).to.eql({ + type: 'Point', + coordinates: [20, 10] + }); + }); + + it("returns a 3D Point object", function () { + var marker = new L.Marker([10, 20, 30]); + expect(marker.toGeoJSON().geometry).to.eql({ + type: 'Point', + coordinates: [20, 10, 30] + }); + }); + + it('should allow specific precisions', function () { + var marker = new L.Marker([10.123456, 20.123456, 30.123456]); + expect(marker.toGeoJSON(3).geometry).to.eql({ + type: 'Point', + coordinates: [20.123, 10.123, 30.123] + }); + }); +}); + +describe("L.Circle#toGeoJSON", function () { + it("returns a 2D Point object", function () { + var circle = new L.Circle([10, 20], 100); + expect(circle.toGeoJSON().geometry).to.eql({ + type: 'Point', + coordinates: [20, 10] + }); + }); + + it("returns a 3D Point object", function () { + var circle = new L.Circle([10, 20, 30], 100); + expect(circle.toGeoJSON().geometry).to.eql({ + type: 'Point', + coordinates: [20, 10, 30] + }); + }); + + it('should allow specific precisions', function () { + var circle = new L.Circle([10.1234, 20.1234, 30.1234], 100); + expect(circle.toGeoJSON(3).geometry).to.eql({ + type: 'Point', + coordinates: [20.123, 10.123, 30.123] + }); + }); +}); + +describe("L.CircleMarker#toGeoJSON", function () { + it("returns a 2D Point object", function () { + var marker = new L.CircleMarker([10, 20]); + expect(marker.toGeoJSON().geometry).to.eql({ + type: 'Point', + coordinates: [20, 10] + }); + }); + + it("returns a 3D Point object", function () { + var marker = new L.CircleMarker([10, 20, 30]); + expect(marker.toGeoJSON().geometry).to.eql({ + type: 'Point', + coordinates: [20, 10, 30] + }); + }); + + it("should allow specific precisions", function () { + var marker = new L.CircleMarker([10.1234, 20.1234]); + expect(marker.toGeoJSON(3).geometry).to.eql({ + type: 'Point', + coordinates: [20.123, 10.123] + }); + }); +}); + +describe("L.Polyline#toGeoJSON", function () { + it("returns a 2D LineString object", function () { + var polyline = new L.Polyline([[10, 20], [2, 5]]); + expect(polyline.toGeoJSON().geometry).to.eql({ + type: 'LineString', + coordinates: [[20, 10], [5, 2]] + }); + }); + + it("returns a 3D LineString object", function () { + var polyline = new L.Polyline([[10, 20, 30], [2, 5, 10]]); + expect(polyline.toGeoJSON().geometry).to.eql({ + type: 'LineString', + coordinates: [[20, 10, 30], [5, 2, 10]] + }); + }); + + it("should allow specific precisions", function () { + var polyline = new L.Polyline([[10.1234, 20.1234, 30.1234], [2.1234, 5.1234, 10.1234]]); + expect(polyline.toGeoJSON(3).geometry).to.eql({ + type: 'LineString', + coordinates: [[20.123, 10.123, 30.123], [5.123, 2.123, 10.123]] + }); + }); +}); + +describe("L.Polyline (multi) #toGeoJSON", function () { + it("returns a 2D MultiLineString object", function () { + var multiPolyline = new L.Polyline([[[10, 20], [2, 5]], [[1, 2], [3, 4]]]); + expect(multiPolyline.toGeoJSON().geometry).to.eql({ + type: 'MultiLineString', + coordinates: [ + [[20, 10], [5, 2]], + [[2, 1], [4, 3]] + ] + }); + }); + + it("returns a 3D MultiLineString object", function () { + var multiPolyline = new L.Polyline([[[10, 20, 30], [2, 5, 10]], [[1, 2, 3], [4, 5, 6]]]); + expect(multiPolyline.toGeoJSON().geometry).to.eql({ + type: 'MultiLineString', + coordinates: [ + [[20, 10, 30], [5, 2, 10]], + [[2, 1, 3], [5, 4, 6]] + ] + }); + }); + + it("should allow specific precisions", function () { + var multiPolyline = new L.Polyline([[[10.1234, 20.1234, 30.1234], [2.1234, 5.1234, 10.1234]], [[1.1234, 2.1234, 3.1234], [4.1234, 5.1234, 6.1234]]]); + expect(multiPolyline.toGeoJSON(3).geometry).to.eql({ + type: 'MultiLineString', + coordinates: [ + [[20.123, 10.123, 30.123], [5.123, 2.123, 10.123]], + [[2.123, 1.123, 3.123], [5.123, 4.123, 6.123]] + ] + }); + }); +}); + +describe("L.Polygon#toGeoJSON", function () { + it("returns a 2D Polygon object (no holes) from a flat LatLngs array", function () { + var polygon = new L.Polygon([[1, 2], [3, 4], [5, 6]]); + expect(polygon.toGeoJSON().geometry).to.eql({ + type: 'Polygon', + coordinates: [[[2, 1], [4, 3], [6, 5], [2, 1]]] + }); + }); + + it("returns a 3D Polygon object (no holes) from a flat LatLngs array", function () { + var polygon = new L.Polygon([[1, 2, 3], [4, 5, 6], [7, 8, 9]]); + expect(polygon.toGeoJSON().geometry).to.eql({ + type: 'Polygon', + coordinates: [[[2, 1, 3], [5, 4, 6], [8, 7, 9], [2, 1, 3]]] + }); + }); + + it("returns a 2D Polygon object from a simple GeoJSON like input", function () { + var multiPolygon = new L.Polygon([[[1, 2], [3, 4], [5, 6]]]); + expect(multiPolygon.toGeoJSON().geometry).to.eql({ + type: 'Polygon', + coordinates: [ + [[2, 1], [4, 3], [6, 5], [2, 1]] + ] + }); + }); + + it("returns a 3D MultiPolygon object from a simple GeoJSON like input", function () { + var multiPolygon = new L.Polygon([[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]); + expect(multiPolygon.toGeoJSON().geometry).to.eql({ + type: 'Polygon', + coordinates: [ + [[2, 1, 3], [5, 4, 6], [8, 7, 9], [2, 1, 3]] + ] + }); + }); + + it("returns a 2D Polygon object (with holes)", function () { + var polygon = new L.Polygon([[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]]); + expect(polygon.toGeoJSON().geometry).to.eql({ + type: 'Polygon', + coordinates: [ + [[2, 1], [4, 3], [6, 5], [2, 1]], + [[8, 7], [10, 9], [12, 11], [8, 7]] + ] + }); + }); + + it("returns a 3D Polygon object (with holes)", function () { + var polygon = new L.Polygon([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]]]); + expect(polygon.toGeoJSON().geometry).to.eql({ + type: 'Polygon', + coordinates: [ + [[2, 1, 3], [5, 4, 6], [8, 7, 9], [2, 1, 3]], + [[11, 10, 12], [14, 13, 15], [17, 16, 18], [11, 10, 12]] + ] + }); + }); + + it("should allow specific precisions", function () { + var polygon = new L.Polygon([[1.1234, 2.1234], [3.1234, 4.1234], [5.1234, 6.1234]]); + expect(polygon.toGeoJSON(3).geometry).to.eql({ + type: 'Polygon', + coordinates: [[[2.123, 1.123], [4.123, 3.123], [6.123, 5.123], [2.123, 1.123]]] + }); + }); +}); + +describe("L.Polygon (multi) #toGeoJSON", function () { + it("returns a 2D MultiPolygon object", function () { + var multiPolygon = new L.Polygon([[[[1, 2], [3, 4], [5, 6]]]]); + expect(multiPolygon.toGeoJSON().geometry).to.eql({ + type: 'MultiPolygon', + coordinates: [ + [[[2, 1], [4, 3], [6, 5], [2, 1]]] + ] + }); + }); + + it("returns a 3D MultiPolygon object", function () { + var multiPolygon = new L.Polygon([[[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]]); + expect(multiPolygon.toGeoJSON().geometry).to.eql({ + type: 'MultiPolygon', + coordinates: [ + [[[2, 1, 3], [5, 4, 6], [8, 7, 9], [2, 1, 3]]] + ] + }); + }); + + it("returns a 2D MultiPolygon object with two polygons", function () { + var multiPolygon = new L.Polygon([[[[1, 2], [3, 4], [5, 6]]], [[[7, 8], [9, 10], [11, 12]]]]); + expect(multiPolygon.toGeoJSON().geometry).to.eql({ + type: 'MultiPolygon', + coordinates: [ + [[[2, 1], [4, 3], [6, 5], [2, 1]]], + [[[8, 7], [10, 9], [12, 11], [8, 7]]] + ] + }); + }); + + it("returns a 2D MultiPolygon object with polygon having a hole", function () { + var multiPolygon = new L.Polygon([[[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]]]); + expect(multiPolygon.toGeoJSON().geometry).to.eql({ + type: 'MultiPolygon', + coordinates: [ + [[[2, 1], [4, 3], [6, 5], [2, 1]], [[8, 7], [10, 9], [12, 11], [8, 7]]] + ] + }); + }); + + it("should allow specific precisions", function () { + var multiPolygon = new L.Polygon([[[[1.1234, 2.1234], [3.1234, 4.1234], [5.1234, 6.1234]]]]); + expect(multiPolygon.toGeoJSON(3).geometry).to.eql({ + type: 'MultiPolygon', + coordinates: [ + [[[2.123, 1.123], [4.123, 3.123], [6.123, 5.123], [2.123, 1.123]]] + ] + }); + }); +}); + +describe("L.LayerGroup#toGeoJSON", function () { + it("returns a 2D FeatureCollection object", function () { + var marker = new L.Marker([10, 20]), + polyline = new L.Polyline([[10, 20], [2, 5]]), + layerGroup = new L.LayerGroup([marker, polyline]); + expect(layerGroup.toGeoJSON()).to.eql({ + type: 'FeatureCollection', + features: [marker.toGeoJSON(), polyline.toGeoJSON()] + }); + }); + + it("returns a 3D FeatureCollection object", function () { + var marker = new L.Marker([10, 20, 30]), + polyline = new L.Polyline([[10, 20, 30], [2, 5, 10]]), + layerGroup = new L.LayerGroup([marker, polyline]); + expect(layerGroup.toGeoJSON()).to.eql({ + type: 'FeatureCollection', + features: [marker.toGeoJSON(), polyline.toGeoJSON()] + }); + }); + + it("ensures that every member is a Feature", function () { + var tileLayer = new L.TileLayer(), + layerGroup = new L.LayerGroup([tileLayer]); + + tileLayer.toGeoJSON = function () { + return { + type: 'Point', + coordinates: [20, 10] + }; + }; + + expect(layerGroup.toGeoJSON()).to.eql({ + type: 'FeatureCollection', + features: [{ + type: 'Feature', + properties: {}, + geometry: { + type: 'Point', + coordinates: [20, 10] + } + }] + }); + }); + + it('roundtrips GeometryCollection features', function () { + var json = { + "type": "FeatureCollection", + "features": [{ + "type": "Feature", + "geometry": { + "type": "GeometryCollection", + "geometries": [{ + "type": "LineString", + "coordinates": [[-122.4425587930444, 37.80666418607323], [-122.4428379594768, 37.80663578323093]] + }, { + "type": "LineString", + "coordinates": [ + [-122.4425509770566, 37.80662588061205], + [-122.4428340530617, 37.8065999493009] + ] + }] + }, + "properties": { + "name": "SF Marina Harbor Master" + } + }] + }; + + var expected = { + "type": "FeatureCollection", + "features": [{ + "type": "Feature", + "geometry": { + "type": "GeometryCollection", + "geometries": [{ + "type": "LineString", + "coordinates": [[-122.442559, 37.806664], [-122.442838, 37.806636]] + }, { + "type": "LineString", + "coordinates": [[-122.442551, 37.806626], [-122.442834, 37.8066]] + }] + }, + "properties": { + "name": "SF Marina Harbor Master" + } + }] + }; + expect(L.geoJSON(json).toGeoJSON()).to.eql(expected); + }); + + it('roundtrips MultiPoint features', function () { + var json = { + "type": "FeatureCollection", + "features": [{ + "type": "Feature", + "geometry": { + "type": "MultiPoint", + "coordinates": [[-122.4425587930444, 37.80666418607323], [-122.4428379594768, 37.80663578323093]] + }, + "properties": { + "name": "Test MultiPoints" + } + }] + }; + + var expected = { + "type": "FeatureCollection", + "features": [{ + "type": "Feature", + "geometry": { + "type": "MultiPoint", + "coordinates": [[-122.442559, 37.806664], [-122.442838, 37.806636]] + }, + "properties": { + "name": "Test MultiPoints" + } + }] + }; + expect(L.geoJSON(json).toGeoJSON()).to.eql(expected); + }); + + it("omits layers which do not implement toGeoJSON", function () { + var tileLayer = new L.TileLayer(), + layerGroup = new L.LayerGroup([tileLayer]); + expect(layerGroup.toGeoJSON()).to.eql({ + type: 'FeatureCollection', + features: [] + }); + }); + + it('should return only one FeatureCollection for nested LayerGroups', function () { + var layerGroup = new L.LayerGroup([ + new L.LayerGroup([new L.Marker([-41.3330287, 173.2008273])]), + new L.Marker([-41.273356, 173.287278]) + ]); + + var geoJSON = layerGroup.toGeoJSON(); + + expect(geoJSON.features.length).to.eql(2); + expect(geoJSON.features[0].type).to.eql("Feature"); + expect(geoJSON.features[1].type).to.eql("Feature"); + }); + + it("should allow specific precisions", function () { + var marker = new L.Marker([10, 20]), + polyline = new L.Polyline([[10, 20], [2, 5]]), + layerGroup = new L.LayerGroup([marker, polyline]); + expect(layerGroup.toGeoJSON(3)).to.eql({ + type: 'FeatureCollection', + features: [marker.toGeoJSON(3), polyline.toGeoJSON(3)] + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/ImageOverlaySpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/ImageOverlaySpec.js new file mode 100644 index 000000000..6f1616a8e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/ImageOverlaySpec.js @@ -0,0 +1,186 @@ +describe('ImageOverlay', function () { + describe('#setStyle', function () { + it('sets opacity', function () { + var overlay = L.imageOverlay().setStyle({opacity: 0.5}); + expect(overlay.options.opacity).to.equal(0.5); + }); + }); + describe('#setBounds', function () { + it('sets bounds', function () { + var bounds = new L.LatLngBounds( + new L.LatLng(14, 12), + new L.LatLng(30, 40)); + var overlay = L.imageOverlay().setBounds(bounds); + expect(overlay._bounds).to.equal(bounds); + }); + }); + describe("_image", function () { + var c, map, overlay; + // Url for testing errors + var errorUrl = 'data:image/false;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAT1JREFUOI2dk79qwlAUxr9zcKmxbyAWh0IIDqJrcchkX6ODrn2TDAWRPEkyKKVzBxHJkKFoySP0mlLhnA5NbIgmpf6my73n+853/xFKRLY9UJEpAy6Am2x6q8xLYZ73omhVrKd88DocNpvGPBHwUDYtIiL+9X7/2EmS9GiQiUMC7urER1RfLGPGnSRJGQCyzidiy/Nged6pAdHoo9XyAIAj2x78FfscBEw3jtNnFZn+V5zDIhPOTvsiFHAZv1d1SYIuXyrOaQDYArg9t3gIw1qxML81lHlJFQZfQVBrwKoLFuZ5VUHlO8ggVZ97UbQSEf9cwSEMq7ehOrPjeE0A8N5uXxnLCkA0qs2cIcBzM03vu7vdJwNAJ0lSy5hxVZJy51wMFH5jzsZx+iwyUcBlkS7wc9qsuiBV347jdbH+G/fth7AzHdiJAAAAAElFTkSuQmCC'; + var blankUrl = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + + // Create map and overlay for each test + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + document.body.appendChild(c); + map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); // view needs to be set so when layer is added it is initilized + + overlay = L.imageOverlay(blankUrl, [[40.712216, -74.22655], [40.773941, -74.12544]], { + errorOverlayUrl: errorUrl, + className: 'my-custom-image-class' + }); + map.addLayer(overlay); + + var bounds = new L.LatLngBounds( + new L.LatLng(14, 12), + new L.LatLng(30, 40)); + overlay.setBounds(bounds); + }); + + // Clean up after each test run + afterEach(function () { + document.body.removeChild(c); + map.removeLayer(overlay); + overlay = null; + map = null; + }); + + function raiseImageEvent(event) { + var domEvent = document.createEvent('Event'); + domEvent.initEvent(event); + overlay._image.dispatchEvent(domEvent); + } + + describe('when loaded', function () { + it('should raise the load event', function () { + var loadRaised = sinon.spy(); + overlay.once('load', loadRaised); + raiseImageEvent('load'); + expect(loadRaised.called).to.be(true); + }); + }); + + describe('when load fails', function () { + it('should raise the error event', function () { + var errorRaised = sinon.spy(); + overlay.once('error', errorRaised); + raiseImageEvent('error'); + expect(errorRaised.called).to.be(true); + }); + it('should change the image to errorOverlayUrl', function () { + raiseImageEvent('error'); + expect(overlay._url).to.be(errorUrl); + expect(overlay._image.src).to.be(errorUrl); + }); + }); + + describe('className', function () { + it('should set image\'s class', function () { + expect(L.DomUtil.hasClass(overlay._image, 'my-custom-image-class')).to.be(true); + }); + }); + }); + + describe('#setZIndex', function () { + + var div, map; + var corner1 = L.latLng(40.712, -74.227), + corner2 = L.latLng(40.774, -74.125), + bounds = L.latLngBounds(corner1, corner2); + + beforeEach(function () { + div = document.createElement('div'); + div.style.width = '800px'; + div.style.height = '600px'; + div.style.visibility = 'hidden'; + + document.body.appendChild(div); + + map = L.map(div); + map.setView([0, 0], 1); // view needs to be set so when layer is added it is initilized + }); + + afterEach(function () { + document.body.removeChild(div); + }); + + it('sets the z-index of the image', function () { + var overlay = L.imageOverlay(); + overlay.setZIndex(10); + expect(overlay.options.zIndex).to.equal(10); + }); + + it('should update the z-index of the image if it has allready been added to the map', function () { + var overlay = L.imageOverlay('', bounds); + overlay.addTo(map); + expect(overlay._image.style.zIndex).to.be('1'); + + overlay.setZIndex('10'); + expect(overlay._image.style.zIndex).to.be('10'); + }); + + it('should set the z-index of the image when it is added to the map', function () { + var overlay = L.imageOverlay('', bounds); + overlay.setZIndex('10'); + overlay.addTo(map); + expect(overlay._image.style.zIndex).to.be('10'); + }); + + it('should use the z-index specified in options', function () { + var overlay = L.imageOverlay('', bounds, {zIndex: 20}); + overlay.addTo(map); + expect(overlay._image.style.zIndex).to.be('20'); + }); + + it('should be fluent', function () { + var overlay = L.imageOverlay(); + expect(overlay.setZIndex()).to.equal(overlay); + }); + }); + + // For tests that do not actually need to append the map container to the document. + // This saves PhantomJS memory. + describe('_image2', function () { + var c, map, overlay; + var blankUrl = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + var bounds = [[40.712216, -74.22655], [40.773941, -74.12544]]; + + // Create map and overlay for each test + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); // view needs to be set so when layer is added it is initialized + }); + + // Clean up after each test run + afterEach(function () { + map.removeLayer(overlay); + overlay = null; + map = null; + }); + + // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes + testCrossOriginValue(undefined, null); // Falsy value (other than empty string '') => no attribute set. + testCrossOriginValue(true, ''); + testCrossOriginValue('', ''); + testCrossOriginValue('anonymous', 'anonymous'); + testCrossOriginValue('use-credentials', 'use-credentials'); + + function testCrossOriginValue(crossOrigin, expectedValue) { + it('uses crossOrigin option value ' + crossOrigin, function () { + overlay = L.imageOverlay(blankUrl, bounds, { + crossOrigin: crossOrigin + }); + map.addLayer(overlay); + + expect(overlay._image.getAttribute('crossorigin')).to.be(expectedValue); + }); + } + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/LayerGroupSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/LayerGroupSpec.js new file mode 100644 index 000000000..3767e4b48 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/LayerGroupSpec.js @@ -0,0 +1,111 @@ +describe('LayerGroup', function () { + describe("#hasLayer", function () { + it("returns false when passed undefined, null, or false", function () { + var lg = L.layerGroup(); + expect(lg.hasLayer(undefined)).to.equal(false); + expect(lg.hasLayer(null)).to.equal(false); + expect(lg.hasLayer(false)).to.equal(false); + }); + }); + + describe("#addLayer", function () { + it('adds a layer', function () { + var lg = L.layerGroup(), + marker = L.marker([0, 0]); + + expect(lg.addLayer(marker)).to.eql(lg); + + expect(lg.hasLayer(marker)).to.be(true); + }); + }); + + describe("#removeLayer", function () { + it('removes a layer', function () { + var lg = L.layerGroup(), + marker = L.marker([0, 0]); + + lg.addLayer(marker); + expect(lg.removeLayer(marker)).to.eql(lg); + + expect(lg.hasLayer(marker)).to.be(false); + }); + }); + + describe("#clearLayers", function () { + it('removes all layers', function () { + var lg = L.layerGroup(), + marker = L.marker([0, 0]); + + lg.addLayer(marker); + expect(lg.clearLayers()).to.eql(lg); + + expect(lg.hasLayer(marker)).to.be(false); + }); + }); + + describe("#getLayers", function () { + it('gets all layers', function () { + var lg = L.layerGroup(), + marker = L.marker([0, 0]); + + lg.addLayer(marker); + + expect(lg.getLayers()).to.eql([marker]); + }); + }); + + describe("#eachLayer", function () { + it('iterates over all layers', function () { + var lg = L.layerGroup(), + marker = L.marker([0, 0]), + ctx = {foo: 'bar'}; + + lg.addLayer(marker); + + lg.eachLayer(function (layer) { + expect(layer).to.eql(marker); + expect(this).to.eql(ctx); + }, ctx); + }); + }); + + describe("#toGeoJSON", function () { + it('should return valid GeoJSON for a layer with a FeatureCollection', function () { + var geoJSON = { + "type":"FeatureCollection", + "features":[ + { + "type":"Feature", + "properties":{}, + "geometry": { + "type":"Point", + "coordinates": [78.3984375, 56.9449741808516] + } + } + ] + }; + + var layerGroup = L.layerGroup(); + var layer = L.geoJSON(geoJSON); + layerGroup.addLayer(layer); + + L.geoJson(layerGroup.toGeoJSON()); + }); + }); + + describe("#invoke", function () { + it('should invoke `setOpacity` method on every layer', function () { + var layers = [ + L.marker([0, 0]), + L.marker([1, 1]) + ]; + var lg = L.layerGroup(layers); + var opacity = 0.5; + + expect(layers[0].options.opacity).to.not.eql(opacity); + lg.invoke('setOpacity', opacity); + expect(layers[0].options.opacity).to.eql(opacity); + expect(layers[1].options.opacity).to.eql(opacity); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/PopupSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/PopupSpec.js new file mode 100644 index 000000000..a5451e296 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/PopupSpec.js @@ -0,0 +1,502 @@ +describe('Popup', function () { + + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + document.body.appendChild(c); + map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); + }); + + afterEach(function () { + document.body.removeChild(c); + }); + + it("closes on map click when map has closePopupOnClick option", function () { + map.options.closePopupOnClick = true; + + var popup = new L.Popup() + .setLatLng(new L.LatLng(55.8, 37.6)) + .openOn(map); + + happen.click(c); + + expect(map.hasLayer(popup)).to.be(false); + }); + + it("closes on map click when popup has closeOnClick option", function () { + map.options.closePopupOnClick = false; + + var popup = new L.Popup({closeOnClick: true}) + .setLatLng(new L.LatLng(55.8, 37.6)) + .openOn(map); + + happen.click(c); + + expect(map.hasLayer(popup)).to.be(false); + }); + + it("does not close on map click when popup has closeOnClick: false option", function () { + map.options.closePopupOnClick = true; + + var popup = new L.Popup({closeOnClick: false}) + .setLatLng(new L.LatLng(55.8, 37.6)) + .openOn(map); + + happen.click(c); + + expect(map.hasLayer(popup)).to.be(true); + }); + + it("toggles its visibility when marker is clicked", function () { + var marker = new L.Marker(new L.LatLng(55.8, 37.6)); + map.addLayer(marker); + + marker.bindPopup('Popup1'); + expect(map.hasLayer(marker._popup)).to.be(false); + + // toggle open popup + happen.click(marker._icon); + expect(map.hasLayer(marker._popup)).to.be(true); + + // toggle close popup + happen.click(marker._icon); + expect(map.hasLayer(marker._popup)).to.be(false); + }); + + it("it should use a popup with a function as content with a FeatureGroup", function () { + var marker1 = new L.Marker(new L.LatLng(55.8, 37.6)); + var marker2 = new L.Marker(new L.LatLng(54.6, 38.2)); + var group = new L.FeatureGroup([marker1, marker2]).addTo(map); + + marker1.description = "I'm marker 1."; + marker2.description = "I'm marker 2."; + group.bindPopup(function (layer) { + return layer.description; + }); + + map.options.closePopupOnClick = true; + + // toggle popup on marker1 + group.fire('click', { + latlng: new L.LatLng(55.8, 37.6), + layer: marker1 + }); + expect(map.hasLayer(group._popup)).to.be(true); + expect(group._popup._contentNode.innerHTML).to.be("I'm marker 1."); + + // toggle popup on marker2 + group.fire('click', { + latlng: new L.LatLng(54.6, 38.2), + layer: marker2 + }); + expect(map.hasLayer(group._popup)).to.be(true); + expect(group._popup._contentNode.innerHTML).to.be("I'm marker 2."); + }); + + it("it should function for popup content after bindPopup is called", function () { + var marker1 = new L.Marker(new L.LatLng(55.8, 37.6)); + var marker2 = new L.Marker(new L.LatLng(54.6, 38.2)); + var group = new L.FeatureGroup([marker1]).addTo(map); + + marker1.description = "I'm marker 1."; + marker2.description = "I'm marker 2."; + group.bindPopup(function (layer) { + return layer.description; + }); + + group.addLayer(marker2); + + map.options.closePopupOnClick = true; + + // toggle popup on marker1 + group.fire('click', { + latlng: new L.LatLng(55.8, 37.6), + layer: marker1 + }); + expect(map.hasLayer(group._popup)).to.be(true); + expect(group._popup._contentNode.innerHTML).to.be("I'm marker 1."); + + // toggle popup on marker2 + group.fire('click', { + latlng: new L.LatLng(54.6, 38.2), + layer: marker2 + }); + expect(map.hasLayer(group._popup)).to.be(true); + expect(group._popup._contentNode.innerHTML).to.be("I'm marker 2."); + }); + + it("should use a function for popup content when a source is passed to Popup", function () { + var marker = new L.Marker(new L.LatLng(55.8, 37.6)).addTo(map); + var popup = L.popup({}, marker); + + marker.description = "I am a marker."; + + marker.bindPopup(function (layer) { + return layer.description; + }); + + marker.fire('click', { + latlng: new L.LatLng(55.8, 37.6) + }); + + expect(map.hasLayer(marker._popup)).to.be(true); + expect(marker._popup._contentNode.innerHTML).to.be("I am a marker."); + }); + + it("triggers popupopen on marker when popup opens", function () { + var marker1 = new L.Marker(new L.LatLng(55.8, 37.6)); + var marker2 = new L.Marker(new L.LatLng(57.123076977278, 44.861962891635)); + + map.addLayer(marker1); + map.addLayer(marker2); + + marker1.bindPopup('Popup1'); + marker2.bindPopup('Popup2'); + + var spy = sinon.spy(); + + marker1.on('popupopen', spy); + + expect(spy.called).to.be(false); + marker2.openPopup(); + expect(spy.called).to.be(false); + marker1.openPopup(); + expect(spy.called).to.be(true); + }); + + it("triggers popupclose on marker when popup closes", function () { + var marker1 = new L.Marker(new L.LatLng(55.8, 37.6)); + var marker2 = new L.Marker(new L.LatLng(57.123076977278, 44.861962891635)); + + map.addLayer(marker1); + map.addLayer(marker2); + + marker1.bindPopup('Popup1'); + marker2.bindPopup('Popup2'); + + var spy = sinon.spy(); + + marker1.on('popupclose', spy); + + expect(spy.called).to.be(false); + marker2.openPopup(); + expect(spy.called).to.be(false); + marker1.openPopup(); + expect(spy.called).to.be(false); + marker2.openPopup(); + expect(spy.called).to.be(true); + marker1.openPopup(); + marker1.closePopup(); + expect(spy.callCount).to.be(2); + }); + + describe('should take into account icon popupAnchor option on', function () { + var latlng = new L.LatLng(55.8, 37.6); + var offset = new L.Point(20, 30); + var autoPanBefore; + var popupAnchorBefore; + var icon; + var marker1; + var marker2; + + before(function () { + autoPanBefore = L.Popup.prototype.options.autoPan; + L.Popup.prototype.options.autoPan = false; + popupAnchorBefore = L.Icon.Default.prototype.options.popupAnchor; + L.Icon.Default.prototype.options.popupAnchor = [0, 0]; + }); + + beforeEach(function () { + icon = new L.DivIcon({popupAnchor: offset}); + marker1 = new L.Marker(latlng); + marker2 = new L.Marker(latlng, {icon: icon}); + }); + + after(function () { + L.Popup.prototype.options.autoPan = autoPanBefore; + L.Icon.Default.prototype.options.popupAnchor = popupAnchorBefore; + }); + + it.skipInNonPhantom("non-any3d browsers", function () { + marker1.bindPopup('Popup').addTo(map); + marker1.openPopup(); + var defaultLeft = parseInt(marker1._popup._container.style.left, 10); + var defaultBottom = parseInt(marker1._popup._container.style.bottom, 10); + marker2.bindPopup('Popup').addTo(map); + marker2.openPopup(); + var offsetLeft = parseInt(marker2._popup._container.style.left, 10); + var offsetBottom = parseInt(marker2._popup._container.style.bottom, 10); + expect(offsetLeft - offset.x).to.eql(defaultLeft); + expect(offsetBottom + offset.y).to.eql(defaultBottom); + + // Now retry passing a popup instance to bindPopup + marker2.bindPopup(new L.Popup()); + marker2.openPopup(); + offsetLeft = parseInt(marker2._popup._container.style.left, 10); + offsetBottom = parseInt(marker2._popup._container.style.bottom, 10); + expect(offsetLeft - offset.x).to.eql(defaultLeft); + expect(offsetBottom + offset.y).to.eql(defaultBottom); + }); + + it.skipInPhantom("any3d browsers", function () { + marker1.bindPopup('Popup').addTo(map); + marker1.openPopup(); + var defaultLeft = marker1._popup._container._leaflet_pos.x; + var defaultTop = marker1._popup._container._leaflet_pos.y; + marker2.bindPopup('Popup').addTo(map); + marker2.openPopup(); + var offsetLeft = marker2._popup._container._leaflet_pos.x; + var offsetTop = marker2._popup._container._leaflet_pos.y; + expect(offsetLeft - offset.x).to.eql(defaultLeft); + expect(offsetTop - offset.y).to.eql(defaultTop); + + // Now retry passing a popup instance to bindPopup + marker2.bindPopup(new L.Popup()); + marker2.openPopup(); + offsetLeft = marker2._popup._container._leaflet_pos.x; + offsetTop = marker2._popup._container._leaflet_pos.y; + expect(offsetLeft - offset.x).to.eql(defaultLeft); + expect(offsetTop - offset.y).to.eql(defaultTop); + }); + }); + + it("prevents an underlying map click for Layer", function () { + var layer = new L.Polygon([[55.8, 37.6], [55.9, 37.7], [56.0, 37.8]]).addTo(map); + layer.bindPopup("layer popup"); + + var mapClicked = false; + map.on('click', function (e) { + mapClicked = true; + new L.Popup() + .setLatLng(e.latlng) + .setContent("map popup") + .openOn(map); + }); + + expect(map.hasLayer(layer._popup)).to.be(false); + happen.click(layer._path); + expect(mapClicked).to.be(false); + expect(map.hasLayer(layer._popup)).to.be(true); + }); + + + it("can open a popup with enter keypress when marker has focus", function () { + var layer = new L.Marker([55.8, 37.6]).addTo(map); + layer.bindPopup("layer popup"); + + happen.keypress(layer._icon, { + keyCode: 13 + }); + + expect(map.hasLayer(layer._popup)).to.be(true); + }); + + describe("autoPan option should pan popup into visibility", function () { + + // Helper function which calculates the offset of the map-container & popup-container in pixel + function getPopupOffset(map, popup) { + var mapOffset = map._container.getBoundingClientRect().top; + var popupOffset = popup._container.getBoundingClientRect().top; + return popupOffset - mapOffset; + } + + it("should not pan map to show popup content if autoPan is disabled", function (done) { + map.on('popupopen', function (e) { + var popupTopOffset = getPopupOffset(map, e.popup); + expect(popupTopOffset).to.be.below(0, "The upper edge of the popup should not be visible"); + done(); + }); + map.openPopup('
', L.latLng(58.4, 37.6), { + autoPan: false + }); + }); + + it("should pan map to show popup content if autoPan is enabled", function (done) { + map.on('popupopen', function (e) { + var popupTopOffset = getPopupOffset(map, e.popup); + expect(popupTopOffset).to.be(10, "The upper edge of the popup have a padding of 10"); + done(); + }); + map.openPopup('
', L.latLng(58.4, 37.6), { + autoPan: true, + autoPanPadding: L.point(10, 10) + }); + }); + + it("should pan map to show popup content if autoPan is enabled even when animating", function (done) { + map.on('popupopen', function (e) { + var popupTopOffset = getPopupOffset(map, e.popup); + expect(popupTopOffset).to.be(10); + done(); + }); + + map.panTo([55.8, 40.7], { + animate: true, + duration: 1 + }); + + map.openPopup('
', L.latLng(58.4, 37.6), { + autoPan: true, + autoPanPadding: L.point(10, 10) + }); + }); + }); +}); + +describe("L.Map#openPopup", function () { + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); + }); + + afterEach(function () { + if (document.body.contains(c)) { + document.body.removeChild(c); + } + }); + + it("adds the popup layer to the map", function () { + var popup = new L.Popup() + .setLatLng(new L.LatLng(55.8, 37.6)); + map.openPopup(popup); + expect(map.hasLayer(popup)).to.be(true); + }); + + it("sets popup location", function () { + var popup = new L.Popup(); + map.openPopup(popup, L.latLng(55.8, 37.6)); + expect(popup.getLatLng()).to.eql(L.latLng(55.8, 37.6)); + }); + + it("creates a popup from content", function () { + map.openPopup("

Hello World

", L.latLng(55.8, 37.6)); + expect(map._popup).to.be.an(L.Popup); + expect(map._popup.getContent()).to.eql("

Hello World

"); + }); + + it("closes existing popup", function () { + var p1 = new L.Popup().setLatLng(new L.LatLng(55.8, 37.6)); + var p2 = new L.Popup().setLatLng(new L.LatLng(55.8, 37.6)); + map.openPopup(p1); + map.openPopup(p2); + expect(map.hasLayer(p1)).to.be(false); + }); + + it("does not close existing popup with autoClose: false option", function () { + var p1 = new L.Popup({autoClose: false}).setLatLng(new L.LatLng(55.8, 37.6)); + var p2 = new L.Popup().setLatLng(new L.LatLng(55.8, 37.6)); + map.openPopup(p1); + map.openPopup(p2); + expect(map.hasLayer(p1)).to.be(true); + expect(map.hasLayer(p2)).to.be(true); + }); + + it('should not be closen when dragging map', function (done) { + document.body.appendChild(c); + c.style.position = 'absolute'; + c.style.left = 0; + c.style.top = 0; + c.style.zIndex = 10000; + var coords = map._container.getBoundingClientRect(); + var spy = sinon.spy(); + var p = new L.Popup().setLatLng(new L.LatLng(55.8, 37.6)); + map.openPopup(p); + expect(map.hasLayer(p)).to.be(true); + map.on('drag', spy); + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + expect(spy.called).to.be(true); + expect(map.hasLayer(p)).to.be(true); + done(); + }}); + var mouse = hand.growFinger('mouse'); + mouse.moveTo(coords.left + 100, coords.left + 100, 0) + .down().moveBy(10, 10, 20).up(); + }); + +}); + +describe('L.Layer#_popup', function () { + var c, map, marker; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); + marker = L.marker(L.latLng(55.8, 37.6)).addTo(map); + }); + + afterEach(function () { + if (document.body.contains(c)) { + document.body.removeChild(c); + } + }); + + it("only adds a popup to the map when opened", function () { + marker.bindPopup("new layer"); + expect(map.hasLayer(marker.getPopup())).to.be(false); + marker.openPopup(); + expect(map.hasLayer(marker.getPopup())).to.be(true); + }); + + it("keeps an open popup on the map when it's unbound from the layer", function () { + marker.bindPopup("new layer").openPopup(); + var popup = marker.getPopup(); + marker.unbindPopup(); + expect(map.hasLayer(popup)).to.be(true); + }); + + it("should not give an error when the marker has no popup", function () { + expect(function () { + marker.isPopupOpen(); + }).to.not.throwException(); + expect(marker.isPopupOpen()).to.be(false); + }); + + it("should show a popup as closed if it's never opened", function () { + marker.bindPopup("new layer"); + expect(marker.isPopupOpen()).to.be(false); + }); + + it("should show a popup as opend if it's opened", function () { + marker.bindPopup("new layer").openPopup(); + expect(marker.isPopupOpen()).to.be(true); + }); + + it("should show a popup as closed if it's opened and closed", function () { + marker.bindPopup("new layer").openPopup().closePopup(); + expect(marker.isPopupOpen()).to.be(false); + }); + + it("should show the popup as closed if it's unbound", function () { + marker.bindPopup("new layer").openPopup().unbindPopup(); + expect(function () { + marker.isPopupOpen(); + }).to.not.throwException(); + expect(marker.isPopupOpen()).to.be(false); + }); + + it('does not throw is popup is inmediately closed', function (done) { + + map.on('popupopen', function (ev) { + marker.closePopup(); + }); + + expect(function () { + marker.bindPopup("new layer").openPopup(); + done(); + }).to.not.throwException(); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/TooltipSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/TooltipSpec.js new file mode 100644 index 000000000..be4d3447f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/TooltipSpec.js @@ -0,0 +1,291 @@ +describe('Tooltip', function () { + + var c, map, p2ll, + center = [55.8, 37.6]; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + // Allow to use happen.at with determinist positions. + c.style.position = 'absolute'; + c.style.top = '0'; + c.style.left = '0'; + document.body.appendChild(c); + map = new L.Map(c); + map.setView(center, 6); + p2ll = function (x, y) { + return map.layerPointToLatLng([x, y]); + }; + }); + + afterEach(function () { + document.body.removeChild(c); + }); + + it("opens on marker mouseover and close on mouseout", function () { + var layer = new L.Marker(center).addTo(map); + + layer.bindTooltip('Tooltip'); + + happen.mouseover(layer._icon, {relatedTarget: map._container}); + + expect(map.hasLayer(layer._tooltip)).to.be(true); + + happen.mouseout(layer._icon, {relatedTarget: map._container}); + expect(map.hasLayer(layer._tooltip)).to.be(false); + }); + + it("stays open on marker when permanent", function () { + var layer = new L.Marker(center).addTo(map); + + layer.bindTooltip('Tooltip', {permanent: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + }); + + it("can be added with bindTooltip before added to the map", function () { + var layer = new L.Marker(center); + + layer.bindTooltip('Tooltip', {permanent: true}); + expect(map.hasLayer(layer._tooltip)).to.be(false); + layer.addTo(map); + expect(map.hasLayer(layer._tooltip)).to.be(true); + }); + + it("is removed when removing marker", function () { + var layer = new L.Marker(center).addTo(map); + + layer.bindTooltip('Tooltip', {permanent: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + layer.remove(); + expect(map.hasLayer(layer._tooltip)).to.be(false); + }); + + it("can be made interactive", function () { + var layer = new L.Marker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('Tooltip', {permanent: true, interactive: true}); + happen.click(layer._tooltip._container); + expect(spy.calledOnce).to.be(true); + }); + + it("can be forced on left direction", function () { + var layer = new L.Marker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('A long tooltip that should be displayed on the left', {permanent: true, direction: 'left', interactive: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + happen.at('click', 150, 180); // Marker is on the map center, which is 400px large. + expect(spy.calledOnce).to.be(true); + }); + + it("honours offset on left direction", function () { + var layer = new L.Marker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('A long tooltip that should be displayed on the left', {permanent: true, direction: 'left', interactive: true, offset: [-20, -20]}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + happen.at('click', 150, 180); + expect(spy.calledOnce).to.be(false); + happen.at('click', 130, 160); + expect(spy.calledOnce).to.be(true); + }); + + it("can be forced on top direction", function () { + var layer = L.circleMarker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'top', interactive: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + happen.at('click', 200, 180); // Marker is on the map center, which is 400px large. + expect(spy.calledOnce).to.be(true); + }); + + it("honours offset on top direction", function () { + var layer = L.circleMarker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'top', interactive: true, offset: [-20, -20]}); + happen.at('click', 200, 180); + expect(spy.calledOnce).to.be(false); + happen.at('click', 180, 150); + expect(spy.calledOnce).to.be(true); + }); + + it("can be forced on bottom direction", function () { + var layer = L.circleMarker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'bottom', interactive: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + happen.at('click', 200, 220); // Marker is on the map center, which is 400px large. + expect(spy.calledOnce).to.be(true); + }); + + it("honours offset on bottom direction", function () { + var layer = L.circleMarker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('A tooltip that should be displayed on the top', {permanent: true, direction: 'bottom', interactive: true, offset: [20, 20]}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + happen.at('click', 200, 220); + expect(spy.calledOnce).to.be(false); + happen.at('click', 220, 230); + expect(spy.calledOnce).to.be(true); + }); + + it("can be forced on center", function () { + var layer = new L.Marker(center).addTo(map); + var spy = sinon.spy(); + layer.on('click', spy); + + layer.bindTooltip('A tooltip that should be displayed on the center', {permanent: true, direction: 'center', interactive: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + happen.at('click', 150, 180); // Marker is on the map center, which is 400px large. + expect(spy.calledOnce).to.be(true); + }); + + it("honours opacity option", function () { + var layer = new L.Marker(center).addTo(map); + layer.bindTooltip('Tooltip', {permanent: true, opacity: 0.57}); + expect(layer._tooltip._container.style.opacity).to.eql(0.57); + }); + + it("can change opacity with setOpacity", function () { + var layer = new L.Marker(center).addTo(map); + layer.bindTooltip('Tooltip', {permanent: true}); + expect(layer._tooltip._container.style.opacity).to.eql(0.9); + layer._tooltip.setOpacity(0.57); + expect(layer._tooltip._container.style.opacity).to.eql(0.57); + }); + + it("it should use a tooltip with a function as content with a FeatureGroup", function () { + var marker1 = new L.Marker(new L.LatLng(55.8, 37.6), {description: "I'm marker 1."}); + var marker2 = new L.Marker(new L.LatLng(54.6, 38.2), {description: "I'm marker 2."}); + var group = new L.FeatureGroup([marker1, marker2]).addTo(map); + + group.bindTooltip(function (layer) { + return layer.options.description; + }); + + // toggle popup on marker1 + happen.mouseover(marker1._icon, {relatedTarget: map._container}); + expect(map.hasLayer(group._tooltip)).to.be(true); + expect(group._tooltip._container.innerHTML).to.be("I'm marker 1."); + + // toggle popup on marker2 + happen.mouseover(marker2._icon, {relatedTarget: map._container}); + expect(map.hasLayer(group._tooltip)).to.be(true); + expect(group._tooltip._container.innerHTML).to.be("I'm marker 2."); + }); + + it("opens on polygon mouseover and close on mouseout", function () { + var layer = new L.Polygon([[55.8, 37.6], [55.9, 37.6], [55.8, 37.5]]).addTo(map); + + layer.bindTooltip('Tooltip'); + + happen.mouseover(layer._path, {relatedTarget: map._container}); + + expect(map.hasLayer(layer._tooltip)).to.be(true); + + happen.mouseout(layer._path, {relatedTarget: map._container}); + expect(map.hasLayer(layer._tooltip)).to.be(false); + }); + + it("stays open on polygon when permanent", function () { + var layer = new L.Polygon([[55.8, 37.6], [55.9, 37.6], [55.8, 37.5]]).addTo(map); + + layer.bindTooltip('Tooltip', {permanent: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + }); + + it("can be added on polygon with bindTooltip before beind added to the map", function () { + var layer = new L.Polygon([[55.8, 37.6], [55.9, 37.6], [55.8, 37.5]]); + + layer.bindTooltip('Tooltip', {permanent: true}); + expect(map.hasLayer(layer._tooltip)).to.be(false); + layer.addTo(map); + expect(map.hasLayer(layer._tooltip)).to.be(true); + layer.remove(); + expect(map.hasLayer(layer._tooltip)).to.be(false); + layer.addTo(map); + expect(map.hasLayer(layer._tooltip)).to.be(true); + }); + + it("opens on polyline mouseover and close on mouseout", function () { + var layer = new L.Polyline([[55.8, 37.6], [55.9, 37.6], [55.8, 37.5]]).addTo(map); + + layer.bindTooltip('Tooltip'); + + happen.mouseover(layer._path, {relatedTarget: map._container}); + + expect(map.hasLayer(layer._tooltip)).to.be(true); + + happen.mouseout(layer._path, {relatedTarget: map._container}); + expect(map.hasLayer(layer._tooltip)).to.be(false); + }); + + it("stays open on polyline when permanent", function () { + var layer = new L.Polyline([[55.8, 37.6], [55.9, 37.6], [55.8, 37.5]]).addTo(map); + + layer.bindTooltip('Tooltip', {permanent: true}); + expect(map.hasLayer(layer._tooltip)).to.be(true); + }); + + it("can be added on polyline with bindTooltip before added to the map", function () { + var layer = new L.Polyline([[55.8, 37.6], [55.9, 37.6], [55.8, 37.5]]); + + layer.bindTooltip('Tooltip', {permanent: true}); + expect(map.hasLayer(layer._tooltip)).to.be(false); + layer.addTo(map); + expect(map.hasLayer(layer._tooltip)).to.be(true); + layer.remove(); + expect(map.hasLayer(layer._tooltip)).to.be(false); + layer.addTo(map); + expect(map.hasLayer(layer._tooltip)).to.be(true); + }); + + it.skipIfNotTouch("is opened when tapping on touch", function () { + var layer = new L.Marker(center).addTo(map); + + layer.bindTooltip('Tooltip'); + expect(map.hasLayer(layer._tooltip)).to.be(false); + happen.click(layer._icon); + expect(map.hasLayer(layer._tooltip)).to.be(true); + }); + + it.skipIfNotTouch("is closed if not permanent when clicking on the map elsewhere on touch", function () { + var layer = new L.Marker(center).addTo(map); + + layer.bindTooltip('Tooltip'); + happen.click(layer._icon); + expect(map.hasLayer(layer._tooltip)).to.be(true); + happen.click(map._container); + expect(map.hasLayer(layer._tooltip)).to.be(false); + }); + + + it("opens with map.openTooltip", function (done) { + map.on('tooltipopen', function (e) { + expect(map.hasLayer(e.tooltip)).to.be(true); + done(); + }); + map.openTooltip('Tooltip', center); + }); + + it("can call closeTooltip while not on the map", function () { + var layer = new L.Marker(center); + layer.bindTooltip('Tooltip', {interactive: true}); + layer.closeTooltip(); + }); + +}); + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/Icon.DefaultSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/Icon.DefaultSpec.js new file mode 100644 index 000000000..1c9666390 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/Icon.DefaultSpec.js @@ -0,0 +1,33 @@ +describe("Icon.Default", function () { + + it("icon measures 25x41px", function () { + var div = document.createElement('div'); + div.style.height = '100px'; + document.body.appendChild(div); + + var map = L.map(div).setView([0, 0], 0); + + var marker = new L.Marker([0, 0]).addTo(map); + + var img = map.getPane('markerPane').querySelector('img'); + expect(img.clientHeight).to.be(41); + expect(img.clientWidth).to.be(25); + document.body.removeChild(div); + }); + + it("shadow measures 41x41px", function () { + var div = document.createElement('div'); + div.style.height = '100px'; + document.body.appendChild(div); + + var map = L.map(div).setView([0, 0], 0); + + var marker = new L.Marker([0, 0]).addTo(map); + + var img = map.getPane('shadowPane').querySelector('img'); + expect(img.clientHeight).to.be(41); + expect(img.clientWidth).to.be(41); + document.body.removeChild(div); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/Marker.DragSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/Marker.DragSpec.js new file mode 100644 index 000000000..107f3296e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/Marker.DragSpec.js @@ -0,0 +1,123 @@ +describe("Marker.Drag", function () { + var map, + div; + + beforeEach(function () { + div = document.createElement('div'); + div.style.width = div.style.height = '600px'; + div.style.top = div.style.left = 0; + div.style.position = 'absolute'; + document.body.appendChild(div); + + map = L.map(div).setView([0, 0], 0); + }); + + afterEach(function () { + document.body.removeChild(div); + }); + + describe("drag", function () { + it("drags a marker with mouse", function (done) { + var marker = new L.Marker([0, 0], { + draggable: true + }); + map.addLayer(marker); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + expect(center.lat).to.be(0); + expect(center.lng).to.be(0); + + var markerPos = marker.getLatLng(); + // Marker drag is very timing sensitive, so we can't check + // exact values here, just verify that the drag is in the + // right ballpark + expect(markerPos.lat).to.be.within(-50, -30); + expect(markerPos.lng).to.be.within(340, 380); + + done(); + } + }); + var toucher = hand.growFinger('mouse'); + + toucher.wait(100).moveTo(300, 280, 0) + .down().moveBy(5, 0, 20).moveBy(256, 32, 1000).wait(100).up().wait(100); + }); + + describe("in CSS scaled container", function () { + var scaleX = 2; + var scaleY = 1.5; + + beforeEach(function () { + div.style.webkitTransformOrigin = 'top left'; + div.style.webkitTransform = 'scale(' + scaleX + ', ' + scaleY + ')'; + }); + + afterEach(function () { + div.style.webkitTransformOrigin = ''; + div.style.webkitTransform = ''; + }); + + it("drags a marker with mouse, compensating for CSS scale", function (done) { + var marker = new L.Marker([0, 0], { + draggable: true + }); + map.addLayer(marker); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + expect(center.lat).to.be(0); + expect(center.lng).to.be(0); + + var markerPos = marker.getLatLng(); + // Marker drag is very timing sensitive, so we can't check + // exact values here, just verify that the drag is in the + // right ballpark + expect(markerPos.lat).to.be.within(-50, -30); + expect(markerPos.lng).to.be.within(340, 380); + + done(); + } + }); + var toucher = hand.growFinger('mouse'); + + toucher.wait(100).moveTo(scaleX * 300, scaleY * 280, 0) + .down().moveBy(5, 0, 20).moveBy(scaleX * 256, scaleY * 32, 1000).wait(100).up().wait(100); + }); + }); + + it("pans map when autoPan is enabled", function (done) { + var marker = new L.Marker([0, 0], { + draggable: true, + autoPan: true + }); + map.addLayer(marker); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + expect(center.lat).to.be(0); + expect(center.lng).to.be.within(10, 30); + + var markerPos = marker.getLatLng(); + // Marker drag is very timing sensitive, so we can't check + // exact values here, just verify that the drag is in the + // right ballpark + expect(markerPos.lat).to.be.within(-50, -30); + expect(markerPos.lng).to.be.within(400, 450); + + done(); + } + }); + var toucher = hand.growFinger('mouse'); + + toucher.wait(100).moveTo(300, 280, 0) + .down().moveBy(5, 0, 20).moveBy(290, 32, 1000).wait(100).up().wait(100); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/MarkerSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/MarkerSpec.js new file mode 100644 index 000000000..63b9e3066 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/marker/MarkerSpec.js @@ -0,0 +1,333 @@ +describe("Marker", function () { + var map, + spy, + div, + icon1, + icon2; + + beforeEach(function () { + div = document.createElement('div'); + div.style.height = '100px'; + document.body.appendChild(div); + + map = L.map(div).setView([0, 0], 0); + icon1 = new L.Icon.Default(); + icon2 = new L.Icon.Default({ + iconUrl: icon1.options.iconUrl + '?2', + shadowUrl: icon1.options.shadowUrl + '?2' + }); + }); + + afterEach(function () { + document.body.removeChild(div); + }); + + describe("#setIcon", function () { + + it("set the correct x and y size attributes", function () { + var expectedX = 96; + var expectedY = 100; + var sizedIcon = new L.Icon.Default({ + iconUrl: icon1.options.iconUrl + '?3', + iconSize: [expectedX, expectedY] + }); + + var marker = new L.Marker([0, 0], {icon: sizedIcon}); + map.addLayer(marker); + + var icon = marker._icon; + + expect(icon.style.width).to.be(expectedX + 'px'); + expect(icon.style.height).to.be(expectedY + 'px'); + }); + + it("set the correct x and y size attributes passing only one value", function () { + var expectedXY = 96; + var sizedIcon = new L.Icon.Default({ + iconUrl: icon1.options.iconUrl + '?3', + iconSize: expectedXY + }); + + var marker = new L.Marker([0, 0], {icon: sizedIcon}); + map.addLayer(marker); + + var icon = marker._icon; + + expect(icon.style.width).to.be(expectedXY + 'px'); + expect(icon.style.height).to.be(expectedXY + 'px'); + }); + + it("set the correct x and y size attributes passing a L.Point instance", function () { + var expectedXY = 96; + var sizedIcon = new L.Icon.Default({ + iconUrl: icon1.options.iconUrl + '?3', + iconSize: L.point(expectedXY, expectedXY) + }); + + var marker = new L.Marker([0, 0], {icon: sizedIcon}); + map.addLayer(marker); + + var icon = marker._icon; + + expect(icon.style.width).to.be(expectedXY + 'px'); + expect(icon.style.height).to.be(expectedXY + 'px'); + }); + + it("changes the icon to another image while re-using the IMG element", function () { + var marker = new L.Marker([0, 0], {icon: icon1}); + map.addLayer(marker); + + var beforeIcon = marker._icon; + marker.setIcon(icon2); + var afterIcon = marker._icon; + + expect(beforeIcon).to.be(afterIcon); // Check that the element is re-used + expect(afterIcon.src).to.contain(icon2._getIconUrl('icon')); + }); + + it("preserves draggability", function () { + var marker = new L.Marker([0, 0], {icon: icon1}); + map.addLayer(marker); + + marker.dragging.disable(); + marker.setIcon(icon2); + + expect(marker.dragging.enabled()).to.be(false); + + marker.dragging.enable(); + + marker.setIcon(icon1); + + expect(marker.dragging.enabled()).to.be(true); + + map.removeLayer(marker); + map.addLayer(marker); + + expect(marker.dragging.enabled()).to.be(true); + + map.removeLayer(marker); + // Dragging is still enabled, we should be able to disable it, + // even if marker is off the map. + expect(marker.dragging).to.be(undefined); + marker.options.draggable = false; + map.addLayer(marker); + + map.removeLayer(marker); + + // We should also be able to enable dragging while off the map + expect(marker.dragging).to.be(undefined); + marker.options.draggable = true; + + map.addLayer(marker); + expect(marker.dragging.enabled()).to.be(true); + }); + + it("changes the DivIcon to another DivIcon, while re-using the DIV element", function () { + var marker = new L.Marker([0, 0], {icon: new L.DivIcon({html: 'Inner1Text'})}); + map.addLayer(marker); + + var beforeIcon = marker._icon; + marker.setIcon(new L.DivIcon({html: 'Inner2Text'})); + var afterIcon = marker._icon; + + expect(beforeIcon).to.be(afterIcon); // Check that the
element is re-used + expect(afterIcon.innerHTML).to.contain('Inner2Text'); + }); + + it("removes text when changing to a blank DivIcon", function () { + var marker = new L.Marker([0, 0], {icon: new L.DivIcon({html: 'Inner1Text'})}); + map.addLayer(marker); + + marker.setIcon(new L.DivIcon()); + var afterIcon = marker._icon; + + expect(marker._icon.innerHTML).to.not.contain('Inner1Text'); + }); + + it("changes a DivIcon to an image", function () { + var marker = new L.Marker([0, 0], {icon: new L.DivIcon({html: 'Inner1Text'})}); + map.addLayer(marker); + var oldIcon = marker._icon; + + marker.setIcon(icon1); + + expect(oldIcon).to.not.be(marker._icon); // Check that the _icon is NOT re-used + expect(oldIcon.parentNode).to.be(null); + + if (L.Browser.retina) { + expect(marker._icon.src).to.contain('marker-icon-2x.png'); + } else { + expect(marker._icon.src).to.contain('marker-icon.png'); + } + expect(marker._icon.parentNode).to.be(map._panes.markerPane); + }); + + it("changes an image to a DivIcon", function () { + var marker = new L.Marker([0, 0], {icon: icon1}); + map.addLayer(marker); + var oldIcon = marker._icon; + + marker.setIcon(new L.DivIcon({html: 'Inner1Text'})); + + expect(oldIcon).to.not.be(marker._icon); // Check that the _icon is NOT re-used + expect(oldIcon.parentNode).to.be(null); + + expect(marker._icon.innerHTML).to.contain('Inner1Text'); + expect(marker._icon.parentNode).to.be(map._panes.markerPane); + }); + + it("reuses the icon/shadow when changing icon", function () { + var marker = new L.Marker([0, 0], {icon: icon1}); + map.addLayer(marker); + var oldIcon = marker._icon; + var oldShadow = marker._shadow; + + marker.setIcon(icon2); + + expect(oldIcon).to.be(marker._icon); + expect(oldShadow).to.be(marker._shadow); + + expect(marker._icon.parentNode).to.be(map._panes.markerPane); + expect(marker._shadow.parentNode).to.be(map._panes.shadowPane); + }); + + it("sets the alt attribute to an empty string when no alt text is passed", function () { + var marker = L.marker([0, 0], {icon: icon1}); + map.addLayer(marker); + var icon = marker._icon; + expect(icon.hasAttribute('alt')).to.be(true); + expect(icon.alt).to.be(''); + }); + + it("doesn't set the alt attribute for DivIcons", function () { + var marker = L.marker([0, 0], {icon: L.divIcon(), alt: 'test'}); + map.addLayer(marker); + var icon = marker._icon; + expect(icon.hasAttribute('alt')).to.be(false); + }); + }); + + describe("#setLatLng", function () { + it("fires a move event", function () { + + var marker = new L.Marker([0, 0], {icon: icon1}); + map.addLayer(marker); + + var beforeLatLng = marker._latlng; + var afterLatLng = new L.LatLng(1, 2); + + var eventArgs = null; + marker.on('move', function (e) { + eventArgs = e; + }); + + marker.setLatLng(afterLatLng); + + expect(eventArgs).to.not.be(null); + expect(eventArgs.oldLatLng).to.be(beforeLatLng); + expect(eventArgs.latlng).to.be(afterLatLng); + expect(marker.getLatLng()).to.be(afterLatLng); + }); + }); + + describe('events', function () { + it('fires click event when clicked', function () { + var spy = sinon.spy(); + + var marker = L.marker([0, 0]).addTo(map); + + marker.on('click', spy); + happen.click(marker._icon); + + expect(spy.called).to.be.ok(); + }); + + it('fires click event when clicked with DivIcon', function () { + var spy = sinon.spy(); + + var marker = L.marker([0, 0], {icon: new L.DivIcon()}).addTo(map); + + marker.on('click', spy); + happen.click(marker._icon); + + expect(spy.called).to.be.ok(); + }); + + it('fires click event when clicked on DivIcon child element', function () { + var spy = sinon.spy(); + + var marker = L.marker([0, 0], {icon: new L.DivIcon({html: ''})}).addTo(map); + + marker.on('click', spy); + + happen.click(marker._icon); + expect(spy.called).to.be.ok(); + + happen.click(marker._icon.querySelector('img')); + expect(spy.calledTwice).to.be.ok(); + }); + + it('fires click event when clicked on DivIcon child element set using setIcon', function () { + var spy = sinon.spy(); + + var marker = L.marker([0, 0]).addTo(map); + marker.setIcon(new L.DivIcon({html: ''})); + + marker.on('click', spy); + + happen.click(marker._icon); + expect(spy.called).to.be.ok(); + + happen.click(marker._icon.querySelector('img')); + expect(spy.calledTwice).to.be.ok(); + }); + + it("do not propagate click event", function () { + var spy = sinon.spy(); + var spy2 = sinon.spy(); + var mapSpy = sinon.spy(); + var marker = new L.Marker(new L.LatLng(55.8, 37.6)); + map.addLayer(marker); + marker.on('click', spy); + marker.on('click', spy2); + map.on('click', mapSpy); + happen.click(marker._icon); + expect(spy.called).to.be.ok(); + expect(spy2.called).to.be.ok(); + expect(mapSpy.called).not.to.be.ok(); + }); + + it("do not propagate dblclick event", function () { + var spy = sinon.spy(); + var spy2 = sinon.spy(); + var mapSpy = sinon.spy(); + var marker = new L.Marker(new L.LatLng(55.8, 37.6)); + map.addLayer(marker); + marker.on('dblclick', spy); + marker.on('dblclick', spy2); + map.on('dblclick', mapSpy); + happen.dblclick(marker._icon); + expect(spy.called).to.be.ok(); + expect(spy2.called).to.be.ok(); + expect(mapSpy.called).not.to.be.ok(); + }); + + it("do not catch event if it does not listen to it", function (done) { + var marker = new L.Marker([55, 37]); + map.addLayer(marker); + marker.once('mousemove', function (e) { + // It should be the marker coordinates + expect(e.latlng.equals(marker.getLatLng())).to.be.equal(true); + }); + happen.mousemove(marker._icon); + + map.once('mousemove', function (e) { + // It should be the mouse coordinates, not the marker ones + expect(e.latlng.equals(marker.getLatLng())).to.be.equal(false); + done(); + }); + happen.mousemove(marker._icon); + }); + + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/tile/GridLayerSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/tile/GridLayerSpec.js new file mode 100644 index 000000000..4698a7a3b --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/tile/GridLayerSpec.js @@ -0,0 +1,1132 @@ + +describe('GridLayer', function () { + + var div, map; + + beforeEach(function () { + div = document.createElement('div'); + div.style.width = '800px'; + div.style.height = '600px'; + div.style.visibility = 'hidden'; + + document.body.appendChild(div); + + map = L.map(div); + }); + + afterEach(function () { + document.body.removeChild(div); + }); + + describe('#redraw', function () { + it('can be called before map.setView', function () { + var grid = L.gridLayer().addTo(map); + expect(grid.redraw()).to.equal(grid); + }); + }); + + describe('#setOpacity', function () { + it('can be called before map.setView', function () { + var grid = L.gridLayer().addTo(map); + expect(grid.setOpacity(0.5)).to.equal(grid); + }); + + it('works when map has fadeAnimated=false (IE8 is exempt)', function (done) { + map.remove(); + map = L.map(div, {fadeAnimation: false}).setView([0, 0], 0); + + var grid = L.gridLayer().setOpacity(0.5).addTo(map); + grid.on('load', function () { + expect(grid._container.style.opacity).to.equal('0.5'); + done(); + }); + }); + }); + + it('positions tiles correctly with wrapping and bounding', function () { + + map.setView([0, 0], 1); + + var tiles = []; + + var grid = L.gridLayer(); + grid.createTile = function (coords) { + var tile = document.createElement('div'); + tiles.push({coords: coords, tile: tile}); + return tile; + }; + + map.addLayer(grid); + + var loaded = {}; + + for (var i = 0; i < tiles.length; i++) { + var coords = tiles[i].coords, + pos = L.DomUtil.getPosition(tiles[i].tile); + + loaded[pos.x + ':' + pos.y] = [coords.x, coords.y]; + } + + expect(loaded).to.eql({ + '144:0': [0, 0], + '400:0': [1, 0], + '144:256': [0, 1], + '400:256': [1, 1], + '-112:0': [1, 0], + '656:0': [0, 0], + '-112:256': [1, 1], + '656:256': [0, 1] + }); + }); + + describe('tile pyramid', function () { + var clock; + + beforeEach(function () { + clock = sinon.useFakeTimers(); + }); + + afterEach(function () { + clock.restore(); + }); + + it('removes tiles for unused zoom levels', function (done) { + map.remove(); + map = L.map(div, {fadeAnimation: false}); + map.setView([0, 0], 1); + + var grid = L.gridLayer(); + var tiles = {}; + + grid.createTile = function (coords) { + tiles[grid._tileCoordsToKey(coords)] = true; + return document.createElement('div'); + }; + + grid.on('tileunload', function (e) { + delete tiles[grid._tileCoordsToKey(e.coords)]; + }); + + grid.on('load', function (e) { + if (Object.keys(tiles).length === 1) { + expect(Object.keys(tiles)).to.eql(['0:0:0']); + grid.off(); + done(); + } + }); + + map.addLayer(grid); + map.setZoom(0, {animate: false}); + clock.tick(250); + }); + }); + + describe('#createTile', function () { + var grid; + + beforeEach(function () { + // Simpler sizes to test. + div.style.width = '512px'; + div.style.height = '512px'; + + map.remove(); + map = L.map(div); + map.setView([0, 0], 10); + + grid = L.gridLayer(); + }); + + afterEach(function () { + div.style.width = '800px'; + div.style.height = '600px'; + }); + + // Passes on Firefox, but fails on phantomJS: done is never called. + it('only creates tiles for visible area on zoom in', function (done) { + var count = 0, + loadCount = 0; + grid.createTile = function (coords) { + count++; + return document.createElement('div'); + }; + var onLoad = function (e) { + expect(count).to.eql(4); + count = 0; + loadCount++; + if (loadCount === 1) { // On layer add. + map.zoomIn(); + } else { // On zoom in. + done(); + } + }; + grid.on('load', onLoad); + map.addLayer(grid); + }); + + describe('when done() is called with an error parameter', function () { + var keys; + + beforeEach(function () { + keys = []; + grid.createTile = function (coords, done) { + var tile = document.createElement('div'); + keys.push(this._tileCoordsToKey(coords)); + done('error', tile); + return tile; + }; + }); + + it('does not raise tileload events', function (done) { + var tileLoadRaised = sinon.spy(); + grid.on('tileload', tileLoadRaised); + grid.on('tileerror', function () { + if (keys.length === 4) { + expect(tileLoadRaised.notCalled).to.be(true); + done(); + } + }); + map.addLayer(grid); + }); + + it('raises tileerror events', function (done) { + var tileErrorRaised = sinon.spy(); + grid.on('tileerror', function () { + tileErrorRaised(); + if (keys.length === 4) { + expect(tileErrorRaised.callCount).to.be(4); + done(); + } + }); + map.addLayer(grid); + }); + + it('does not add the .leaflet-tile-loaded class to tile elements', function (done) { + var count = 0; + grid.on('tileerror', function (e) { + if (!L.DomUtil.hasClass(e.tile, 'leaflet-tile-loaded')) { + count++; + } + if (keys.length === 4) { + expect(count).to.be(4); + done(); + } + }); + map.addLayer(grid); + }); + }); + + }); + + describe("#onAdd", function () { + it('is called after zoomend on first map load', function () { + var layer = L.gridLayer().addTo(map); + + var onAdd = layer.onAdd, + onAddSpy = sinon.spy(); + layer.onAdd = function () { + onAdd.apply(this, arguments); + onAddSpy(); + }; + + var onReset = sinon.spy(); + map.on('zoomend', onReset); + map.setView([0, 0], 0); + + expect(onReset.calledBefore(onAddSpy)).to.be.ok(); + }); + }); + + describe("#getMaxZoom, #getMinZoom", function () { + describe("when a tilelayer is added to a map with no other layers", function () { + it("has the same zoomlevels as the tilelayer", function () { + var maxZoom = 10, + minZoom = 5; + + map.setView([0, 0], 1); + + L.gridLayer({ + maxZoom: maxZoom, + minZoom: minZoom + }).addTo(map); + + expect(map.getMaxZoom()).to.be(maxZoom); + expect(map.getMinZoom()).to.be(minZoom); + }); + }); + + describe("accessing a tilelayer's properties", function () { + it('provides a container', function () { + map.setView([0, 0], 1); + + var layer = L.gridLayer().addTo(map); + expect(layer.getContainer()).to.be.ok(); + }); + }); + + describe("when a tilelayer is added to a map that already has a tilelayer", function () { + it("has its zoomlevels updated to fit the new layer", function () { + map.setView([0, 0], 1); + + L.gridLayer({minZoom: 10, maxZoom: 15}).addTo(map); + expect(map.getMinZoom()).to.be(10); + expect(map.getMaxZoom()).to.be(15); + + L.gridLayer({minZoom: 5, maxZoom: 10}).addTo(map); + expect(map.getMinZoom()).to.be(5); // changed + expect(map.getMaxZoom()).to.be(15); // unchanged + + L.gridLayer({minZoom: 10, maxZoom: 20}).addTo(map); + expect(map.getMinZoom()).to.be(5); // unchanged + expect(map.getMaxZoom()).to.be(20); // changed + + + L.gridLayer({minZoom: 0, maxZoom: 25}).addTo(map); + expect(map.getMinZoom()).to.be(0); // changed + expect(map.getMaxZoom()).to.be(25); // changed + }); + }); + + describe("when a gridlayer is removed from a map", function () { + it("has its zoomlevels updated to only fit the layers it currently has", function () { + var tiles = [ + L.gridLayer({minZoom: 10, maxZoom: 15}).addTo(map), + L.gridLayer({minZoom: 5, maxZoom: 10}).addTo(map), + L.gridLayer({minZoom: 10, maxZoom: 20}).addTo(map), + L.gridLayer({minZoom: 0, maxZoom: 25}).addTo(map) + ]; + map.whenReady(function () { + expect(map.getMinZoom()).to.be(0); + expect(map.getMaxZoom()).to.be(25); + + map.removeLayer(tiles[0]); + expect(map.getMinZoom()).to.be(0); + expect(map.getMaxZoom()).to.be(25); + + map.removeLayer(tiles[3]); + expect(map.getMinZoom()).to.be(5); + expect(map.getMaxZoom()).to.be(20); + + map.removeLayer(tiles[2]); + expect(map.getMinZoom()).to.be(5); + expect(map.getMaxZoom()).to.be(10); + + map.removeLayer(tiles[1]); + expect(map.getMinZoom()).to.be(0); + expect(map.getMaxZoom()).to.be(Infinity); + }); + }); + }); + }); + + + describe("min/maxNativeZoom option", function () { + it("calls createTile() with maxNativeZoom when map zoom is larger", function (done) { + map.setView([0, 0], 10); + + var grid = L.gridLayer({ + maxNativeZoom: 5 + }); + var tileCount = 0; + + grid.createTile = function (coords) { + expect(coords.z).to.be(5); + tileCount++; + return document.createElement('div'); + }; + grid.on('load', function () { + if (tileCount > 0) { + done(); + } else { + done('No tiles loaded'); + } + }); + + map.addLayer(grid); + }); + + it("calls createTile() with minNativeZoom when map zoom is smaller", function (done) { + map.setView([0, 0], 3); + + var grid = L.gridLayer({ + minNativeZoom: 5 + }); + var tileCount = 0; + + grid.createTile = function (coords) { + expect(coords.z).to.be(5); + tileCount++; + return document.createElement('div'); + }; + grid.on('load', function () { + if (tileCount > 0) { + done(); + } else { + done('No tiles loaded'); + } + }); + + map.addLayer(grid); + }); + }); + + describe("number of 256px tiles loaded in synchronous non-animated grid @800x600px", function () { + var clock, grid, counts; + + beforeEach(function () { + clock = sinon.useFakeTimers(); + + grid = L.gridLayer({ + attribution: 'Grid Layer', + tileSize: L.point(256, 256) + }); + + grid.createTile = function (coords) { + var tile = document.createElement('div'); + tile.innerHTML = [coords.x, coords.y, coords.z].join(', '); + tile.style.border = '2px solid red'; + return tile; + }; + + counts = { + tileload: 0, + tileerror: 0, + tileloadstart: 0, + tileunload: 0 + }; + + grid.on('tileload tileunload tileerror tileloadstart', function (ev) { + // console.log(ev.type); + counts[ev.type]++; + }); + // grid.on('tileunload', function (ev) { + // console.log(ev.type, ev.coords, counts); + // }); + + map.options.fadeAnimation = false; + map.options.zoomAnimation = false; + }); + + afterEach(function () { + clock.restore(); + grid.off(); + grid = undefined; + counts = undefined; + }); + + it("Loads 8 tiles zoom 1", function (done) { + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(8); + expect(counts.tileload).to.be(8); + expect(counts.tileunload).to.be(0); + done(); + }); + + map.addLayer(grid).setView([0, 0], 1); + clock.tick(250); + }); + + it("Loads 5 tiles zoom 0", function (done) { + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(5); + expect(counts.tileload).to.be(5); + expect(counts.tileunload).to.be(0); + done(); + }); + + map.addLayer(grid).setView([0, 0], 0); + clock.tick(250); + }); + + it("Loads 16 tiles zoom 10", function (done) { + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + grid.off(); + + done(); + }); + + map.addLayer(grid).setView([0, 0], 10); + clock.tick(250); + }); + + it("Loads 32, unloads 16 tiles zooming in 10-11", function (done) { + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(32); + expect(counts.tileload).to.be(32); + expect(counts.tileunload).to.be(16); + done(); + }); + + map.setZoom(11, {animate: false}); + clock.tick(250); + }); + + + map.addLayer(grid).setView([0, 0], 10); + clock.tick(250); + }); + + it("Loads 32, unloads 16 tiles zooming out 11-10", function (done) { + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(32); + expect(counts.tileload).to.be(32); + expect(counts.tileunload).to.be(16); + done(); + }); + + map.setZoom(10, {animate: false}); + clock.tick(250); + }); + + + map.addLayer(grid).setView([0, 0], 11); + clock.tick(250); + }); + + + it("Loads 32, unloads 16 tiles zooming out 18-10", function (done) { + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(32); + expect(counts.tileload).to.be(32); + expect(counts.tileunload).to.be(16); + done(); + }); + + map.setZoom(10, {animate: false}); + clock.tick(250); + }); + + + map.addLayer(grid).setView([0, 0], 18); + clock.tick(250); + }); + + }); + + + describe("number of 256px tiles loaded in synchronous animated grid @800x600px", function () { + + var clock, grid, counts; + + beforeEach(function () { + clock = sinon.useFakeTimers(); + + grid = L.gridLayer({ + attribution: 'Grid Layer', + tileSize: L.point(256, 256) + }); + + grid.createTile = function (coords) { + var tile = document.createElement('div'); + tile.innerHTML = [coords.x, coords.y, coords.z].join(', '); + tile.style.border = '2px solid red'; + return tile; + }; + + counts = { + tileload: 0, + tileerror: 0, + tileloadstart: 0, + tileunload: 0 + }; + + grid.on('tileload tileunload tileerror tileloadstart', function (ev) { + counts[ev.type]++; + }); + }); + + afterEach(function () { + clock.restore(); + grid.off(); + grid = undefined; + counts = undefined; + }); + + // Debug helper + function logTiles(ev) { + var pending = 0; + for (var key in grid._tiles) { + if (!grid._tiles[key].loaded) { pending++; } + } + console.log(ev.type + ': ', ev.coords, grid._loading, counts, ' pending: ', pending); + } + + + // animationFrame helper, just runs requestAnimFrame() a given number of times + function runFrames(n) { + return _runFrames(n)(); + } + + function _runFrames(n) { + if (n) { + return function () { + clock.tick(40); // 40msec/frame ~= 25fps + map.fire('_frame'); + L.Util.requestAnimFrame(_runFrames(n - 1)); + }; + } else { + return L.Util.falseFn; + } + } + + // NOTE: This test has different behaviour in PhantomJS and graphical + // browsers due to CSS animations! + it.skipInPhantom("Loads 32, unloads 16 tiles zooming in 10-11", function (done) { + + // Advance the time to !== 0 otherwise `tile.loaded` timestamp will appear to be falsy. + clock.tick(1); + // Date.now() is 1. + + // grid.on('tileload tileunload tileloadstart load loading', logTiles); + + // Use "once" to automatically detach the listener, + // and avoid removing the above logTiles + // (which would happen when calling "grid.off('load')"). + grid.once('load', function () { + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + + // Wait for a frame to let _updateOpacity starting. + L.Util.requestAnimFrame(function () { + // Wait > 250msec for the tile fade-in animation to complete, + // which triggers the tile pruning + clock.tick(300); + // At 251ms, the pruneTile from the end of the z10 tiles fade-in animation executes. + // Date.now() is 301. + + grid.once('load', function () { + expect(counts.tileload).to.be(32); + + // We're one frame into the zoom animation, + // so GridLayer._setView with noPrune === undefined is not called yet + // No tile should be unloaded yet. + expect(counts.tileunload).to.be(0); + + // Wait > 250msec for the zoom animation to complete, + // which triggers the tile pruning + // Animated zoom takes 1 frame + 250ms before firing "zoom" event + // => GridLayer._resetView => GridLayer._setView => _pruneTiles + // However, this "load" event callback executes synchronously, + // i.e. _tileReady still did not have a chance to prepare the + // setTimeout(250) for pruning after the end of the fade-in animation. + clock.tick(300); + // At 301 + 250 = 551ms, the pruneTile from the end of the zoom animation executes. + // It unloads the 'outside' 12 tiles from z10, but not the 4 tiles in the center, + // since _updateOpacity did not have a chance yet to flag the 16 new z11 tiles as "active". + expect(counts.tileunload).to.be(12); + // Date.now() is 601. + + // Wait for a frame to let _updateOpacity starting + // + _tileReady to be able to prepare its setTimeout(250) + // for pruning after the end of the fade-in animation. + // Since we are already > 200ms since the 'load' event fired, + // _updateOpacity should directly set the current tiles as "active", + // so the remaining 4 tiles from z10 can then be pruned. + // However we have skipped any pruning from _updateOpacity, + // so we will have to rely on the setTimeout from _tileReady. + L.Util.requestAnimFrame(function () { + // Wait > 250msec for the tile fade-in animation to complete, + // which triggers the tile pruning + clock.tick(300); + // At 851ms, the pruneTile from the end of the z11 tiles fade-in animation executes. + // It unloads the remaining 4 tiles from z10. + expect(counts.tileunload).to.be(16); + // Date.now() is 901. + done(); + }); + }); + + map.setZoom(11, {animate: true}); + // Animation (and new tiles loading) starts after 1 frame. + L.Util.requestAnimFrame(function () { + // 16 extra tiles from z11 being loaded. Total 16 + 16 = 32. + expect(counts.tileloadstart).to.be(32); + }); + + }); + }); + + map.addLayer(grid).setView([0, 0], 10); + // The first setView does not animated, therefore it starts loading tiles immediately. + // 16 tiles from z10 being loaded. + expect(counts.tileloadstart).to.be(16); + // At 1ms, first pruneTile (map fires "viewreset" event => GridLayer._resetView => GridLayer._setView => _pruneTiles). + }); + + it("Loads 32, unloads 16 tiles zooming in 10-18", function (done) { + grid.on('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + grid.on('load', function () { + + // In this particular scenario, the tile unloads happen in the + // next render frame after the grid's 'load' event. + L.Util.requestAnimFrame(function () { + expect(counts.tileloadstart).to.be(32); + expect(counts.tileload).to.be(32); + expect(counts.tileunload).to.be(16); + done(); + }); + }); + + map.setZoom(18, {animate: true}); + clock.tick(250); + }); + + map.addLayer(grid).setView([0, 0], 10); + clock.tick(250); + }); + + // NOTE: This test has different behaviour in PhantomJS and graphical + // browsers due to CSS animations! + it.skipInPhantom("Loads 32, unloads 16 tiles zooming out 11-10", function (done) { + + // Advance the time to !== 0 otherwise `tile.loaded` timestamp will appear to be falsy. + clock.tick(1); + // Date.now() is 1. + + // grid.on('tileload tileunload load', logTiles); + + grid.once('load', function () { + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + + // Wait for a frame to let _updateOpacity starting. + L.Util.requestAnimFrame(function () { + // Wait > 250msec for the tile fade-in animation to complete, + // which triggers the tile pruning + clock.tick(300); + // At 251ms, the pruneTile from the end of the z11 tiles fade-in animation executes. + // Date.now() is 301. + + grid.once('load', function () { + expect(counts.tileload).to.be(20); + // No tile should be unloaded yet. + expect(counts.tileunload).to.be(0); + + // Wait > 250msec for the zoom animation to complete, + // which triggers the tile pruning, but there are no + // tiles to prune yet (z11 tiles are all in bounds). + clock.tick(300); + // Date.now() is 601. + + // At the end of the animation, all 16 tiles from z10 + // are loading. + expect(counts.tileloadstart).to.be(32); + expect(counts.tileload).to.be(20); + + // Now that the zoom animation is complete, + // the grid is ready to fire a new "load" event + // on next frame, so prepare its listener now. + // During that frame, _updateOpacity will flag the 4 + // central tiles from z10 as "active", since we are now + // > 200ms after the first "load" event fired. + grid.once('load', function () { + expect(counts.tileload).to.be(32); + // No tile should be unloaded yet. + expect(counts.tileunload).to.be(0); + + // Wait for a frame for next _updateOpacity to prune + // all 16 tiles from z11 which are now covered by the + // 4 central active tiles of z10. + L.Util.requestAnimFrame(function () { + expect(counts.tileunload).to.be(16); + done(); + }); + }); + }); + }); + + map.setZoom(10, {animate: true}); + // Animation (and new tiles loading) starts after 1 frame. + L.Util.requestAnimFrame(function () { + // We're one frame into the zoom animation, there are + // 16 tiles for z11 plus 4 tiles for z10 covering the + // bounds at the *beginning* of the zoom-*out* anim + expect(counts.tileloadstart).to.be(20); + }); + }); + + map.addLayer(grid).setView([0, 0], 11); + // The first setView does not animated, therefore it starts loading tiles immediately. + // 16 tiles from z10 being loaded. + expect(counts.tileloadstart).to.be(16); + }); + + it("Loads 32, unloads 16 tiles zooming out 18-10", function (done) { + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + grid.on('load', function () { + + // In this particular scenario, the tile unloads happen in the + // next render frame after the grid's 'load' event. + L.Util.requestAnimFrame(function () { + expect(counts.tileloadstart).to.be(32); + expect(counts.tileload).to.be(32); + expect(counts.tileunload).to.be(16); + done(); + }); + }); + + map.setZoom(10, {animate: true}); + clock.tick(250); + }); + + map.addLayer(grid).setView([0, 0], 18); + clock.tick(250); + }); + + // NOTE: This test has different behaviour in PhantomJS and graphical + // browsers due to CSS animations! + it.skipInPhantom("Loads 290, unloads 275 tiles on MAD-TRD flyTo()", function (done) { + + this.timeout(10000); // This test takes longer than usual due to frames + + var mad = [40.40, -3.7], trd = [63.41, 10.41]; + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(12); + expect(counts.tileload).to.be(12); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + map.on('zoomend', function () { + expect(counts.tileloadstart).to.be(290); + expect(counts.tileunload).to.be(275); + expect(counts.tileload).to.be(290); + expect(grid._container.querySelectorAll('div').length).to.be(16); // 15 + container + done(); + }); + + map.flyTo(trd, 12, {animate: true}); + + // map.on('_frame', function () { + // console.log('frame', counts); + // }); + + runFrames(500); + }); + + grid.options.keepBuffer = 0; + + map.addLayer(grid).setView(mad, 12); + clock.tick(250); + }); + + }); + + describe("configurable tile pruning", function () { + var clock, grid, counts; + + beforeEach(function () { + clock = sinon.useFakeTimers(); + + grid = L.gridLayer({ + attribution: 'Grid Layer', + tileSize: L.point(256, 256) + }); + + grid.createTile = function (coords) { + var tile = document.createElement('div'); + tile.innerHTML = [coords.x, coords.y, coords.z].join(', '); + tile.style.border = '2px solid red'; + return tile; + }; + + counts = { + tileload: 0, + tileerror: 0, + tileloadstart: 0, + tileunload: 0 + }; + + grid.on('tileload tileunload tileerror tileloadstart', function (ev) { + // console.log(ev.type); + counts[ev.type]++; + }); + // grid.on('tileunload', function (ev) { + // console.log(ev.type, ev.coords, counts); + // }); + + map.options.fadeAnimation = false; + map.options.zoomAnimation = false; + }); + + afterEach(function () { + clock.restore(); + grid.off(); + grid = undefined; + counts = undefined; + }); + + // NOTE: This test has different behaviour in PhantomJS and graphical + // browsers due to CSS animations! + it("Loads map, moves forth by 512 px, keepBuffer = 0", function (done) { + + // Advance the time to !== 0 otherwise `tile.loaded` timestamp will appear to be falsy. + clock.tick(1); + // Date.now() is 1. + + grid.once('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + + // Wait for a frame to let _updateOpacity starting. + L.Util.requestAnimFrame(function () { + + // Wait > 250msec for the tile fade-in animation to complete, + // which triggers the tile pruning + clock.tick(300); + // At 251ms, the pruneTile from the end of the setView tiles fade-in animation executes. + // Date.now() is 301. + + grid.once('load', function () { + // Since there is no animation requested, + // We directly jump to the target position. + // => 12 new tiles, total = 16 + 12 = 28 tiles. + expect(counts.tileloadstart).to.be(28); + expect(counts.tileload).to.be(28); + + // Wait for a frame to let _updateOpacity starting + // It will prune the 12 tiles outside the new bounds. + // PhantomJS has Browser.any3d === false, so it actually + // does not perform the fade animation and does not need + // this rAF, but it does not harm either. + L.Util.requestAnimFrame(function () { + expect(counts.tileunload).to.be(12); + done(); + }); + }); + + // Move up 512px => 2 tile rows => 2*4 = 8 new tiles (V and M). + // Move right 512px => 2 tile columns => 2*4 = 4 new tiles (H) + 4 new tiles (M) in common with vertical pan. + // Total = 8 + 8 - 4 = 12 new tiles. + // ..VVMM + // ..VVMM + // OOXXHH // O = Old tile, X = Old tile still visible. + // OOXXHH + // OOOO + // OOOO + map.panBy([512, 512], {animate: false}); + // clock.tick(250); + + }); + }); + + grid.options.keepBuffer = 0; + + // 800px width * 600px height => 4 tiles horizontally * 4 tiles vertically = 16 tiles + map.addLayer(grid).setView([0, 0], 10); + // clock.tick(250); + }); + + // NOTE: This test has different behaviour in PhantomJS and graphical + // browsers due to CSS animations! + it("Loads map, moves forth and back by 512 px, keepBuffer = 0", function (done) { + + grid.once('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + + grid.once('load', function () { + expect(counts.tileloadstart).to.be(28); + expect(counts.tileload).to.be(28); + + // Wait for a frame to let _updateOpacity starting + // It will prune the 12 tiles outside the new bounds. + // PhantomJS has Browser.any3d === false, so it actually + // does not perform the fade animation and does not need + // this rAF, but it does not harm either. + L.Util.requestAnimFrame(function () { + expect(counts.tileunload).to.be(12); + + grid.once('load', function () { + expect(counts.tileloadstart).to.be(40); + expect(counts.tileload).to.be(40); + + // Wait an extra frame for the tile pruning to happen. + L.Util.requestAnimFrame(function () { + expect(counts.tileunload).to.be(24); + done(); + }); + }); + + map.panBy([-512, -512], {animate: false}); + clock.tick(250); + }); + }); + + map.panBy([512, 512], {animate: false}); + clock.tick(250); + }); + + grid.options.keepBuffer = 0; + + map.addLayer(grid).setView([0, 0], 10); + clock.tick(250); + }); + + it("Loads map, moves forth and back by 512 px, default keepBuffer", function (done) { + + var spy = sinon.spy(); + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(16); + expect(counts.tileload).to.be(16); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + grid.on('load', function () { + expect(counts.tileloadstart).to.be(28); + expect(counts.tileload).to.be(28); + expect(counts.tileunload).to.be(0); + grid.off('load'); + + grid.addEventListener('load', spy); + + map.panBy([-512, -512], {animate: false}); + clock.tick(250); + + expect(spy.called).to.be(false); + done(); + }); + + map.panBy([512, 512], {animate: false}); + clock.tick(250); + }); + + map.addLayer(grid).setView([0, 0], 10); + clock.tick(250); + }); + }); + + describe("nowrap option", function () { + it("When false, uses same coords at zoom 0 for all tiles", function (done) { + + var grid = L.gridLayer({ + attribution: 'Grid Layer', + tileSize: L.point(256, 256), + noWrap: false + }); + var loadedTileKeys = []; + + grid.createTile = function (coords) { + loadedTileKeys.push(coords.x + ':' + coords.y + ':' + coords.z); + return document.createElement('div'); + }; + + map.addLayer(grid).setView([0, 0], 0); + + grid.on('load', function () { + expect(loadedTileKeys).to.eql(["0:0:0", "0:0:0", "0:0:0", "0:0:0", "0:0:0"]); + done(); + }); + }); + + it("When true, uses different coords at zoom level 0 for all tiles", function (done) { + + var grid = L.gridLayer({ + attribution: 'Grid Layer', + tileSize: L.point(256, 256), + noWrap: true + }); + var loadedTileKeys = []; + + grid.createTile = function (coords) { + loadedTileKeys.push(coords.x + ':' + coords.y + ':' + coords.z); + return document.createElement('div'); + }; + + map.addLayer(grid).setView([0, 0], 0); + + grid.on('load', function () { + expect(loadedTileKeys).to.eql(['0:0:0', '-1:0:0', '1:0:0', '-2:0:0', '2:0:0']); + done(); + }); + }); + + it("When true and with bounds, loads just one tile at zoom level 0", function (done) { + + var grid = L.gridLayer({ + attribution: 'Grid Layer', + tileSize: L.point(256, 256), + bounds: [[-90, -180], [90, 180]], + noWrap: true + }); + var loadedTileKeys = []; + + grid.createTile = function (coords) { + loadedTileKeys.push(coords.x + ':' + coords.y + ':' + coords.z); + return document.createElement('div'); + }; + + map.addLayer(grid).setView([0, 0], 0); + + grid.on('load', function () { + expect(loadedTileKeys).to.eql(['0:0:0']); + done(); + }); + }); + }); + + describe("Sanity checks for infinity", function () { + it("Throws error on map center at plus Infinity longitude", function () { + expect(function () { + map.setCenter([Infinity, Infinity]); + L.gridLayer().addTo(map); + }).to.throwError('Attempted to load an infinite number of tiles'); + }); + + it("Throws error on map center at minus Infinity longitude", function () { + expect(function () { + map.setCenter([-Infinity, -Infinity]); + L.gridLayer().addTo(map); + }).to.throwError('Attempted to load an infinite number of tiles'); + }); + }); + + it("doesn't call map's getZoomScale method with null after _invalidateAll method was called", function () { + map.setView([0, 0], 0); + var grid = L.gridLayer().addTo(map); + var wrapped = sinon.spy(map, 'getZoomScale'); + grid._invalidateAll(); + grid.redraw(); + expect(wrapped.neverCalledWith(sinon.match.any, null)).to.be(true); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/tile/TileLayerSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/tile/TileLayerSpec.js new file mode 100644 index 000000000..2f1c032d4 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/tile/TileLayerSpec.js @@ -0,0 +1,482 @@ + + +describe('TileLayer', function () { + + var div, map; + + // Placekitten via http://placekitten.com/attribution.html + // Image licensed under CC-by-sa by http://flickr.com/photos/lachlanrogers/ + + var placeKitten = "data:image/jpeg;base64," + + "/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBF" + + "RyB2NjIpLCBxdWFsaXR5ID0gNjUK/9sAQwALCAgKCAcLCgkKDQwLDREcEhEPDxEiGRoUHCkkKyooJCcn" + + "LTJANy0wPTAnJzhMOT1DRUhJSCs2T1VORlRAR0hF/9sAQwEMDQ0RDxEhEhIhRS4nLkVFRUVFRUVFRUVF" + + "RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF/8AAEQgBAAEAAwEiAAIRAQMRAf/E" + + "AB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUS" + + "ITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RV" + + "VldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TF" + + "xsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgME" + + "BQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1Lw" + + "FWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKD" + + "hIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp" + + "6vLz9PX29/j5+v/aAAwDAQACEQMRAD8Azy+KN+aqtNzUkTZrjubkjkiozJxUzrlc1mzy7DimIWdg2azZ" + + "sBvrU7T56mq0jZNUkFyeBAw680+VABUUMgFOkfmgREo2tkVdhbcKrLg9atwACkwQkiEjFVnjKng8VoED" + + "FRFVPWkmMroxxg0mwdatCEEcU5IcnBouBU3Ljmqssm1uDWjcW3B2ms6S3YN81UmhMaXWRfeqM42NkVoN" + + "Cqr15qhOp5JzVxeomRjL0ONnJpInCHnpT52DAGr6kkYfkGponquFyM1LEOpNNgXI5AvXrTZJMt1qANk+" + + "1LjLiotqO5dtH+cGuy0u6GwAmuHjYIRjOa2NPvTvABrnrw5lcqLsegwyBlqbIrI0+43qM1pBxXnypFtj" + + "ywppemM1RM9YumYuRKXpC4qt5lLvzQqYRmef+axatOyzxmqEcWXrYsYenFeszsULItGPKVh6hFtOa6ny" + + "f3fSsDVF2k5qzCWhz0rFah8wk4qW5GTUAU9ecVokZliN/U1ZX5hVRVOcVZjJzzUsaHhSDVlGAHNIg456" + + "U2X/AGahjJTIKjMvNVXcio1l+bBOKEguX0nO70qx5+1eKqLjbuzmmibc2MUrATS3LA5xUUlyjpz1pZmU" + + "rjgVUaFm+7VJAQyzHdgfnUZJZTup7wsMcc1p2emG4XLDBx0q20kKzZiJBluelTm1BGM5Na0+nrC2OmKf" + + "Bbo4z14qXPqPlM2GwzESw/GnNZBU464rWkjCFf7tOSKNlLZqeZlJIwY7Jt1ElqwfjpW2I0Q5yME4rQOn" + + "K6rxyaOdi5Tj2RkPQ1dspPJfDZ4rVmsI13NgYHSqUlo24lRyafOmhWaN2wvgMYNb8M+9Qc1w8O+JwCCK" + + "6CyuyFGTWMooUkzdZ+KgdyaRZgVzkGkasnE55pke4mnhjTaUGkojpo5WJPmHFbljGDiseM4cVt6cw3Ct" + + "09T1HsbC2+Y+lYGtWeQTiutt1BQVQ1O1DqeK16HJLVnmlxCyuc1AExXS3tiAx4rJktSD6U1Ikqoo45qy" + + "sQI5qIx4PWpV6cmhsBrSeW2BSiUSVFKPSmouMZOPejoBPKgIqt5Yzg8VZJwOenY1GWyGbjC9aExkZDAY" + + "BojjIOTkGl3qW61KzhhnsKeoCKpdgK2LexHlhsZPesdW2yhjx3robG4jkiO0jNRIaMma3Eb5YcZrTsnU" + + "YANVNTJWNnHrWVHqDqn3jkdOaSjdXC9maGp3YMny8+1VLe5KtkY9aoz3O/ac+uaZDJtbOe2K1UdCb6mp" + + "JdGVSc4AqNr4+b5YI2gVQMvyMfwqBZOeTz60+UXMbEF3nBPc1sJqiLH1rlFl2twc4qWFZJpFQsQCc1Mo" + + "XGnY3DK1xMi9jzxWmkaMWJACrwKx4ruO1XdkFu3NVbjWZeVQ7VFZKLZd0al9cRKWwFyvU1nQXF3dyhLN" + + "CQOrnoKj06xn1aTLsUt1OXb19q6SLZEghto9qD0pTkoadSox5tSjBYanEFc3QPfaa27e4eVQJV2uOoql" + + "NMyEAHFXoCHiDnlulZuTe5FWmlG6LApwFRK1SrUpHNTkcuOGFa+nvhhWOQd1aFm5UirW56mrR2Fo/wAg" + + "ou13qap2c2VFXm+Za2vdHLJWOfurbcTxWVPZcHArp54xzVGWMYNSI5Ke2KseKr4C9RW/dQjJrOmth1NU" + + "hGa3J4pFGTtxyelTmHbVvTLeJ7tPMPAPTNMRFFo1/MCCoRT0Dd6zbzTr3T2/fxEqf4l5FekXUasimI5G" + + "Kx5C6yAMCUJxjrWTqSi9jVQUkcGkik9aeWIzjgGuputF0+6Y/KYZP7ynj8RWReeH7u0G5f3keeCvIrWN" + + "WMiHTaMtLj5sMeKuR3bQqzxk8elZ8kbK5DqQwqe1nRFeOTOGArSS0uQuxefUBcwLGTyzc1kzAiUqKlRh" + + "9qwMbQ3SkI8y7IHUGhKwPUgfKNtPJp0wKBcdxUs6eZOvGMgGoHk/fYHReKpCH5yoB5yeaXygQSDUKsWd" + + "gO/6VZsxujfjOKHoAliiyy/OcD1NWpi1uoKHkLj6VSt3K3IVeatX8uUVFP3uTUyV5DWxVaVmwzHIFWtL" + + "0+XUpwBwmck1Wt7d767it4hlnIFduYodMtRbWwBcjDPU1Z8istxwjzMTfHAi2tuuFXg47mlZxFHjPzd8" + + "dqYoVB6seuOaz755ACfuj3PP5VxxV2dIsl0PNxnPtW7aHFkpY4JNchbyjzRnk11UThreDPfNU1Zk1PgZ" + + "cU1IjYqFW3HA6CpBQjy46MwjjPAqeFtpquZAp5pwnUCtOU9FYixu2lxjGTWol0u3rXIrebKlXU296pIz" + + "nVudDcXS881nvcA55rON20nrQCTTsRzhczZNVnYEVO0BbmoWt2WixLmys4XrjNNiAD8rT5AV69KjDDOD" + + "TsLnZ0NhdLt2tgDHbmpZ0DYYfdPpWDEDwVODWraOzwMkh6Dg1Mlc2hIbJEvOAWB9RUYeSEkrnB6gnrUE" + + "k8tuxzyKi/tDcwXIDHpzWDjfY3uT3GnQainyARTkYHTBri7q3ktrx4pF2spwRXWtdFcHODnIrC1XNzqL" + + "yeqj862oys7Mioupkq5V+Bk1Z0+J5JDLwcVCYGAaQqRtNXNPBhgl3jGRlTXRJ6aGS3FuFCRyMMbv6VnB" + + "DtLEcnirTgmHcW3FuMVW3chcc0RQMZCcMSRmr9viO2bA5OSfyqBbfZMMdzVtYCtpKzrtUZxSk0CTM1N3" + + "mFl7U8EsjMR0p1tGZWfA4NSkAptA5Tr71TYki94YcRX8krdVQ4zWyXM05PIXPA9q5+yjYSnbkbu9dFb2" + + "5wW6ntmuSs7yN6a0IpLryv4gBWZeO9ycCTcPRTWldWkQO3arHuSaoSJGgYIBt9F4z+NOFkN6jLK0HmA7" + + "s89fWtqW5aO4t7fBA9c1R062lD+ZJhVHRR6UzUJGfU49n3uFFJ6z1CXwHUxYKjFSgYptunl26g9cU41m" + + "9DjjDU5eR+aaGJ6VZNkzHnNWItPPpW2ptaJQAY9BViOInrWgtgfSpBZMO1FmWuWxXiiA6irKotL5DL2p" + + "vIpktImVFxUM4VR1FIdxFV5o3aqRBm3suCcVnrKS3JrQuLR2ziqotHBwy5Hr3FArI0LI7q00XYNwGfas" + + "20iaLB6j1FbUcQmj460kXYo3qO6Bk6GqVva+eSkiDPattAqLskxxx1qWKCHOVH4VnaxomYF1bhYSDz6e" + + "1YzW5ZjzgoMEd/rXaTRIxJIHvx+tZV3bxB+w+lQp8rLtdHOTrss5Y3HIPB/lT7SVPsZRh25qbWIg0AKn" + + "GajsYAkLFiCpHrW104XMupGYEEKleQPm+lU5og4WRcAg4Iq/CqrAyhsHkdazGjkSTGOB1rSG4mKrk3Kc" + + "5wc1a1G8BjMS98d6he1eDEy/MvWqYkLy7mq0lJ3Ju0aWhxGQy8dBxWiNKDSZXoetUtIYLnsx61tafIW3" + + "bz3rmqyak7GsFoWbPSlUZ4yOlWZlES7YwCzdD6VIlyqE7T0GakgliYq7kcc4xWC1epqyi9g7FMLlnHJP" + + "QCnDTFOAAMDvV+a6A46e1VHvMfKpxVtk2Y26CW6bIxj1IHSs2CFbrU0bGQnc+tSXM7O2FFNtmYXA2de5" + + "oi9RNaHTCPKDPamNgd6fHKPJA6nFRMSe1KRMI6luLTckfLV2PS8DkVtJbBO1TeWAOldqiYXMX7Aqjhai" + + "ez9q2ZAB1qq5WhpAZD2ee1Qmx9q2DimELU2GZP2AelIbAHtWv8vpS/J6UWAw200HtUT6YCMYrocJ6U10" + + "THSnYDmjYmJsgYqeNCFzjB9q1JEX8PQ1CI054xn0qWhpmHclQ+4sT7CnwXi4wpYEdjUGpRokjEPgZ6EV" + + "SRnyChVx14PSsJm0TQurkk5U9Kz5D5nOTn0xTpGyRtOD6Gow+CAwwfWsdTQzNZkMcY2g4I5BqKJw2mBl" + + "JGOvtT9WbcrA9ahtDnTCVwccEV1x+BGL+IjRd6blJ5GeO9Vp32NuUnntU0LgwlTkDP5Gq8ikyDHzc1qt" + + "yHsWzOBa4fgN2qlHbK78HINWL5Y1t02nHtVeyY78UR2bQPfUvWsbRZ5wQePetCGQqFyevWq6kFwB0NWM" + + "BF5HzVzT943irIuLK4Gc8UjzFFyST9KrqSVO405tpByw96x5TQSS8lb+L/61JHORy3/16ayRgAnqe1Vp" + + "ZBGeOp7Voo3JbsXGkSRsZAP1qW3eNDndjB9axZLllf5F6+tTpJIGQnn6CtPZtIzck9jsbN96buT7VI7E" + + "n0qvpkoa3HFWWGOTWUiobnfTMqDk1Sku+w4rPudSXklqy5NUBbhq7mzkNmW496qPdD1rNN4zjiq0k7mp" + + "A1zdj1qB79V71kPOw6mqU07Hncalmisbx1RR3pP7VX+9XLSTN/eNQmZv7xpajsjsBqq/3qDqq/3hXHee" + + "w/iP50xrqQdGNPUTOwOoo/B/SpIp1c4IJH1rj4LyXfyc1v6ZMZGANDJRX16yVnDo7AN6VmQxFMcg/U4J" + + "rsNUsy9gXVQdoziuV3RyoCq89CKxqG0GRyuwXnk/7X+NBIeIDk+xqCU+W2RuX36VUbVhFJsWIPnuKzjF" + + "y2NHJJBqUJeMsPxqjbk2xKEnbKOPrWxeHzrDeoIOO46VjxhrmxbPLRnIxW8H7upk9yGIn50PXNLEzCfa" + + "cUjSA7JVGOzCpQMsZSOFGcVqQQ3snm3CoMYpqxNA6yHin2lu1zNu7bs5q5qKCOLp3o5rNRC19R8AMigg" + + "/NU6uqHBPOOpqDRwXMjduwPSq1/dD7UyR5Yjgn1rJxvJo0UrK5deU7hg8HpT423IOay4rpxw8ZxV6G6j" + + "RPmHWplBoqM7lncC2W6DvVS4uYtx2kcGqt5qAkJReAPSqqL5hwoJNaQpdWRKp0RbE0e4E9RVuJzcSoiE" + + "kDrVJLBxGWbI9q09Eid7oIq529+wpytbQlN9Tq9Nh8q2XI5qd1JPerEMDLGAcUMhrm3NE7HMyanLKepq" + + "S2kZ2GTVqbwlqtueYN4/2TVzR/D9zLcgXMUka56YrpujmLFnbPcYWNSx+lay+GrmVM8D8K6rTtJgs4lC" + + "LzWkFA6CrUG9wPPJfCF43Qj8qpy+Dbwclh+Ven4pCgPUCn7PzA8o/wCELvJTgMAfTFNPgO//AL4/KvWB" + + "EoOQBTto9KPZ+YHj0vgi/jUkEH8K57ULK402TbcxMq/3gOK+gDGrdQKx9Z8P2upW7q8YOR6UnBrZgeIQ" + + "zxFx8zZ9xXT6NIhcc5/Cs7UvBt9YXx+zRGSHPGeMVo6dp11AV8yMrj3qW0CZ2ccUc9ttI6iuH1zT5NHm" + + "aWNQ8JOT6rXbWAPlANUGrW6zQMpAPHeoZojzGe+kuR+7IOepCinQae7x7yyljzggCqN/Ysl9JHuKnPAB" + + "7VNPFLaaWWRz975uhJFKyWiZd31NGDiJoJ9pQ8AjtVCCxlsrl8LviboQKzZZmXLF29V56iptK1aaG5VZ" + + "jvhYhSD2zVOnJJ2EpoS9t/LlYrwj/oalsYWlBiPUZH1FaV/ZBLgSE5jfHGKtWVsv2gEDr1qPaaWHy63K" + + "FtZi1bDfe7+9R6hayTjCAnmtjUrcKy8cHuO1KqrFaeY3Zc1HM78xVtLGUlv9jsNithz1NUYUs0JDSEyH" + + "qarNdNd3EiyMQvJUA1SVsTcDgcV0RpvqzJyXQ3rgQLF97I9qwppGaQhTwOlWrc75oozyCcYp2oQJbz4X" + + "jvTilF2E3dEFnZtcSDnAroLawjhO1Wz61maUrSSE9hVq7vjattj5Y1nUcpS5UaQslc1Gt1KYJ/Ctfw/Y" + + "RIpZQefauZ0tbzUrtQSSmeTXpOn2K28Cr1OKy5HHRjcrgYsCozEa0PKppip2Fc7Mop6gUgjQHhR+VPor" + + "uMAooooAKKKKACiiigApKWigCKS3jk+8oNUrjTIiCQorSpr4280rAYQthGSAKpXkW5Tg4ramXk4rPuYi" + + "wOKwki4nmfinSpCxnjGSPSsG0vo5oWt7s7VIxur0vULIyIwI/KvONc0Wa1mZ40ZkJz9KhWejKfczLq0l" + + "gbbw0f8AAc8fnVPY4YDbjB7GtnTvMI8tjtHoeRW15AktnHkpvxwQtU6rjow5E9StDOb3SUZj+8ThvrWt" + + "ZQjzFxnkZrA0aK5W4kgC5UnqRwK6qCIxHI5AHJrGS940WxDqiDygxHTrWRqM2zTTt7rgVtXUZljIfvXJ" + + "a5cMsQg2kYPX2oUbySHsjFIYOCBhh3oMblidoyfetvR40eIeZGrZ6ZFas2m/JvwsYx1C81u6tnaxlydT" + + "nLSD7KPtNwQCPug9TVO5uGurgu54J/Krt7aSCUs7Fl7Z6moba23SDfEzZPAAxVJr4mT5Gjpi+VEWBCr6" + + "9zUsenXGq3HyA7c+laen6d520yAxqvRRXX6dBHAgCAVz83vXNbaWKmgeHjp6Av8AeNdKseBRE2RUuKZD" + + "GFaaVqQ0lAF+PxBEfvDFWU1m2bq2K88/tWL+8KcNTi/vVtzSIsejrqVs3/LQU8Xtuf8AlqtecDUo/wC/" + + "+tO/tJf+en60+eQWPRxdwH/lov50faof+ei/nXnH9pr/AM9T+dH9qD/nr+tHOwsej/a4B/y0X86ab63H" + + "WVfzrzn+1F/56H86adTTu/60c7Cx6I2p2q9ZVqJtatF/jz9K8+/tOP8Av/rR/akQ/iFLnkHKd4dciPCK" + + "TTo7qS45xgVx1hqUUkyrkV19tMnljB7UJt7sLE7DA5rOuJME4FSz3qhtuazLi+jL7cjNKTKSK11MRkms" + + "i52TKcgH61Z1Sf8AdHFYz3gWINmsmWhY7G3jkyIlBPoK0I448Y2AGqKXG9etWIrlT8pOGFSU0LJAkTZR" + + "MZqwqLHEPpzUFzOqwlj09aT7Sph5I6UwSFn2lc9DWLdWEF6211y3tV6e5TbwwNVrSdDclM5alfUvkdrj" + + "LPQ0tsfMSorRYBhsHIHrStJxg5A9aVGQDI7d6H3IsU5rKI5ZwBnrVXy4YuI41x6gUuqXoY4jywHUKeRW" + + "dFICdytkfrUso2bd8H2rXt5sYOa5Zr4RrgEE1o2FyzxlmYYx0oQM662uAw4NWhJmuZsLv5yM1sxzZFWm" + + "ZyRe3Uhaq/m0eZTJRyf/AAjh/vMPxph8OS9pXH41urq645UGnf2xFnBQA09AsYA8PzYyJXzSDQLk/wDL" + + "Zq6M6rbr1XmpBqVsQCAOaNAscs2gXfaZqadBu/8Ans1dZ9vtj6DFOF3al8d6YWOSHh66I5nanDw1ct/y" + + "3euvFzaFsZ5HWpRc2ueG/SiwWRxLeGboHHnvTv8AhFp8ZM7/AJ12hubXu6j60Ge2PSReOtKwWOVs9Blt" + + "XDCV2Pua3Yrue2TBy2Ks+fEOrrTm8phyw5osFjCudVlFxkq2KzLrU5BcB1DYz6V0c9tGzcYqnNZoTjAp" + + "WZRnS6gs8W3BzWTcTFYiqg/Wt57NEUgFfzqhPCu0ng/jSaY0zMtJ5IzhweeakurmQEGPrUwiOTxTHiOO" + + "lT1KHJqJ27JecjBqvK8ikmFyyn+E9qYYXz0PNKqMp6GgcZcr0KklzMZMHhvfpV+ykjgy3WRurYpjBf4h" + + "UibR90c0M0lVclYuCZ3OWOB71HPeELtQkH1HWomZsd6rPvbnHI/WlczIZF8w7wdrDuOh/wAKhdN7cny5" + + "OzdjVrawO4DGeuR1qRYgRgjg9j2p3EU0jk3gTAZ7HrmtWEbY8Dp7UxIMMIyMjGRntV2C2IGB+Ro3AlsQ" + + "Ac81sRyYFZ0EDL9as7WBo2IkXlkJ709WOetU4ydxBO33qdVwf9YM00JGEWJUMg5qPdlRkkPnrTM4O0N8" + + "p7+lOMYbnONo5qiiQONoJ5OKC5Z1ZR93mmCULtVQDg80O43EsBtOMUAPLAuSTyacJHwQpyxqHcPvMOnS" + + "nE7j9RkH0oAlWU+ZlG3HHNK7vtJD4YDHWoGRvlIIyAcmnCb5WJG4j0HWgCSKVmIBO71FKZMZbfycj0xU" + + "QZV54y3aglcfLyVPpQFiUSl9552kUkc8pTY5OGxznpUaZDKxUAc4zSsJQAgI4GcjigCUTOGYBiccjJxT" + + "mnlkR1LNyCAR2FVC8gJXcG7cjvSqgMqbpCACTjP+eKQFzzpVCYkJB6MP60C4kkU7kGRyPeoJipfJHHBw" + + "ATio0KktukO884A6YpgTzXBBwUTJI24AwBSFVBxI0ZPO35B8xqGVkCAZJIHOQScZp0mUBYnAX+9346UX" + + "Ak3ArgW0XA6lRyajjMXmMoiikPJ+5gjnio1BX5Vbbk5CFdwAz1pEExJVs49l6+9FwJGiRtzCKMBckLjr" + + "jtxQwt0b5bfgnGcnj9ajY7NsfOBztU/eB6f1p7TbQiyhVVhkkf0NFwJP3eSvlqz7SQNx7fjSeXAhUSp8" + + "zZ4DMAPTPNVGkCM4RmkTH3QByfr6VIJWLFFUhVP3c9hj/GgCUrblcRxjdnABc+v1pESLzCu0BSOCHJpr" + + "uyqPLGBgdcE9qWfccKkjHPIAGCe55pASx+U4+RcnnPzdOeKeLtVAPRfXjpVJXHmbkjwxO193AOPenEsC" + + "6FcLg5BXOR7UwL51DYwCnKkH5uOfpxThqBaTChmGcdACf0qioWKLap/djhiw/lUTTBBlXUNwu4jGPrQF" + + "jVe/8pNxGPwHH6UPqixkAg88c1mO4k/dhsnOSegaka5IuFUnf/Cc0hWEYg52jAApA5I4HfvQQclexNGW" + + "yCo6CmMQKfNyB8voO1SEggKMMB69aaCVwBgMaSNdrZbGetAEpYbcD7wPOaRwQN60wEGQqzYHXilMiopT" + + "gFqAFEmRtLEKelBQ7ODwp3fUVE2CwXjI7etOB2kEnCnk0gHMWCZBBA5waUOQFKjDD73vQoV28xecDjml" + + "YhnDNuwMfdoAeJGBLlei9M9DTT8zHy3OWPJ6dqVQecjO4ZHPamq5YNgkAcZxQAsbeXwo3DB5YdaVcHBx" + + "jPy8/pTTkptZhsHIP1pWCchAoZOuT29RQA4EjaMEtgkvnv6UuXdkbIV+BtA4NMWbdsY4jwOcetNlmCyA" + + "nhlzyO9ACiXytrAEuq/M/b3/AKUFfMA3R7v9psfN+FRo0ZLsOSozj1HpQCXLFFJ3EcE9fwoAcGdxMqsh" + + "ZABux26kU0gvFtiyu37pHfrxSARZZXVFkA6cnj2oiKDYy/LzhSvANADtzBOW5U8gr0Hp/n0p5EbgyIev" + + "A+UcY/rUB8vzMqSDux0yMU/Cb5I4xnYOAOOR1oAQSojPt5fA2grx7mhtyysp++xI3E8fhUIDGHzNzEqC" + + "c4GSO4pgkVleNju2EbWXJIPX+tAFoSS+YZECFcYZc9cfypuQJQ5YKSSoAOMcfpTVPlTAbfMVuGI65xmn" + + "bvMcvltrA5XGcfWgALRjDMSXVcbVByeal8xGjByFkYZIA4x3qKNzIzMVztBGf73HUflUZd5REQ2MAk7R" + + "1HrQAquBAVL5cE7QOQB/WpCFjQblRt3p16+lVvNaVsJtx95iRwRUsLLLM5LEEfJuP+fpQA5iylVHCY25" + + "+p4pgcLlApaReASc/p+NNztnZWG5Sc4PC/jRKjSnICkFtodRjaRQBYUEsGJzzSM+CQenak3KEznpRGvt" + + "nuDQABQMtgk4oVhhQeCT1p+SRzx2zUZA4A5weaAH7xk8Co16/NzzkVIQGITjPceoowPMKjGBxg0AMGyQ" + + "ccFT1Jpy7VG0c55Ge1REHIGMj2qVOUyMjHHNCAXeSBuyQB/D0pFUeWgxgg8ikI2ABn3BjyQOKC26Js5U" + + "KeCOtADvMKjhTxwMHoaESVyGz2wQecmow5EqEAfN61IU5BGVwcsR0oAPvwhwNuBgjrimoFWXIB564z17" + + "Usf+sw4EeGxt9fSnytsJPX1wRzQBGhL/AC4Kruzg8EikMfAO7gtn2/Cn/e4XI4+8fWmnyhEVHBVTgA5N" + + "ACNEHCvGnlqDkn6+v8qd5wQMEGM5weeKbDxuX5lAUHvnGKVHYTmADeeDnnP4flQAFkYDeMsRjOMfXmmp" + + "E4ywVQct8uePrQ5Ryqldz4wT2z3/ABoyqkRhm2HkL3Oc8ZoAEbywHTnBz/umo45Sc8MApwWPUk84Gal3" + + "gomQgG/LAZ6Djp60x2C/wru+6zngA5/p0oAczB9igtsZfXH+e1JuhjiPeRiqkKOnb+lMXdEyuRkvgBWO" + + "c8f4UTOYuWYDqC3U/wCetADkVwyP5YIHy5JH4ZpIo3ALNtCk856/UGhJUL5jyqMRnHG7/PFMkUIoO0lw" + + "PlBz9RQA4Rt8m5z1xuxjqeBn2pqgpKFAJiAyGx8x4NOkc42oMFskhjUfzbyXPynK5QZIFAD4jHIXdJSo" + + "HDA8546Uxtodd0iDHGQeVPsKcxVPuA7duSSMg9v5UNgyGVhtHRsAYx659aAHsElixJIwA4znH48VGVYB" + + "jGFMa9ieRSJhHCI24KCDu7+/0pMxwuWQEqMlsnlqQFgjd8rde9S4IUbTjApp2nADD607PAw1MAMilCMc" + + "ikBBzjOTQqKWwR1pUR1fABx3oATJ8wsueOMHijaWJPpzk1In3XUn5vUU4AMmCcH6UAV2di27qRxxUpDA" + + "fdO5ecgfzpBEJGYg4IGBSh9uVLHJ60ANDEMDjdk8g0pQFWbGTT8FiVK557d6a2VGeQvb1FADWjYKdwHy" + + "84+tOVsDDDt90jNBk3yA8lgBnHNI5JUsRnPTA6UAARSNxG9up9qiLmRyI/mBOODincOm1gwdeBx1FKiG" + + "Mhwo+bgigBJEWNiTuUDnAbPaiNoxyxwTj34pFYtMwbGw9QewpwjVjjd8q8ADgUASearEOqsVXgDP3uOK" + + "gLxh/MCt847GmtAIpDEmVXlmbPNPkCvONrfOg+UN/n60AAyVLoBvXCnByB71Ai52syblJ6sRhhVpUDFg" + + "G2q2MKTj8ajIACxqvyA8DoM9DxQBHIrZJPPOQucbgPehiqxh8ghVycjnGf5UjeZ1YkBjksfUetKVzHhl" + + "OG7jBI9P60AEIaIAygKTjAPbg4FClZl3MeJOPu8HPFK5Jl3rsbC4XdxnrmmLuXCwxkL3XHXP1/z1oAdc" + + "REGNY13tnPoM+3vUjyCSLaQW2t8wzgn3qAIEmG5y+CGHcA05GVV25AEhJTnkDpQA0H5mUZcBsEsMc+n0" + + "qMEAbA4BUkEHPNTRh5Y2wTuJ6MOvSovLEsSKoMar/Fnk9e9AEzMWg2hsEkjI71DCWhh+V94Xnjk/lTDG" + + "8kRchtw56dc9z/nvTjIftC+YoUtwMHqPegBiYZ98Qdc8fMP5VI+Vh8zZltuCPf2odlWMlmIIOwsw4P69" + + "qQzPJJgDeASMHuOx+lAH/9k="; + + beforeEach(function () { + div = document.createElement('div'); + div.style.width = '800px'; + div.style.height = '600px'; + div.style.visibility = 'hidden'; + + document.body.appendChild(div); + + map = L.map(div); + }); + + afterEach(function () { + if (div) { + document.body.removeChild(div); + } + }); + + function kittenLayerFactory(options) { + return L.tileLayer(placeKitten, options || {}); + } + + function eachImg(layer, callback) { + var imgtags = layer._container.children[0].children; + for (var i in imgtags) { + if (imgtags[i].tagName === 'IMG') { + callback(imgtags[i]); + } + } + } + + describe("number of kittens loaded", function () { + + var clock, kittenLayer, counts; + + // animationFrame helper, just runs requestAnimFrame() a given number of times + function runFrames(n) { + return _runFrames(n)(); + } + + function _runFrames(n) { + if (n) { + return function () { + clock.tick(40); // 40msec/frame ~= 25fps + map.fire('_frame'); + L.Util.requestAnimFrame(_runFrames(n - 1)); + }; + } else { + return L.Util.falseFn; + } + } + + beforeEach(function () { + clock = sinon.useFakeTimers(); + + kittenLayer = kittenLayerFactory({keepBuffer: 0}); + + counts = { + tileload: 0, + tileerror: 0, + tileloadstart: 0, + tileunload: 0 + }; + + kittenLayer.on('tileload tileunload tileerror tileloadstart', function (ev) { + // console.log(ev.type); + counts[ev.type]++; + }); + // grid.on('tileunload', function (ev) { + // console.log(ev.type, ev.coords, counts); + // }); + + map.options.fadeAnimation = false; + map.options.zoomAnimation = false; + }); + + afterEach(function () { + clock.restore(); + kittenLayer.off(); + kittenLayer = undefined; + counts = undefined; + }); + + it("Loads 8 kittens zoom 1", function (done) { + + kittenLayer.on('load', function () { + expect(counts.tileloadstart).to.be(8); + expect(counts.tileload).to.be(8); + expect(counts.tileunload).to.be(0); + expect(kittenLayer._container.querySelectorAll('img').length).to.be(8); + done(); + }); + + map.addLayer(kittenLayer).setView([0, 0], 1); + clock.tick(250); + }); + + + // NOTE: This test has different behaviour in PhantomJS and graphical + // browsers due to CSS animations! + it.skipInPhantom("Loads 290, unloads 275 kittens on MAD-TRD flyTo()", function (done) { + + this.timeout(10000); // This test takes longer than usual due to frames + + var mad = [40.40, -3.7], trd = [63.41, 10.41]; + + kittenLayer.on('load', function () { + expect(counts.tileloadstart).to.be(12); + expect(counts.tileload).to.be(12); + expect(counts.tileunload).to.be(0); + kittenLayer.off('load'); + + map.on('zoomend', function () { + expect(counts.tileloadstart).to.be(290); + expect(counts.tileunload).to.be(275); + + // image tiles take time, so then might not be fully loaded yet. + expect(counts.tileload).to.be.lessThan(counts.tileloadstart + 1); + expect(counts.tileload).to.be.greaterThan(counts.tileunload); + expect(kittenLayer._container.querySelectorAll('img').length).to.be(15); + done(); + }); + + map.flyTo(trd, 12, {animate: true}); + + // map.on('_frame', function () { + // console.log('frame', counts); + // }); + + runFrames(500); + }); + + map.addLayer(kittenLayer).setView(mad, 12); + clock.tick(250); + }); + + }); + + describe('url template', function () { + beforeEach(function () { + div = document.createElement('div'); + div.style.width = '400px'; + div.style.height = '400px'; + div.style.visibility = 'hidden'; + + document.body.appendChild(div); + + map = L.map(div).setView([0, 0], 2); + }); + + it('replaces {y} with y coordinate', function () { + var layer = L.tileLayer('http://example.com/{z}/{y}/{x}.png').addTo(map); + + var urls = [ + 'http://example.com/2/1/1.png', + 'http://example.com/2/1/2.png', + 'http://example.com/2/2/1.png', + 'http://example.com/2/2/2.png' + ]; + + var i = 0; + eachImg(layer, function (img) { + expect(img.src).to.eql(urls[i]); + i++; + }); + }); + + it('replaces {-y} with inverse y coordinate', function () { + var layer = L.tileLayer('http://example.com/{z}/{-y}/{x}.png').addTo(map); + var urls = [ + 'http://example.com/2/2/1.png', + 'http://example.com/2/2/2.png', + 'http://example.com/2/1/1.png', + 'http://example.com/2/1/2.png' + ]; + var i = 0; + eachImg(layer, function (img) { + expect(img.src).to.eql(urls[i]); + i++; + }); + }); + + it('Does not replace {-y} on map with infinite CRS', function () { + var simplediv = document.createElement('div'); + simplediv.style.width = '400px'; + simplediv.style.height = '400px'; + simplediv.style.visibility = 'hidden'; + + document.body.appendChild(simplediv); + var simpleMap = L.map(simplediv, { + crs: L.CRS.Simple + }).setView([0, 0], 5); + var layer = L.tileLayer('http://example.com/{z}/{-y}/{x}.png'); + + expect(function () { + layer.addTo(simpleMap); + }).to.throwError('No value provided for variable {-y}'); + + simpleMap.remove(); + document.body.removeChild(simplediv); + }); + + it('replaces {s} with [abc] by default', function () { + var layer = L.tileLayer('http://{s}.example.com/{z}/{-y}/{x}.png').addTo(map); + + eachImg(layer, function (img) { + expect(['a', 'b', 'c'].indexOf(img.src[7]) >= 0).to.eql(true); + }); + }); + + it('replaces {s} with specified prefixes', function () { + var layer = L.tileLayer('http://{s}.example.com/{z}/{-y}/{x}.png', { + subdomains: 'qrs' + }).addTo(map); + + eachImg(layer, function (img) { + expect(['q', 'r', 's'].indexOf(img.src[7]) >= 0).to.eql(true); + }); + }); + + it('uses zoomOffset option', function () { + // Map view is set at zoom 2 in beforeEach. + var layer = L.tileLayer('http://example.com/{z}/{y}/{x}.png', { + zoomOffset: 1 // => zoom 2 + zoomOffset 1 => z 3 in URL. + }).addTo(map); + + var urls = [ + 'http://example.com/3/1/1.png', + 'http://example.com/3/1/2.png', + 'http://example.com/3/2/1.png', + 'http://example.com/3/2/2.png' + ]; + + var i = 0; + eachImg(layer, function (img) { + expect(img.src).to.eql(urls[i]); + i++; + }); + }); + + it('uses negative zoomOffset option', function () { + // Map view is set at zoom 2 in beforeEach. + var layer = L.tileLayer('http://example.com/{z}/{y}/{x}.png', { + zoomOffset: -3 // => zoom 2 + zoomOffset -3 => z -1 in URL. + }).addTo(map); + + var urls = [ + 'http://example.com/-1/1/1.png', + 'http://example.com/-1/1/2.png', + 'http://example.com/-1/2/1.png', + 'http://example.com/-1/2/2.png' + ]; + + var i = 0; + eachImg(layer, function (img) { + expect(img.src).to.eql(urls[i]); + i++; + }); + }); + + }); + + describe('options', function () { + + beforeEach(function () { + div = document.createElement('div'); + div.style.width = '400px'; + div.style.height = '400px'; + + map = L.map(div).setView([0, 0], 2); + }); + + afterEach(function () { + map = null; + div = null; + }); + + // https://html.spec.whatwg.org/multipage/urls-and-fetching.html#cors-settings-attributes + testCrossOriginValue(undefined, null); // Falsy value (other than empty string '') => no attribute set. + testCrossOriginValue(true, ''); + testCrossOriginValue('', ''); + testCrossOriginValue('anonymous', 'anonymous'); + testCrossOriginValue('use-credentials', 'use-credentials'); + + function testCrossOriginValue(crossOrigin, expectedValue) { + it('uses crossOrigin value ' + crossOrigin, function () { + var layer = L.tileLayer('http://example.com/{z}/{y}/{x}.png', { + crossOrigin: crossOrigin + }).addTo(map); + + eachImg(layer, function (img) { + expect(img.getAttribute('crossorigin')).to.be(expectedValue); + }); + }); + } + }); + + describe('#setUrl', function () { + it('fires only one load event', function (done) { + var layer = L.tileLayer(placeKitten).addTo(map); + var counts = { + load: 0, + tileload: 0 + }; + map.setView([0, 0], 1); + + layer.on('tileload load', function (e) { + counts[e.type]++; + }); + + layer.setUrl(placeKitten); + + setTimeout(function () { + expect(counts.load).to.equal(1); + expect(counts.tileload).to.equal(8); + done(); + }, 250); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CanvasSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CanvasSpec.js new file mode 100644 index 000000000..3d0349176 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CanvasSpec.js @@ -0,0 +1,301 @@ +describe('Canvas', function () { + + var c, map, p2ll, latLngs; + + before(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + c.style.position = 'absolute'; + c.style.top = '0'; + c.style.left = '0'; + document.body.appendChild(c); + map = new L.Map(c, {preferCanvas: true, zoomControl: false}); + map.setView([0, 0], 6); + p2ll = function (x, y) { + return map.layerPointToLatLng([x, y]); + }; + latLngs = [p2ll(0, 0), p2ll(0, 100), p2ll(100, 100), p2ll(100, 0)]; + }); + + after(function () { + document.body.removeChild(c); + }); + + describe("#events", function () { + var layer; + + beforeEach(function () { + layer = L.polygon(latLngs).addTo(map); + }); + + afterEach(function () { + layer.remove(); + }); + + it("should fire event when layer contains mouse", function () { + var spy = sinon.spy(); + layer.on('click', spy); + happen.at('click', 50, 50); // Click on the layer. + expect(spy.callCount).to.eql(1); + happen.at('click', 150, 150); // Click outside layer. + expect(spy.callCount).to.eql(1); + layer.off("click", spy); + }); + + it("DOM events propagate from canvas polygon to map", function () { + var spy = sinon.spy(); + map.on("click", spy); + happen.at('click', 50, 50); + expect(spy.callCount).to.eql(1); + map.off("click", spy); + }); + + it("DOM events fired on canvas polygon can be cancelled before being caught by the map", function () { + var mapSpy = sinon.spy(); + var layerSpy = sinon.spy(); + map.on("click", mapSpy); + layer.on("click", L.DomEvent.stopPropagation).on("click", layerSpy); + happen.at('click', 50, 50); + expect(layerSpy.callCount).to.eql(1); + expect(mapSpy.callCount).to.eql(0); + map.off("click", mapSpy); + layer.off("click", L.DomEvent.stopPropagation).off("click", layerSpy); + }); + + it("DOM events fired on canvas polygon are propagated only once to the map even when two layers contains the event", function () { + var spy = sinon.spy(); + var layer2 = L.polygon(latLngs).addTo(map); + map.on("click", spy); + happen.at('click', 50, 50); + expect(spy.callCount).to.eql(1); + layer2.remove(); + map.off("click", spy); + }); + + it("should fire preclick before click", function () { + var clickSpy = sinon.spy(); + var preclickSpy = sinon.spy(); + layer.on('click', clickSpy); + layer.on('preclick', preclickSpy); + layer.once('preclick', function (e) { + expect(clickSpy.called).to.be(false); + }); + happen.at('click', 50, 50); // Click on the layer. + expect(clickSpy.callCount).to.eql(1); + expect(preclickSpy.callCount).to.eql(1); + happen.at('click', 150, 150); // Click outside layer. + expect(clickSpy.callCount).to.eql(1); + expect(preclickSpy.callCount).to.eql(1); + layer.off(); + }); + + it("should not fire click when dragging the map on top of it", function (done) { + var downSpy = sinon.spy(); + var clickSpy = sinon.spy(); + var preclickSpy = sinon.spy(); + layer.on('click', clickSpy); + layer.on('preclick', preclickSpy); + layer.on('mousedown', downSpy); + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + // Prosthetic does not fire a click when we down+up, but it real world + // browsers would, so let's simulate it. + happen.at('click', 70, 60); + expect(downSpy.called).to.be(true); + expect(clickSpy.called).to.be(false); + expect(preclickSpy.called).to.be(false); + layer.off(); + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + mouse.moveTo(50, 50, 0) + .down().moveBy(20, 10, 200).up(); + }); + + }); + + describe("#events(interactive=false)", function () { + var layer; + + beforeEach(function () { + layer = L.polygon(latLngs, {interactive: false}).addTo(map); + }); + + afterEach(function () { + layer.remove(); + }); + + it("should not fire click when not interactive", function () { + var spy = sinon.spy(); + layer.on('click', spy); + happen.at('click', 50, 50); // Click on the layer. + expect(spy.callCount).to.eql(0); + happen.at('click', 150, 150); // Click outside layer. + expect(spy.callCount).to.eql(0); + layer.off("click", spy); + }); + + }); + + describe('#dashArray', function () { + it('can add polyline with dashArray', function () { + var layer = L.polygon(latLngs, { + dashArray: "5,5" + }).addTo(map); + }); + it('can setStyle with dashArray', function () { + var layer = L.polygon(latLngs).addTo(map); + layer.setStyle({ + dashArray: "5,5" + }); + }); + }); + + it('removes vector on next animation frame', function (done) { + var layer = L.circle([0, 0]).addTo(map), + layerId = L.stamp(layer), + canvas = map.getRenderer(layer); + + expect(canvas._layers.hasOwnProperty(layerId)).to.be(true); + + map.removeLayer(layer); + // Defer check due to how Canvas renderer manages layer removal. + L.Util.requestAnimFrame(function () { + expect(canvas._layers.hasOwnProperty(layerId)).to.be(false); + done(); + }, this); + }); + + it('adds vectors even if they have been removed just before', function (done) { + var layer = L.circle([0, 0]).addTo(map), + layerId = L.stamp(layer), + canvas = map.getRenderer(layer); + + expect(canvas._layers.hasOwnProperty(layerId)).to.be(true); + + map.removeLayer(layer); + map.addLayer(layer); + expect(canvas._layers.hasOwnProperty(layerId)).to.be(true); + // Re-perform a deferred check due to how Canvas renderer manages layer removal. + L.Util.requestAnimFrame(function () { + expect(canvas._layers.hasOwnProperty(layerId)).to.be(true); + done(); + }, this); + }); + + describe('#bringToBack', function () { + + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c, {preferCanvas: true}); + map.setView(new L.LatLng(0, 0), 0); + document.body.appendChild(c); + }); + + afterEach(function () { + document.body.removeChild(c); + }); + + it('is a no-op for layers not on a map', function () { + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]); + expect(path.bringToBack()).to.equal(path); + }); + + it('is a no-op for layers no longer in a LayerGroup', function () { + var group = new L.LayerGroup().addTo(map); + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]).addTo(group); + + group.clearLayers(); + + expect(path.bringToBack()).to.equal(path); + }); + }); + + + describe('#bringToFront', function () { + + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c, {preferCanvas: true}); + map.setView(new L.LatLng(0, 0), 0); + document.body.appendChild(c); + }); + + afterEach(function () { + document.body.removeChild(c); + }); + it('is a no-op for layers not on a map', function () { + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]); + expect(path.bringToFront()).to.equal(path); + }); + + it('is a no-op for layers no longer in a LayerGroup', function () { + var group = new L.LayerGroup().addTo(map); + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]).addTo(group); + + group.clearLayers(); + + expect(path.bringToFront()).to.equal(path); + }); + }); +}); + +describe('Canvas remove', function () { + + var c; + + before(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + c.style.position = 'absolute'; + c.style.top = '0'; + c.style.left = '0'; + document.body.appendChild(c); + }); + + after(function () { + document.body.removeChild(c); + }); + + function createCanvasMap(c, options) { + var map = new L.Map(c, options); + map.setView([0, 0], 6); + var p2ll = function (x, y) { + return map.layerPointToLatLng([x, y]); + }; + var latLngs = [p2ll(0, 0), p2ll(0, 100), p2ll(100, 100), p2ll(100, 0)]; + var layer = L.polygon(latLngs).addTo(map); + return map; + } + + it("can remove the map without errors", function (done) { + var map1 = createCanvasMap(c, {preferCanvas: true, zoomControl: false}); + map1.remove(); + L.Util.requestAnimFrame(function () { done(); }); + }); + + it("can remove renderer without errors", function (done) { + var canvas = L.canvas(); + var map = createCanvasMap(c, {renderer: canvas, zoomControl: false}); + canvas.remove(); + map.remove(); + L.Util.requestAnimFrame(function () { done(); }); + }); + +}); + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CircleMarkerSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CircleMarkerSpec.js new file mode 100644 index 000000000..11094392d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CircleMarkerSpec.js @@ -0,0 +1,53 @@ +describe('CircleMarker', function () { + describe("#_radius", function () { + var map; + beforeEach(function () { + map = L.map(document.createElement('div')); + map.setView([0, 0], 1); + }); + describe("when a CircleMarker is added to the map ", function () { + describe("with a radius set as an option", function () { + it("takes that radius", function () { + var marker = L.circleMarker([0, 0], {radius: 20}).addTo(map); + + expect(marker._radius).to.be(20); + }); + }); + + describe("and radius is set before adding it", function () { + it("takes that radius", function () { + var marker = L.circleMarker([0, 0], {radius: 20}); + marker.setRadius(15); + marker.addTo(map); + expect(marker._radius).to.be(15); + }); + }); + + describe("and radius is set after adding it", function () { + it("takes that radius", function () { + var marker = L.circleMarker([0, 0], {radius: 20}); + marker.addTo(map); + marker.setRadius(15); + expect(marker._radius).to.be(15); + }); + }); + + describe("and setStyle is used to change the radius after adding", function () { + it("takes the given radius", function () { + var marker = L.circleMarker([0, 0], {radius: 20}); + marker.addTo(map); + marker.setStyle({radius: 15}); + expect(marker._radius).to.be(15); + }); + }); + describe("and setStyle is used to change the radius before adding", function () { + it("takes the given radius", function () { + var marker = L.circleMarker([0, 0], {radius: 20}); + marker.setStyle({radius: 15}); + marker.addTo(map); + expect(marker._radius).to.be(15); + }); + }); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CircleSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CircleSpec.js new file mode 100644 index 000000000..65d4a349c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/CircleSpec.js @@ -0,0 +1,52 @@ +describe('Circle', function () { + + describe('#init', function () { + + it('uses default radius if not given', function () { + var circle = L.circle([0, 0]); + expect(circle.getRadius()).to.eql(10); + }); + + it('throws error if radius is NaN', function () { + expect(function () { + L.circle([0, 0], NaN); + }).to.throwException('Circle radius cannot be NaN'); + }); + + }); + + describe('#getBounds', function () { + + var map, circle; + + beforeEach(function () { + map = L.map(document.createElement('div')).setView([0, 0], 4); + circle = L.circle([50, 30], {radius: 200}).addTo(map); + }); + + it('returns bounds', function () { + var bounds = circle.getBounds(); + + expect(bounds.getSouthWest()).nearLatLng(new L.LatLng(49.99820, 29.99720)); + expect(bounds.getNorthEast()).nearLatLng(new L.LatLng(50.00179, 30.00279)); + }); + }); + + describe('Legacy factory', function () { + + var map, circle; + + beforeEach(function () { + map = L.map(document.createElement('div')).setView([0, 0], 4); + circle = L.circle([50, 30], 200).addTo(map); + }); + + it('returns same bounds as 1.0 factory', function () { + var bounds = circle.getBounds(); + + expect(bounds.getSouthWest()).nearLatLng(new L.LatLng(49.99820, 29.99720)); + expect(bounds.getNorthEast()).nearLatLng(new L.LatLng(50.00179, 30.00279)); + }); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PathSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PathSpec.js new file mode 100644 index 000000000..ee35c1a1a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PathSpec.js @@ -0,0 +1,144 @@ +describe('Path', function () { + + // The following two tests are skipped, as the ES6-ifycation of Leaflet + // means that L.Path is no longer visible. + describe('#bringToBack', function () { + + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c); + map.setView(new L.LatLng(0, 0), 0); + document.body.appendChild(c); + }); + + afterEach(function () { + document.body.removeChild(c); + }); + it('is a no-op for layers not on a map', function () { + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]); + expect(path.bringToBack()).to.equal(path); + }); + + it('is a no-op for layers no longer in a LayerGroup', function () { + var group = new L.LayerGroup().addTo(map); + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]).addTo(group); + + group.clearLayers(); + + expect(path.bringToBack()).to.equal(path); + }); + }); + + describe('#bringToFront', function () { + + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c); + map.setView(new L.LatLng(0, 0), 0); + document.body.appendChild(c); + }); + + afterEach(function () { + document.body.removeChild(c); + }); + it('is a no-op for layers not on a map', function () { + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]); + expect(path.bringToFront()).to.equal(path); + }); + + it('is a no-op for layers no longer in a LayerGroup', function () { + var group = new L.LayerGroup().addTo(map); + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]).addTo(group); + + group.clearLayers(); + + expect(path.bringToFront()).to.equal(path); + }); + }); + + describe('#events', function () { + + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c); + map.setView(new L.LatLng(0, 0), 0); + document.body.appendChild(c); + }); + + afterEach(function () { + document.body.removeChild(c); + }); + + it('fires click event', function () { + var spy = sinon.spy(); + var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]]).addTo(map); + layer.on('click', spy); + happen.click(layer._path); + expect(spy.called).to.be.ok(); + }); + + it('propagates click event by default', function () { + var spy = sinon.spy(); + var spy2 = sinon.spy(); + var mapSpy = sinon.spy(); + var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]]).addTo(map); + layer.on('click', spy); + layer.on('click', spy2); + map.on('click', mapSpy); + happen.click(layer._path); + expect(spy.called).to.be.ok(); + expect(spy2.called).to.be.ok(); + expect(mapSpy.called).to.be.ok(); + }); + + it('can add a layer while being inside a moveend handler', function (done) { + var zoneLayer = L.layerGroup(); + var polygon; + map.addLayer(zoneLayer); + + map.on('moveend', function () { + zoneLayer.clearLayers(); + polygon = new L.Polygon([[1, 2], [3, 4], [5, 6]]); + zoneLayer.addLayer(polygon); + }); + + map.invalidateSize(); + map.setView([1, 2], 12, {animate: false}); + + map.panBy([-260, 0]); + setTimeout(function () { + expect(polygon._parts.length).to.be(0); + map.panBy([260, 0]); + setTimeout(function () { + expect(polygon._parts.length).to.be(1); + done(); + }, 300); + }, 300); + }); + + it('it should return tolerance with stroke', function () { + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]); + var layer = path.addTo(map); + expect(path._clickTolerance()).to.equal(path.options.weight / 2); + }); + + it('it should return zero tolerance without stroke', function () { + var path = new L.Polyline([[1, 2], [3, 4], [5, 6]]); + var layer = path.addTo(map); + path.options.stroke = false; + expect(path._clickTolerance()).to.equal(0); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolygonSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolygonSpec.js new file mode 100644 index 000000000..05b97da98 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolygonSpec.js @@ -0,0 +1,328 @@ +describe('Polygon', function () { + + var c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + var map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); + + describe("#initialize", function () { + it("should never be flat", function () { + var latLngs = [[1, 2], [3, 4]]; + + var polygon = new L.Polygon(latLngs); + + expect(L.LineUtil.isFlat(polygon._latlngs)).to.be(false); + expect(polygon.getLatLngs()).to.eql(polygon._latlngs); + }); + + it("doesn't overwrite the given latlng array", function () { + var originalLatLngs = [ + [1, 2], + [3, 4] + ]; + var sourceLatLngs = originalLatLngs.slice(); + + var polygon = new L.Polygon(sourceLatLngs); + + expect(sourceLatLngs).to.eql(originalLatLngs); + expect(polygon._latlngs).to.not.eql(sourceLatLngs); + }); + + it("can be called with an empty array", function () { + var polygon = new L.Polygon([]); + expect(polygon._latlngs).to.eql([[]]); + expect(polygon.getLatLngs()).to.eql(polygon._latlngs); + }); + + it("can be initialized with holes", function () { + var originalLatLngs = [ + [[0, 10], [10, 10], [10, 0]], // external ring + [[2, 3], [2, 4], [3, 4]] // hole + ]; + + var polygon = new L.Polygon(originalLatLngs); + + expect(polygon._latlngs).to.eql([ + [L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])], + [L.latLng([2, 3]), L.latLng([2, 4]), L.latLng([3, 4])] + ]); + expect(polygon.getLatLngs()).to.eql(polygon._latlngs); + }); + + it("can be initialized with multi including hole", function () { + var latLngs = [ + [[[10, 20], [30, 40], [50, 60]]], + [[[0, 10], [10, 10], [10, 0]], [[2, 3], [2, 4], [3, 4]]] + ]; + + var polygon = new L.Polygon(latLngs); + + expect(polygon._latlngs).to.eql([ + [[L.latLng([10, 20]), L.latLng([30, 40]), L.latLng([50, 60])]], + [[L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])], [L.latLng([2, 3]), L.latLng([2, 4]), L.latLng([3, 4])]] + ]); + expect(polygon.getLatLngs()).to.eql(polygon._latlngs); + }); + + it("can be added to the map when empty", function () { + var polygon = new L.Polygon([]).addTo(map); + expect(map.hasLayer(polygon)).to.be(true); + }); + + }); + + describe("#isEmpty", function () { + + it('should return true for a polygon with no latlngs', function () { + var layer = new L.Polygon([]); + expect(layer.isEmpty()).to.be(true); + }); + + it('should return false for simple polygon', function () { + var latLngs = [[1, 2], [3, 4], [5, 6]]; + var layer = new L.Polygon(latLngs); + expect(layer.isEmpty()).to.be(false); + }); + + it('should return false for a multi-polygon', function () { + var latLngs = [ + [[[10, 20], [30, 40], [50, 60]]], + [[[0, 10], [10, 10], [10, 0]], [[2, 3], [2, 4], [3, 4]]] + ]; + var layer = new L.Polygon(latLngs); + expect(layer.isEmpty()).to.be(false); + }); + + }); + + describe("#setLatLngs", function () { + it("doesn't overwrite the given latlng array", function () { + var originalLatLngs = [ + [1, 2], + [3, 4] + ]; + var sourceLatLngs = originalLatLngs.slice(); + + var polygon = new L.Polygon(sourceLatLngs); + + polygon.setLatLngs(sourceLatLngs); + + expect(sourceLatLngs).to.eql(originalLatLngs); + }); + + it("can be set external ring and holes", function () { + var latLngs = [ + [[0, 10], [10, 10], [10, 0]], // external ring + [[2, 3], [2, 4], [3, 4]] // hole + ]; + + var polygon = new L.Polygon([]); + polygon.setLatLngs(latLngs); + + expect(polygon.getLatLngs()).to.eql([ + [L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])], + [L.latLng([2, 3]), L.latLng([2, 4]), L.latLng([3, 4])] + ]); + }); + + it("can be set multi including hole", function () { + var latLngs = [ + [[[10, 20], [30, 40], [50, 60]]], + [[[0, 10], [10, 10], [10, 0]], [[2, 3], [2, 4], [3, 4]]] + ]; + + var polygon = new L.Polygon([]); + polygon.setLatLngs(latLngs); + + expect(polygon.getLatLngs()).to.eql([ + [[L.latLng([10, 20]), L.latLng([30, 40]), L.latLng([50, 60])]], + [[L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])], [L.latLng([2, 3]), L.latLng([2, 4]), L.latLng([3, 4])]] + ]); + }); + + }); + + describe('#getCenter', function () { + + it('should compute center of a big simple polygon around equator', function () { + var latlngs = [ + [[0, 0], [10, 0], [10, 10], [0, 10]] + ]; + var layer = new L.Polygon(latlngs).addTo(map); + expect(layer.getCenter()).to.be.nearLatLng(L.latLng([5, 5]), 1e-1); + }); + + it('should compute center of a small simple polygon', function () { + var latlngs = [ + [[0, 0], [0.010, 0], [0.010, 0.010], [0, 0.010]] + ]; + var layer = new L.Polygon(latlngs).addTo(map); + map.setZoom(0); // Make the polygon disappear in screen. + expect(layer.getCenter()).to.be.nearLatLng(L.latLng([0, 0])); + }); + + it('throws error if not yet added to map', function () { + expect(function () { + var latlngs = [ + [[0, 0], [10, 0], [10, 10], [0, 10]] + ]; + var layer = new L.Polygon(latlngs); + var center = layer.getCenter(); + }).to.throwException('Must add layer to map before using getCenter()'); + }); + + }); + + describe("#_defaultShape", function () { + + it("should return latlngs on a simple polygon", function () { + var latlngs = [ + L.latLng([1, 2]), + L.latLng([3, 4]) + ]; + + var polygon = new L.Polygon(latlngs); + + expect(polygon._defaultShape()).to.eql(latlngs); + }); + + it("should return first latlngs on a polygon with hole", function () { + var latlngs = [ + [L.latLng([0, 12]), L.latLng([13, 14]), L.latLng([15, 16])], + [L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])] + ]; + + var polygon = new L.Polygon(latlngs); + + expect(polygon._defaultShape()).to.eql(latlngs[0]); + }); + + it("should return first latlngs on a multipolygon", function () { + var latlngs = [ + [[L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]], + [[L.latLng([11, 12]), L.latLng([13, 14]), L.latLng([15, 16])]] + ]; + + var polygon = new L.Polygon(latlngs); + + expect(polygon._defaultShape()).to.eql(latlngs[0][0]); + }); + + it("should return first latlngs on a multipolygon with hole", function () { + var latlngs = [ + [[L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])], + [L.latLng([2, 3]), L.latLng([2, 4]), L.latLng([3, 4])]], + [[L.latLng([10, 20]), L.latLng([30, 40]), L.latLng([50, 60])]] + ]; + + var polygon = new L.Polygon(latlngs); + + expect(polygon._defaultShape()).to.eql(latlngs[0][0]); + }); + + }); + + describe("#addLatLng", function () { + it("should add latlng to latlngs", function () { + var latLngs = [ + [1, 2], + [3, 4] + ]; + + var polygon = new L.Polygon(latLngs); + + polygon.addLatLng([5, 6]); + + expect(polygon._latlngs).to.eql([[L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]]); + }); + + it("should add latlng to first latlngs on a polygon with hole", function () { + var latLngs = [ + [[0, 12], [13, 14], [15, 16]], + [[1, 2], [3, 4], [5, 6]] + ]; + + var polygon = new L.Polygon(latLngs); + + polygon.addLatLng([17, 0]); + + expect(polygon._latlngs[0]).to.eql([L.latLng([0, 12]), L.latLng([13, 14]), L.latLng([15, 16]), L.latLng([17, 0])]); + expect(polygon._latlngs[1]).to.eql([L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]); + }); + + it("should add latlng by reference on a polygon with hole", function () { + var latLngs = [ + [[0, 12], [13, 14], [15, 16]], + [[1, 2], [3, 4], [5, 6]] + ]; + + var polygon = new L.Polygon(latLngs); + + polygon.addLatLng([7, 8], polygon._latlngs[1]); + + expect(polygon._latlngs[0]).to.eql([L.latLng([0, 12]), L.latLng([13, 14]), L.latLng([15, 16])]); + expect(polygon._latlngs[1]).to.eql([L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6]), L.latLng([7, 8])]); + }); + + it("should add latlng to first latlngs on a multi", function () { + var latLngs = [ + [[[1, 2], [3, 4]]], + [[[11, 12], [13, 14], [15, 16]]] + ]; + + var polygon = new L.Polygon(latLngs); + + polygon.addLatLng([5, 6]); + + expect(polygon._latlngs[0]).to.eql([[L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]]); + expect(polygon._latlngs[1]).to.eql([[L.latLng([11, 12]), L.latLng([13, 14]), L.latLng([15, 16])]]); + }); + + it("should add latlng to latlngs by reference on a multi", function () { + var latLngs = [ + [[[11, 12], [13, 14], [15, 16]]], + [[[1, 2], [3, 4]]] + ]; + + var polygon = new L.Polygon(latLngs); + + polygon.addLatLng([5, 6], polygon._latlngs[1][0]); + + expect(polygon._latlngs[1]).to.eql([[L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]]); + expect(polygon._latlngs[0]).to.eql([[L.latLng([11, 12]), L.latLng([13, 14]), L.latLng([15, 16])]]); + }); + + it("should add latlng on first latlngs by default on a multipolygon with hole", function () { + var latLngs = [ + [[[0, 10], [10, 10], [10, 0]], [[2, 3], [2, 4], [3, 4]]], + [[[10, 20], [30, 40], [50, 60]]] + ]; + + var polygon = new L.Polygon(latLngs); + + polygon.addLatLng([-10, -10]); + + expect(polygon._latlngs[0][0]).to.eql([L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0]), L.latLng([-10, -10])]); + expect(polygon._latlngs[0][1]).to.eql([L.latLng([2, 3]), L.latLng([2, 4]), L.latLng([3, 4])]); + expect(polygon._latlngs[1][0]).to.eql([L.latLng([10, 20]), L.latLng([30, 40]), L.latLng([50, 60])]); + }); + + it("should add latlng by reference on a multipolygon with hole", function () { + var latLngs = [ + [[[10, 20], [30, 40], [50, 60]]], + [[[0, 10], [10, 10], [10, 0]], [[2, 3], [2, 4], [3, 4]]] + ]; + + var polygon = new L.Polygon(latLngs); + + polygon.addLatLng([2, 2], polygon._latlngs[1][1]); + + expect(polygon._latlngs[0][0]).to.eql([L.latLng([10, 20]), L.latLng([30, 40]), L.latLng([50, 60])]); + expect(polygon._latlngs[1][0]).to.eql([L.latLng([0, 10]), L.latLng([10, 10]), L.latLng([10, 0])]); + expect(polygon._latlngs[1][1]).to.eql([L.latLng([2, 3]), L.latLng([2, 4]), L.latLng([3, 4]), L.latLng([2, 2])]); + }); + + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolylineGeometrySpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolylineGeometrySpec.js new file mode 100644 index 000000000..02fa07677 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolylineGeometrySpec.js @@ -0,0 +1,69 @@ +describe('PolylineGeometry', function () { + + var c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + var map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); + + describe("#distanceTo", function () { + it("calculates distances to points", function () { + var p1 = map.latLngToLayerPoint(new L.LatLng(55.8, 37.6)); + var p2 = map.latLngToLayerPoint(new L.LatLng(57.123076977278, 44.861962891635)); + var latlngs = [[56.485503424111, 35.545556640339], [55.972522915346, 36.116845702918], [55.502459116923, 34.930322265253], [55.31534617509, 38.973291015816]] + .map(function (ll) { + return new L.LatLng(ll[0], ll[1]); + }); + var polyline = new L.Polyline([], { + 'noClip': true + }); + map.addLayer(polyline); + + expect(polyline.closestLayerPoint(p1)).to.be(null); + + polyline.setLatLngs(latlngs); + var point = polyline.closestLayerPoint(p1); + expect(point).not.to.be(null); + expect(point.distance).to.not.be(Infinity); + expect(point.distance).to.not.be(NaN); + + var point2 = polyline.closestLayerPoint(p2); + + expect(point.distance).to.be.lessThan(point2.distance); + }); + }); +}); + +describe('LineUtil', function () { + describe('#isFlat', function () { + var layer = L.polyline([]); + + it('should return true for an array of LatLngs', function () { + expect(L.LineUtil.isFlat([L.latLng([0, 0])])).to.be(true); + }); + + it('should return true for an array of LatLngs arrays', function () { + expect(L.LineUtil.isFlat([[0, 0]])).to.be(true); + }); + + it('should return true for an empty array', function () { + expect(L.LineUtil.isFlat([])).to.be(true); + }); + + it('should return false for a nested array of LatLngs', function () { + expect(L.LineUtil.isFlat([[L.latLng([0, 0])]])).to.be(false); + }); + + it('should return false for a nested empty array', function () { + expect(L.LineUtil.isFlat([[]])).to.be(false); + }); + + it('should be aliased as _flat for retrocompat', function () { + expect(L.LineUtil._flat([L.latLng([0, 0])])).to.be(true); + }); + + it('should be aliased as L.Polyline._flat for retrocompat', function () { + expect(L.Polyline._flat([L.latLng([0, 0])])).to.be(true); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolylineSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolylineSpec.js new file mode 100644 index 000000000..a4b7ba382 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/layer/vector/PolylineSpec.js @@ -0,0 +1,224 @@ +describe('Polyline', function () { + + var c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + var map = new L.Map(c); + map.setView(new L.LatLng(55.8, 37.6), 6); + + describe("#initialize", function () { + it("doesn't overwrite the given latlng array", function () { + var originalLatLngs = [ + [1, 2], + [3, 4] + ]; + var sourceLatLngs = originalLatLngs.slice(); + + var polyline = new L.Polyline(sourceLatLngs); + + expect(sourceLatLngs).to.eql(originalLatLngs); + expect(polyline._latlngs).to.not.eql(sourceLatLngs); + expect(polyline.getLatLngs()).to.eql(polyline._latlngs); + }); + + it("should accept a multi", function () { + var latLngs = [ + [[1, 2], [3, 4], [5, 6]], + [[11, 12], [13, 14], [15, 16]] + ]; + + var polyline = new L.Polyline(latLngs); + + expect(polyline._latlngs[0]).to.eql([L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]); + expect(polyline._latlngs[1]).to.eql([L.latLng([11, 12]), L.latLng([13, 14]), L.latLng([15, 16])]); + expect(polyline.getLatLngs()).to.eql(polyline._latlngs); + }); + + it("should accept an empty array", function () { + + var polyline = new L.Polyline([]); + + expect(polyline._latlngs).to.eql([]); + expect(polyline.getLatLngs()).to.eql(polyline._latlngs); + }); + + it("can be added to the map when empty", function () { + var polyline = new L.Polyline([]).addTo(map); + expect(map.hasLayer(polyline)).to.be(true); + }); + + }); + + describe("#isEmpty", function () { + + it('should return true for a polyline with no latlngs', function () { + var polyline = new L.Polyline([]); + expect(polyline.isEmpty()).to.be(true); + }); + + it('should return false for simple polyline', function () { + var latLngs = [[1, 2], [3, 4]]; + var polyline = new L.Polyline(latLngs); + expect(polyline.isEmpty()).to.be(false); + }); + + it('should return false for multi-polyline', function () { + var latLngs = [ + [[1, 2], [3, 4]], + [[11, 12], [13, 14]] + ]; + var polyline = new L.Polyline(latLngs); + expect(polyline.isEmpty()).to.be(false); + }); + + }); + + describe("#setLatLngs", function () { + it("doesn't overwrite the given latlng array", function () { + var originalLatLngs = [ + [1, 2], + [3, 4] + ]; + var sourceLatLngs = originalLatLngs.slice(); + + var polyline = new L.Polyline(sourceLatLngs); + + polyline.setLatLngs(sourceLatLngs); + + expect(sourceLatLngs).to.eql(originalLatLngs); + }); + + it("can be set a multi", function () { + var latLngs = [ + [[1, 2], [3, 4], [5, 6]], + [[11, 12], [13, 14], [15, 16]] + ]; + + var polyline = new L.Polyline([]); + polyline.setLatLngs(latLngs); + + expect(polyline._latlngs[0]).to.eql([L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]); + expect(polyline._latlngs[1]).to.eql([L.latLng([11, 12]), L.latLng([13, 14]), L.latLng([15, 16])]); + }); + }); + + describe('#getCenter', function () { + + it('should compute center of a big flat line on equator', function () { + var polyline = new L.Polyline([[0, 0], [0, 90]]).addTo(map); + expect(polyline.getCenter()).to.eql(L.latLng([0, 45])); + }); + + it('should compute center of a big flat line close to the pole', function () { + var polyline = new L.Polyline([[80, 0], [80, 90]]).addTo(map); + expect(polyline.getCenter()).to.be.nearLatLng(L.latLng([80, 45]), 1e-2); + }); + + it('should compute center of a big diagonal line', function () { + var polyline = new L.Polyline([[0, 0], [80, 80]]).addTo(map); + expect(polyline.getCenter()).to.be.nearLatLng(L.latLng([57, 40]), 1); + }); + + it('should compute center of a diagonal line close to the pole', function () { + var polyline = new L.Polyline([[70, 70], [84, 84]]).addTo(map); + expect(polyline.getCenter()).to.be.nearLatLng(L.latLng([79, 77]), 1); + }); + + it('should compute center of a big multiline', function () { + var polyline = new L.Polyline([[10, -80], [0, 0], [0, 10], [10, 90]]).addTo(map); + expect(polyline.getCenter()).to.be.nearLatLng(L.latLng([0, 5]), 1); + }); + + it('should compute center of a small flat line', function () { + var polyline = new L.Polyline([[0, 0], [0, 0.090]]).addTo(map); + map.setZoom(0); // Make the line disappear in screen; + expect(polyline.getCenter()).to.be.nearLatLng(L.latLng([0, 0]), 1e-2); + }); + + it('throws error if not yet added to map', function () { + expect(function () { + var polyline = new L.Polyline([[0, 0], [0, 0.090]]); + var center = polyline.getCenter(); + }).to.throwException('Must add layer to map before using getCenter()'); + }); + + }); + + + describe("#_defaultShape", function () { + + it("should return latlngs when flat", function () { + var latLngs = [L.latLng([1, 2]), L.latLng([3, 4])]; + + var polyline = new L.Polyline(latLngs); + + expect(polyline._defaultShape()).to.eql(latLngs); + }); + + it("should return first latlngs on a multi", function () { + var latLngs = [ + [L.latLng([1, 2]), L.latLng([3, 4])], + [L.latLng([11, 12]), L.latLng([13, 14])] + ]; + + var polyline = new L.Polyline(latLngs); + + expect(polyline._defaultShape()).to.eql(latLngs[0]); + }); + + }); + + describe("#addLatLng", function () { + + it("should add latlng to latlngs", function () { + var latLngs = [ + [1, 2], + [3, 4] + ]; + + var polyline = new L.Polyline(latLngs); + + polyline.addLatLng([5, 6]); + + expect(polyline._latlngs).to.eql([L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]); + }); + + it("should add latlng to first latlngs on a multi", function () { + var latLngs = [ + [[1, 2], [3, 4]], + [[11, 12], [13, 14]] + ]; + + var polyline = new L.Polyline(latLngs); + + polyline.addLatLng([5, 6]); + + expect(polyline._latlngs[0]).to.eql([L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]); + expect(polyline._latlngs[1]).to.eql([L.latLng([11, 12]), L.latLng([13, 14])]); + }); + + it("should add latlng to latlngs by reference", function () { + var latLngs = [ + [[11, 12], [13, 14]], + [[1, 2], [3, 4]] + ]; + + var polyline = new L.Polyline(latLngs); + + polyline.addLatLng([5, 6], polyline._latlngs[1]); + + expect(polyline._latlngs[1]).to.eql([L.latLng([1, 2]), L.latLng([3, 4]), L.latLng([5, 6])]); + expect(polyline._latlngs[0]).to.eql([L.latLng([11, 12]), L.latLng([13, 14])]); + }); + + it("should add latlng on empty polyline", function () { + var polyline = new L.Polyline([]); + + polyline.addLatLng([1, 2]); + + expect(polyline._latlngs).to.eql([L.latLng([1, 2])]); + }); + + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/MapSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/MapSpec.js new file mode 100644 index 000000000..a7b9f9b75 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/MapSpec.js @@ -0,0 +1,1314 @@ +describe("Map", function () { + var map, + spy; + beforeEach(function () { + map = L.map(document.createElement('div')); + }); + + describe("#remove", function () { + it("fires an unload event if loaded", function () { + var container = document.createElement('div'), + map = new L.Map(container).setView([0, 0], 0), + spy = sinon.spy(); + map.on('unload', spy); + map.remove(); + expect(spy.called).to.be.ok(); + }); + + it("fires no unload event if not loaded", function () { + var container = document.createElement('div'), + map = new L.Map(container), + spy = sinon.spy(); + map.on('unload', spy); + map.remove(); + expect(spy.called).not.to.be.ok(); + }); + + describe("corner case checking", function () { + it("throws an exception upon reinitialization", function () { + var container = document.createElement('div'), + map = new L.Map(container); + expect(function () { + L.map(container); + }).to.throwException(function (e) { + expect(e.message).to.eql("Map container is already initialized."); + }); + map.remove(); + }); + + it("throws an exception if a container is not found", function () { + expect(function () { + L.map('nonexistentdivelement'); + }).to.throwException(function (e) { + expect(e.message).to.eql("Map container not found."); + }); + map.remove(); + }); + }); + + it("undefines container._leaflet", function () { + var container = document.createElement('div'), + map = new L.Map(container); + map.remove(); + expect(container._leaflet).to.be(undefined); + }); + + it("unbinds events", function () { + var container = document.createElement('div'), + map = new L.Map(container).setView([0, 0], 1), + spy = sinon.spy(); + + map.on('click dblclick mousedown mouseup mousemove', spy); + map.remove(); + + happen.click(container); + happen.dblclick(container); + happen.mousedown(container); + happen.mouseup(container); + happen.mousemove(container); + + expect(spy.called).to.not.be.ok(); + }); + + it("throws error if container is reused by other instance", function () { + var container = document.createElement('div'), + map = L.map(container), + map2; + + map.remove(); + map2 = L.map(container); + + expect(function () { + map.remove(); + }).to.throwException(); + }); + }); + + describe('#getCenter', function () { + it('throws if not set before', function () { + expect(function () { + map.getCenter(); + }).to.throwError(); + }); + + it('returns a precise center when zoomed in after being set (#426)', function () { + var center = L.latLng(10, 10); + map.setView(center, 1); + map.setZoom(19); + expect(map.getCenter()).to.eql(center); + }); + + it('returns correct center after invalidateSize (#1919)', function () { + map.setView(L.latLng(10, 10), 1); + map.invalidateSize(); + expect(map.getCenter()).not.to.eql(L.latLng(10, 10)); + }); + }); + + describe("#whenReady", function () { + describe("when the map has not yet been loaded", function () { + it("calls the callback when the map is loaded", function () { + var spy = sinon.spy(); + map.whenReady(spy); + expect(spy.called).to.not.be.ok(); + + map.setView([0, 0], 1); + expect(spy.called).to.be.ok(); + }); + }); + + describe("when the map has already been loaded", function () { + it("calls the callback immediately", function () { + var spy = sinon.spy(); + map.setView([0, 0], 1); + map.whenReady(spy); + + expect(spy.called).to.be.ok(); + }); + }); + }); + + describe("#setView", function () { + it("sets the view of the map", function () { + expect(map.setView([51.505, -0.09], 13)).to.be(map); + expect(map.getZoom()).to.be(13); + expect(map.getCenter().distanceTo([51.505, -0.09])).to.be.lessThan(5); + }); + + it("can be passed without a zoom specified", function () { + map.setZoom(13); + expect(map.setView([51.605, -0.11])).to.be(map); + expect(map.getZoom()).to.be(13); + expect(map.getCenter().distanceTo([51.605, -0.11])).to.be.lessThan(5); + }); + + it("limits initial zoom when no zoom specified", function () { + map.options.maxZoom = 20; + map.setZoom(100); + expect(map.setView([51.605, -0.11])).to.be(map); + expect(map.getZoom()).to.be(20); + expect(map.getCenter().distanceTo([51.605, -0.11])).to.be.lessThan(5); + }); + + it("defaults to zoom passed as map option", function () { + map = L.map(document.createElement('div'), {zoom: 13}); + expect(map.setView([51.605, -0.11])).to.be(map); + expect(map.getZoom()).to.be(13); + }); + + it("passes duration option to panBy", function () { + map = L.map(document.createElement('div'), {zoom: 13, center: [0, 0]}); + map.panBy = sinon.spy(); + map.setView([51.605, -0.11], 13, {animate: true, duration: 13}); + expect(map.panBy.callCount).to.eql(1); + expect(map.panBy.args[0][1].duration).to.eql(13); + }); + }); + + describe("#getBounds", function () { + it("is safe to call from within a moveend callback during initial load (#1027)", function () { + map.on("moveend", function () { + map.getBounds(); + }); + + map.setView([51.505, -0.09], 13); + }); + }); + + describe("#getBoundsZoom", function () { + var halfLength = 0.00025; + var bounds = [[-halfLength, -halfLength], [halfLength, halfLength]]; + var wideBounds = [[-halfLength, -halfLength * 10], [halfLength, halfLength * 10]]; + var padding = [100, 100]; + var height = '400px'; + + it("returns high levels of zoom with small areas and big padding", function () { + var container = map.getContainer(); + container.style.height = height; + document.body.appendChild(container); + expect(map.getBoundsZoom(bounds, false, padding)).to.be.equal(19); + }); + + it.skipInPhantom("returns multiples of zoomSnap when zoomSnap > 0 on any3d browsers", function () { + var container = map.getContainer(); + container.style.height = height; + document.body.appendChild(container); + // L.Browser.any3d = true; // L.Browser is frozen since ES6ication + map.options.zoomSnap = 0.5; + expect(map.getBoundsZoom(bounds, false, padding)).to.be.equal(19.5); + map.options.zoomSnap = 0.2; + expect(map.getBoundsZoom(bounds, false, padding)).to.be.equal(19.6); + map.options.zoomSnap = 0; + expect(map.getBoundsZoom(bounds, false, padding)).to.be.within(19.6864560, 19.6864561); + }); + + it("getBoundsZoom does not return Infinity when projected SE - NW has negative components", function () { + var container = map.getContainer(); + container.style.height = 369; + container.style.width = 1048; + document.body.appendChild(container); + var bounds = L.latLngBounds(L.latLng([62.18475569507688, 6.926335173954951]), L.latLng([62.140483526511694, 6.923933370740089])); + + // The following coordinates are bounds projected with proj4leaflet crs = EPSG:25833', '+proj=utm +zone=33 +ellps=GRS80 +units=m +no_defs + var projectedSE = L.point(7800503.059925064, 6440062.353052008); + var projectedNW = L.point(7801987.203481699, 6425186.447901004); + var crsMock = sinon.mock(map.options.crs); + crsMock.expects("project").withArgs(bounds.getNorthWest()).returns(projectedNW); + crsMock.expects("project").withArgs(bounds.getSouthEast()).returns(projectedSE); + + var padding = L.point(-50, -50); + map.setZoom(16); + expect(map.getBoundsZoom(bounds, false, padding)).to.eql(9); + }); + + it("respects the 'inside' parameter", function () { + var container = map.getContainer(); + container.style.height = height; + container.style.width = '1024px'; // Make sure the width is defined for browsers other than PhantomJS (in particular Firefox). + document.body.appendChild(container); + expect(map.getBoundsZoom(wideBounds, false, padding)).to.be.equal(17); + expect(map.getBoundsZoom(wideBounds, true, padding)).to.be.equal(20); + }); + }); + + describe('#setMaxBounds', function () { + var container; + + beforeEach(function () { + container = map.getContainer(); + document.body.appendChild(container); + }); + + afterEach(function () { + // document.body.removeChild(container); + }); + + it("aligns pixel-wise map view center with maxBounds center if it cannot move view bounds inside maxBounds (#1908)", function () { + // large view, cannot fit within maxBounds + container.style.width = container.style.height = "1000px"; + // maxBounds + var bounds = L.latLngBounds([51.5, -0.05], [51.55, 0.05]); + map.setMaxBounds(bounds, {animate: false}); + // set view outside + map.setView(L.latLng([53.0, 0.15]), 12, {animate: false}); + // get center of bounds in pixels + var boundsCenter = map.project(bounds.getCenter()).round(); + expect(map.project(map.getCenter()).round()).to.eql(boundsCenter); + }); + + it("moves map view within maxBounds by changing one coordinate", function () { + // small view, can fit within maxBounds + container.style.width = container.style.height = "200px"; + // maxBounds + var bounds = L.latLngBounds([51, -0.2], [52, 0.2]); + map.setMaxBounds(bounds, {animate: false}); + // set view outside maxBounds on one direction only + // leaves untouched the other coordinate (that is not already centered) + var initCenter = [53.0, 0.1]; + map.setView(L.latLng(initCenter), 16, {animate: false}); + // one pixel coordinate hasn't changed, the other has + var pixelCenter = map.project(map.getCenter()).round(); + var pixelInit = map.project(initCenter).round(); + expect(pixelCenter.x).to.eql(pixelInit.x); + expect(pixelCenter.y).not.to.eql(pixelInit.y); + // the view is inside the bounds + expect(bounds.contains(map.getBounds())).to.be(true); + }); + + it("remove listeners when called without arguments", function () { + L.tileLayer('http://tilecache.openstreetmap.fr/hot/{z}/{x}/{y}.png', {minZoom: 0, maxZoom: 20}).addTo(map); + container.style.width = container.style.height = "500px"; + var bounds = L.latLngBounds([51.5, -0.05], [51.55, 0.05]); + map.setMaxBounds(bounds, {animate: false}); + map.setMaxBounds(); + // set view outside + var center = L.latLng([0, 0]); + map.once('moveend', function () { + expect(center.equals(map.getCenter())).to.be(true); + }); + map.setView(center, 18, {animate: false}); + }); + + }); + + describe("#getMinZoom and #getMaxZoom", function () { + describe('#getMinZoom', function () { + it('returns 0 if not set by Map options or TileLayer options', function () { + var map = L.map(document.createElement('div')); + expect(map.getMinZoom()).to.be(0); + }); + }); + + it("minZoom and maxZoom options overrides any minZoom and maxZoom set on layers", function () { + + var map = L.map(document.createElement('div'), {minZoom: 2, maxZoom: 20}); + + L.tileLayer("{z}{x}{y}", {minZoom: 4, maxZoom: 10}).addTo(map); + L.tileLayer("{z}{x}{y}", {minZoom: 6, maxZoom: 17}).addTo(map); + L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 22}).addTo(map); + + expect(map.getMinZoom()).to.be(2); + expect(map.getMaxZoom()).to.be(20); + }); + + it("layer minZoom overrides map zoom if map has no minZoom set and layer minZoom is bigger than map zoom", function () { + var map = L.map(document.createElement("div"), {zoom: 10}); + L.tileLayer("{z}{x}{y}", {minZoom: 15}).addTo(map); + + expect(map.getMinZoom()).to.be(15); + }); + + it("layer maxZoom overrides map zoom if map has no maxZoom set and layer maxZoom is smaller than map zoom", function () { + var map = L.map(document.createElement("div"), {zoom: 20}); + L.tileLayer("{z}{x}{y}", {maxZoom: 15}).addTo(map); + + expect(map.getMaxZoom()).to.be(15); + }); + + it("map's zoom is adjusted to layer's minZoom even if initialized with smaller value", function () { + var map = L.map(document.createElement("div"), {zoom: 10}); + L.tileLayer("{z}{x}{y}", {minZoom: 15}).addTo(map); + + expect(map.getZoom()).to.be(15); + }); + + it("map's zoom is adjusted to layer's maxZoom even if initialized with larger value", function () { + var map = L.map(document.createElement("div"), {zoom: 20}); + L.tileLayer("{z}{x}{y}", {maxZoom: 15}).addTo(map); + + expect(map.getZoom()).to.be(15); + }); + }); + + describe("#hasLayer", function () { + it("returns false when passed undefined, null, or false", function () { + var map = L.map(document.createElement('div')); + expect(map.hasLayer(undefined)).to.equal(false); + expect(map.hasLayer(null)).to.equal(false); + expect(map.hasLayer(false)).to.equal(false); + }); + }); + + function layerSpy() { + var layer = new L.Layer(); + layer.onAdd = sinon.spy(); + layer.onRemove = sinon.spy(); + return layer; + } + + describe("#addLayer", function () { + + it("calls layer.onAdd immediately if the map is ready", function () { + var layer = layerSpy(); + map.setView([0, 0], 0); + map.addLayer(layer); + expect(layer.onAdd.called).to.be.ok(); + }); + + it("calls layer.onAdd when the map becomes ready", function () { + var layer = layerSpy(); + map.addLayer(layer); + expect(layer.onAdd.called).not.to.be.ok(); + map.setView([0, 0], 0); + expect(layer.onAdd.called).to.be.ok(); + }); + + it("does not call layer.onAdd if the layer is removed before the map becomes ready", function () { + var layer = layerSpy(); + map.addLayer(layer); + map.removeLayer(layer); + map.setView([0, 0], 0); + expect(layer.onAdd.called).not.to.be.ok(); + }); + + it("fires a layeradd event immediately if the map is ready", function () { + var layer = layerSpy(), + spy = sinon.spy(); + map.on('layeradd', spy); + map.setView([0, 0], 0); + map.addLayer(layer); + expect(spy.called).to.be.ok(); + }); + + it("fires a layeradd event when the map becomes ready", function () { + var layer = layerSpy(), + spy = sinon.spy(); + map.on('layeradd', spy); + map.addLayer(layer); + expect(spy.called).not.to.be.ok(); + map.setView([0, 0], 0); + expect(spy.called).to.be.ok(); + }); + + it("does not fire a layeradd event if the layer is removed before the map becomes ready", function () { + var layer = layerSpy(), + spy = sinon.spy(); + map.on('layeradd', spy); + map.addLayer(layer); + map.removeLayer(layer); + map.setView([0, 0], 0); + expect(spy.called).not.to.be.ok(); + }); + + it("adds the layer before firing layeradd", function (done) { + var layer = layerSpy(); + map.on('layeradd', function () { + expect(map.hasLayer(layer)).to.be.ok(); + done(); + }); + map.setView([0, 0], 0); + map.addLayer(layer); + }); + + it("throws if adding something which is not a layer", function () { + var control = L.control.layers(); + expect(function () { + map.addLayer(control); + }).to.throwError(); + }); + + describe("When the first layer is added to a map", function () { + it("fires a zoomlevelschange event", function () { + var spy = sinon.spy(); + map.on("zoomlevelschange", spy); + expect(spy.called).not.to.be.ok(); + L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map); + expect(spy.called).to.be.ok(); + }); + }); + + describe("when a new layer with greater zoomlevel coverage than the current layer is added to a map", function () { + it("fires a zoomlevelschange event", function () { + var spy = sinon.spy(); + L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map); + map.on("zoomlevelschange", spy); + expect(spy.called).not.to.be.ok(); + L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 15}).addTo(map); + expect(spy.called).to.be.ok(); + }); + }); + + describe("when a new layer with the same or lower zoomlevel coverage as the current layer is added to a map", function () { + it("fires no zoomlevelschange event", function () { + var spy = sinon.spy(); + L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map); + map.on("zoomlevelschange", spy); + expect(spy.called).not.to.be.ok(); + L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map); + expect(spy.called).not.to.be.ok(); + L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 5}).addTo(map); + expect(spy.called).not.to.be.ok(); + }); + }); + }); + + describe("#removeLayer", function () { + it("calls layer.onRemove if the map is ready", function () { + var layer = layerSpy(); + map.setView([0, 0], 0); + map.addLayer(layer); + map.removeLayer(layer); + expect(layer.onRemove.called).to.be.ok(); + }); + + it("does not call layer.onRemove if the layer was not added", function () { + var layer = layerSpy(); + map.setView([0, 0], 0); + map.removeLayer(layer); + expect(layer.onRemove.called).not.to.be.ok(); + }); + + it("does not call layer.onRemove if the map is not ready", function () { + var layer = layerSpy(); + map.addLayer(layer); + map.removeLayer(layer); + expect(layer.onRemove.called).not.to.be.ok(); + }); + + it("fires a layerremove event if the map is ready", function () { + var layer = layerSpy(), + spy = sinon.spy(); + map.on('layerremove', spy); + map.setView([0, 0], 0); + map.addLayer(layer); + map.removeLayer(layer); + expect(spy.called).to.be.ok(); + }); + + it("does not fire a layerremove if the layer was not added", function () { + var layer = layerSpy(), + spy = sinon.spy(); + map.on('layerremove', spy); + map.setView([0, 0], 0); + map.removeLayer(layer); + expect(spy.called).not.to.be.ok(); + }); + + it("does not fire a layerremove if the map is not ready", function () { + var layer = layerSpy(), + spy = sinon.spy(); + map.on('layerremove', spy); + map.addLayer(layer); + map.removeLayer(layer); + expect(spy.called).not.to.be.ok(); + }); + + it("removes the layer before firing layerremove", function (done) { + var layer = layerSpy(); + map.on('layerremove', function () { + expect(map.hasLayer(layer)).not.to.be.ok(); + done(); + }); + map.setView([0, 0], 0); + map.addLayer(layer); + map.removeLayer(layer); + }); + + it("supports adding and removing a tile layer without initializing the map", function () { + var layer = L.tileLayer("{z}{x}{y}"); + map.addLayer(layer); + map.removeLayer(layer); + }); + + it("supports adding and removing a tile layer without initializing the map", function () { + map.setView([0, 0], 18); + var layer = L.gridLayer(); + map.addLayer(layer); + map.removeLayer(layer); + }); + + describe("when the last tile layer on a map is removed", function () { + it("fires a zoomlevelschange event", function () { + map.whenReady(function () { + var spy = sinon.spy(); + var tl = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map); + + map.on("zoomlevelschange", spy); + expect(spy.called).not.to.be.ok(); + map.removeLayer(tl); + expect(spy.called).to.be.ok(); + }); + }); + }); + + describe("when a tile layer is removed from a map and it had greater zoom level coverage than the remainding layer", function () { + it("fires a zoomlevelschange event", function () { + map.whenReady(function () { + var spy = sinon.spy(), + tl = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map), + t2 = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 15}).addTo(map); + + map.on("zoomlevelschange", spy); + expect(spy.called).to.not.be.ok(); + map.removeLayer(t2); + expect(spy.called).to.be.ok(); + }); + }); + }); + + describe("when a tile layer is removed from a map it and it had lesser or the sa,e zoom level coverage as the remainding layer(s)", function () { + it("fires no zoomlevelschange event", function () { + map.whenReady(function () { + var tl = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map), + t2 = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 10}).addTo(map), + t3 = L.tileLayer("{z}{x}{y}", {minZoom: 0, maxZoom: 5}).addTo(map); + + map.on("zoomlevelschange", spy); + expect(spy).not.toHaveBeenCalled(); + map.removeLayer(t2); + expect(spy).not.toHaveBeenCalled(); + map.removeLayer(t3); + expect(spy).not.toHaveBeenCalled(); + }); + }); + }); + }); + + describe("#eachLayer", function () { + it("returns self", function () { + expect(map.eachLayer(function () {})).to.be(map); + }); + + it("calls the provided function for each layer", function () { + var t1 = L.tileLayer("{z}{x}{y}").addTo(map), + t2 = L.tileLayer("{z}{x}{y}").addTo(map), + spy = sinon.spy(); + + map.eachLayer(spy); + + expect(spy.callCount).to.eql(2); + expect(spy.firstCall.args).to.eql([t1]); + expect(spy.secondCall.args).to.eql([t2]); + }); + + it("calls the provided function with the provided context", function () { + var t1 = L.tileLayer("{z}{x}{y}").addTo(map), + spy = sinon.spy(); + + map.eachLayer(spy, map); + + expect(spy.thisValues[0]).to.eql(map); + }); + }); + + describe("#invalidateSize", function () { + var container, + origWidth = 100, + clock; + + beforeEach(function () { + container = map.getContainer(); + container.style.width = origWidth + "px"; + document.body.appendChild(container); + map.setView([0, 0], 0); + map.invalidateSize({pan: false}); + clock = sinon.useFakeTimers(); + }); + + afterEach(function () { + document.body.removeChild(container); + clock.restore(); + }); + + it("pans by the right amount when growing in 1px increments", function () { + container.style.width = (origWidth + 1) + "px"; + map.invalidateSize(); + expect(map._getMapPanePos().x).to.be(1); + + container.style.width = (origWidth + 2) + "px"; + map.invalidateSize(); + expect(map._getMapPanePos().x).to.be(1); + + container.style.width = (origWidth + 3) + "px"; + map.invalidateSize(); + expect(map._getMapPanePos().x).to.be(2); + }); + + it("pans by the right amount when shrinking in 1px increments", function () { + container.style.width = (origWidth - 1) + "px"; + map.invalidateSize(); + expect(map._getMapPanePos().x).to.be(0); + + container.style.width = (origWidth - 2) + "px"; + map.invalidateSize(); + expect(map._getMapPanePos().x).to.be(-1); + + container.style.width = (origWidth - 3) + "px"; + map.invalidateSize(); + expect(map._getMapPanePos().x).to.be(-1); + }); + + it("pans back to the original position after growing by an odd size and back", function () { + container.style.width = (origWidth + 5) + "px"; + map.invalidateSize(); + + container.style.width = origWidth + "px"; + map.invalidateSize(); + + expect(map._getMapPanePos().x).to.be(0); + }); + + it("emits no move event if the size has not changed", function () { + var spy = sinon.spy(); + map.on("move", spy); + + map.invalidateSize(); + + expect(spy.called).not.to.be.ok(); + }); + + it("emits a move event if the size has changed", function () { + var spy = sinon.spy(); + map.on("move", spy); + + container.style.width = (origWidth + 5) + "px"; + map.invalidateSize(); + + expect(spy.called).to.be.ok(); + }); + + it("emits a moveend event if the size has changed", function () { + var spy = sinon.spy(); + map.on("moveend", spy); + + container.style.width = (origWidth + 5) + "px"; + map.invalidateSize(); + + expect(spy.called).to.be.ok(); + }); + + it("debounces the moveend event if the debounceMoveend option is given", function () { + var spy = sinon.spy(); + map.on("moveend", spy); + + container.style.width = (origWidth + 5) + "px"; + map.invalidateSize({debounceMoveend: true}); + + expect(spy.called).not.to.be.ok(); + + clock.tick(200); + + expect(spy.called).to.be.ok(); + }); + + it("correctly adjusts for new container size when view is set during map initialization (#6165)", function () { + // Use a newly initialized map + map.remove(); + + var center = [0, 0]; + + // The edge case is only if view is set directly during map initialization + map = L.map(container, { + center: center, + zoom: 0 + }); + + // Change the container size + container.style.width = '600px'; + + // The map should not be aware yet of container size change, + // otherwise the next invalidateSize will not be able to + // compute the size difference + expect(map.getSize().x).to.equal(100); + expect(map.latLngToContainerPoint(center).x).to.equal(50); + + // Now notifying the map that the container size has changed, + // it should return new values and correctly position coordinates + map.invalidateSize(); + + expect(map.getSize().x).to.equal(600); + expect(map.latLngToContainerPoint(center).x).to.equal(300); + }); + }); + + describe('#flyTo', function () { + var div; + + beforeEach(function () { + div = document.createElement('div'); + div.style.width = '800px'; + div.style.height = '600px'; + div.style.visibility = 'hidden'; + + document.body.appendChild(div); + + map = L.map(div); + }); + + afterEach(function () { + document.body.removeChild(div); + }); + + it('move to requested center and zoom, and call zoomend once', function (done) { + this.timeout(10000); // This test takes longer than usual due to frames + + var spy = sinon.spy(), + newCenter = new L.LatLng(10, 11), + newZoom = 12; + var callback = function () { + expect(map.getCenter()).to.eql(newCenter); + expect(map.getZoom()).to.eql(newZoom); + spy(); + expect(spy.calledOnce).to.be.ok(); + done(); + }; + map.setView([0, 0], 0); + map.on('zoomend', callback).flyTo(newCenter, newZoom); + }); + + it('flyTo start latlng == end latlng', function (done) { + this.timeout(10000); // This test takes longer than usual due to frames + + var dc = new L.LatLng(38.91, -77.04); + map.setView(dc, 14); + + map.on('zoomend', function () { + expect(map.getCenter()).to.eql(dc); + expect(map.getZoom()).to.eql(4); + done(); + }); + + map.flyTo(dc, 4); + }); + }); + + describe('#zoomIn and #zoomOut', function () { + var center = L.latLng(22, 33); + beforeEach(function () { + map.setView(center, 10); + }); + + it('zoomIn zooms by 1 zoom level by default', function (done) { + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(11); + expect(map.getCenter()).to.eql(center); + done(); + }); + map.zoomIn(null, {animate: false}); + }); + + it('zoomOut zooms by 1 zoom level by default', function (done) { + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(9); + expect(map.getCenter()).to.eql(center); + done(); + }); + map.zoomOut(null, {animate: false}); + }); + + it.skipInNonPhantom('zoomIn ignores the zoomDelta option on non-any3d browsers', function (done) { + L.Browser.any3d = false; + map.options.zoomSnap = 0.25; + map.options.zoomDelta = 0.25; + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(11); + expect(map.getCenter()).to.eql(center); + done(); + }); + map.zoomIn(null, {animate: false}); + }); + + it.skipInPhantom('zoomIn respects the zoomDelta option on any3d browsers', function (done) { + L.Browser.any3d = true; + map.options.zoomSnap = 0.25; + map.options.zoomDelta = 0.25; + map.setView(center, 10); + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(10.25); + expect(map.getCenter()).to.eql(center); + done(); + }); + map.zoomIn(null, {animate: false}); + }); + + it.skipInPhantom('zoomOut respects the zoomDelta option on any3d browsers', function (done) { + L.Browser.any3d = true; + map.options.zoomSnap = 0.25; + map.options.zoomDelta = 0.25; + map.setView(center, 10); + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(9.75); + expect(map.getCenter()).to.eql(center); + done(); + }); + map.zoomOut(null, {animate: false}); + }); + + it.skipInPhantom('zoomIn snaps to zoomSnap on any3d browsers', function (done) { + map.options.zoomSnap = 0.25; + map.setView(center, 10); + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(10.25); + expect(map.getCenter()).to.eql(center); + done(); + }); + L.Browser.any3d = true; + map.zoomIn(0.22, {animate: false}); + }); + + it.skipInPhantom('zoomOut snaps to zoomSnap on any3d browsers', function (done) { + map.options.zoomSnap = 0.25; + map.setView(center, 10); + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(9.75); + expect(map.getCenter()).to.eql(center); + done(); + }); + L.Browser.any3d = true; + map.zoomOut(0.22, {animate: false}); + }); + }); + + describe('#_getBoundsCenterZoom', function () { + var center = L.latLng(50.5, 30.51); + + it('Returns valid center on empty bounds in unitialized map', function () { + // Edge case from #5153 + var centerAndZoom = map._getBoundsCenterZoom([center, center]); + expect(centerAndZoom.center).to.eql(center); + expect(centerAndZoom.zoom).to.eql(Infinity); + }); + }); + + describe('#fitBounds', function () { + var center = L.latLng(50.5, 30.51), + bounds = L.latLngBounds(L.latLng(1, 102), L.latLng(11, 122)), + boundsCenter = bounds.getCenter(); + + beforeEach(function () { + // fitBounds needs a map container with non-null area + var container = map.getContainer(); + container.style.width = container.style.height = "100px"; + document.body.appendChild(container); + map.setView(center, 15); + }); + + afterEach(function () { + document.body.removeChild(map.getContainer()); + }); + + it('Snaps zoom level to integer by default', function (done) { + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(2); + expect(map.getCenter().equals(boundsCenter, 0.05)).to.eql(true); + done(); + }); + map.fitBounds(bounds, {animate: false}); + }); + + it.skipInPhantom('Snaps zoom to zoomSnap on any3d browsers', function (done) { + map.options.zoomSnap = 0.25; + L.Browser.any3d = true; + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(2.75); + expect(map.getCenter().equals(boundsCenter, 0.05)).to.eql(true); + done(); + }); + map.fitBounds(bounds, {animate: false}); + }); + + it.skipInNonPhantom('Ignores zoomSnap on non-any3d browsers', function (done) { + map.options.zoomSnap = 0.25; + L.Browser.any3d = false; + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(2); + expect(map.getCenter().equals(boundsCenter, 0.05)).to.eql(true); + done(); + }); + map.fitBounds(bounds, {animate: false}); + }); + + it('can be called with an array', function (done) { + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(2); + expect(map.getCenter().equals(boundsCenter, 0.05)).to.eql(true); + done(); + }); + var bounds = [[1, 102], [11, 122]]; + map.fitBounds(bounds, {animate: false}); + }); + + it('throws an error with invalid bounds', function () { + expect(function () { + map.fitBounds(NaN); + }).to.throwError(); + }); + + it('Fits to same scale and zoom', function (done) { + var bounds = map.getBounds(), + zoom = map.getZoom(); + map.once('moveend zoomend', function () { + var newBounds = map.getBounds(); + expect(newBounds.getSouthWest()).to.nearLatLng(bounds.getSouthWest()); + expect(newBounds.getNorthEast()).to.nearLatLng(bounds.getNorthEast()); + expect(map.getZoom()).to.eql(zoom); + done(); + }); + map.fitBounds(bounds, {animate: false}); + }); + + it('Fits to small bounds from small zoom', function (done) { + map.once('zoomend', function () { + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(11); + expect(map.getCenter().equals(boundsCenter, 0.05)).to.eql(true); + done(); + }); + map.fitBounds(bounds); + }); + + bounds = L.latLngBounds([57.73, 11.93], [57.75, 11.95]); + boundsCenter = bounds.getCenter(); + map.setZoom(0); + }); + + it('Fits to large bounds from large zoom', function (done) { + map.once('zoomend', function () { + map.once('zoomend', function () { + expect(map.getZoom()).to.eql(0); + expect(map.getCenter().equals(boundsCenter, 0.05)).to.eql(true); + done(); + }); + map.fitBounds(bounds); + }); + + bounds = L.latLngBounds([90, -180], [-90, 180]); + boundsCenter = bounds.getCenter(); + map.setZoom(22); + }); + }); + + + describe('#fitBounds after layers set', function () { + var center = L.latLng(22, 33), + bounds = L.latLngBounds(L.latLng(1, 102), L.latLng(11, 122)), + boundsCenter = bounds.getCenter(); + + beforeEach(function () { + // fitBounds needs a map container with non-null area + var container = map.getContainer(); + container.style.width = container.style.height = "100px"; + document.body.appendChild(container); + }); + + afterEach(function () { + document.body.removeChild(map.getContainer()); + }); + + it('Snaps to a number after adding tile layer', function (done) { + L.Browser.any3d = true; + map.addLayer(L.tileLayer('file:///dev/null')); + expect(map.getZoom()).to.be(undefined); + map.fitBounds(bounds); + expect(map.getZoom()).to.be(2); + done(); + }); + + it('Snaps to a number after adding marker', function (done) { + L.Browser.any3d = true; + map.addLayer(L.marker(center)); + expect(map.getZoom()).to.be(undefined); + map.fitBounds(bounds); + expect(map.getZoom()).to.be(2); + done(); + }); + + }); + + + describe("#panInside", function () { + var center, + tl, + tlPix; + + beforeEach(function () { + var container = map.getContainer(); + container.style.height = container.style.width = "500px"; + document.body.appendChild(container); + map.setView(L.latLng([53.0, 0.15]), 12, {animate: false}); + center = map.getCenter(); + tl = map.getBounds().getNorthWest(); + tlPix = map.getPixelBounds().min; + }); + + afterEach(function () { + document.body.removeChild(map.getContainer()); + }); + + it("does not pan the map when the target is within bounds", function () { + map.panInside(tl, {animate:false}); + expect(center).to.equal(map.getCenter()); + }); + + it("pans the map when padding is provided and the target is within the border area", function () { + var padding = [40, 20], + p = tlPix.add([30, 0]), // Top-left + distanceMoved; + map.panInside(map.unproject(p), {padding: padding, animate: false}); + distanceMoved = map.getPixelBounds().min.subtract(tlPix); + expect(distanceMoved.equals(L.point([-10, -20]))).to.eql(true); + + tlPix = map.getPixelBounds().min; + p = [map.getPixelBounds().max.x - 10, map.getPixelBounds().min.y]; // Top-right + map.panInside(map.unproject(p), {padding: padding, animate: false}); + distanceMoved = map.getPixelBounds().min.subtract(tlPix); + expect(distanceMoved.equals(L.point([30, -20]))).to.eql(true); + + tlPix = map.getPixelBounds().min; + p = [map.getPixelBounds().min.x + 35, map.getPixelBounds().max.y]; // Bottom-left + map.panInside(map.unproject(p), {padding: padding, animate: false}); + distanceMoved = map.getPixelBounds().min.subtract(tlPix); + expect(distanceMoved.equals(L.point([-5, 20]))).to.eql(true); + + tlPix = map.getPixelBounds().min; + p = [map.getPixelBounds().max.x - 15, map.getPixelBounds().max.y]; // Bottom-right + map.panInside(map.unproject(p), {padding: padding, animate: false}); + distanceMoved = map.getPixelBounds().min.subtract(tlPix); + expect(distanceMoved.equals(L.point([25, 20]))).to.eql(true); + }); + + it("supports different padding values for each border", function () { + var p = tlPix.add([40, 0]), // Top-Left + distanceMoved, + opts = {paddingTL: [60, 20], paddingBR: [10, 10]}; + map.panInside(map.unproject(p), opts); + expect(center).to.equal(map.getCenter()); + + var br = map.getPixelBounds().max; // Bottom-Right + map.panInside(map.unproject(L.point(br.x - 20, br.y)), opts); + expect(center).to.not.equal(map.getCenter); + }); + + it("pans on both X and Y axes when the target is outside of the view area and both the point's coords are outside the bounds", function () { + var p = map.unproject(tlPix.subtract([200, 200])); + map.panInside(p, {animate: false}); + expect(map.getBounds().contains(p)).to.be(true); + expect(map.getCenter().lng).to.not.eql(center.lng); + expect(map.getCenter().lat).to.not.eql(center.lat); + }); + + it("pans only on the Y axis when the target's X coord is within bounds but the Y is not", function () { + var p = L.latLng(tl.lat + 5, tl.lng); + map.panInside(p, {animate: false}); + expect(map.getBounds().contains(p)).to.be(true); + var dx = Math.abs(map.getCenter().lng - center.lng); + expect(dx).to.be.lessThan(1.0E-9); + expect(map.getCenter().lat).to.not.eql(center.lat); + }); + + it("pans only on the X axis when the target's Y coord is within bounds but the X is not", function () { + var p = L.latLng(tl.lat, tl.lng - 5); + map.panInside(p, 0, {animate: false}); + expect(map.getBounds().contains(p)).to.be(true); + expect(map.getCenter().lng).to.not.eql(center.lng); + var dy = map.getCenter().lat - center.lat; + expect(dy).to.be.lessThan(1.0E-9); + }); + }); + + + describe('#DOM events', function () { + + var c, map; + + beforeEach(function () { + c = document.createElement('div'); + c.style.width = '400px'; + c.style.height = '400px'; + map = new L.Map(c); + map.setView(new L.LatLng(0, 0), 0); + document.body.appendChild(c); + }); + + afterEach(function () { + document.body.removeChild(c); + }); + + it("DOM events propagate from polygon to map", function () { + var spy = sinon.spy(); + map.on("mousemove", spy); + var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]]).addTo(map); + happen.mousemove(layer._path); + expect(spy.calledOnce).to.be.ok(); + }); + + it("DOM events propagate from marker to map", function () { + var spy = sinon.spy(); + map.on("mousemove", spy); + var layer = new L.Marker([1, 2]).addTo(map); + happen.mousemove(layer._icon); + expect(spy.calledOnce).to.be.ok(); + }); + + it("DOM events fired on marker can be cancelled before being caught by the map", function () { + var mapSpy = sinon.spy(); + var layerSpy = sinon.spy(); + map.on("mousemove", mapSpy); + var layer = new L.Marker([1, 2]).addTo(map); + layer.on("mousemove", L.DomEvent.stopPropagation).on("mousemove", layerSpy); + happen.mousemove(layer._icon); + expect(layerSpy.calledOnce).to.be.ok(); + expect(mapSpy.called).not.to.be.ok(); + }); + + it("DOM events fired on polygon can be cancelled before being caught by the map", function () { + var mapSpy = sinon.spy(); + var layerSpy = sinon.spy(); + map.on("mousemove", mapSpy); + var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]]).addTo(map); + layer.on("mousemove", L.DomEvent.stopPropagation).on("mousemove", layerSpy); + happen.mousemove(layer._path); + expect(layerSpy.calledOnce).to.be.ok(); + expect(mapSpy.called).not.to.be.ok(); + }); + + it("mouseout is forwarded if fired on the original target", function () { + var mapSpy = sinon.spy(), + layerSpy = sinon.spy(), + otherSpy = sinon.spy(); + var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]]).addTo(map); + var other = new L.Polygon([[10, 20], [30, 40], [50, 60]]).addTo(map); + map.on("mouseout", mapSpy); + layer.on("mouseout", layerSpy); + other.on("mouseout", otherSpy); + happen.mouseout(layer._path, {relatedTarget: map._container}); + expect(mapSpy.called).not.to.be.ok(); + expect(otherSpy.called).not.to.be.ok(); + expect(layerSpy.calledOnce).to.be.ok(); + }); + + it("mouseout is forwarded when using a DivIcon", function () { + var icon = L.divIcon({ + html: "

this is text in a child element

", + iconSize: [100, 100] + }); + var mapSpy = sinon.spy(), + layerSpy = sinon.spy(), + layer = L.marker([1, 2], {icon: icon}).addTo(map); + map.on("mouseout", mapSpy); + layer.on("mouseout", layerSpy); + happen.mouseout(layer._icon, {relatedTarget: map._container}); + expect(mapSpy.called).not.to.be.ok(); + expect(layerSpy.calledOnce).to.be.ok(); + }); + + it("mouseout is not forwarded if relatedTarget is a target's child", function () { + var icon = L.divIcon({ + html: "

this is text in a child element

", + iconSize: [100, 100] + }); + var mapSpy = sinon.spy(), + layerSpy = sinon.spy(), + layer = L.marker([1, 2], {icon: icon}).addTo(map), + child = layer._icon.querySelector('p'); + map.on("mouseout", mapSpy); + layer.on("mouseout", layerSpy); + happen.mouseout(layer._icon, {relatedTarget: child}); + expect(mapSpy.called).not.to.be.ok(); + expect(layerSpy.calledOnce).not.to.be.ok(); + }); + + it("mouseout is not forwarded if fired on target's child", function () { + var icon = L.divIcon({ + html: "

this is text in a child element

", + iconSize: [100, 100] + }); + var mapSpy = sinon.spy(), + layerSpy = sinon.spy(), + layer = L.marker([1, 2], {icon: icon}).addTo(map), + child = layer._icon.querySelector('p'); + map.on("mouseout", mapSpy); + layer.on("mouseout", layerSpy); + happen.mouseout(child, {relatedTarget: layer._icon}); + expect(mapSpy.called).not.to.be.ok(); + expect(layerSpy.calledOnce).not.to.be.ok(); + }); + + it("mouseout is not forwarded to layers if fired on the map", function () { + var mapSpy = sinon.spy(), + layerSpy = sinon.spy(), + otherSpy = sinon.spy(); + var layer = new L.Polygon([[1, 2], [3, 4], [5, 6]]).addTo(map); + var other = new L.Polygon([[10, 20], [30, 40], [50, 60]]).addTo(map); + map.on("mouseout", mapSpy); + layer.on("mouseout", layerSpy); + other.on("mouseout", otherSpy); + happen.mouseout(map._container); + expect(otherSpy.called).not.to.be.ok(); + expect(layerSpy.called).not.to.be.ok(); + expect(mapSpy.calledOnce).to.be.ok(); + }); + + it("preclick is fired before click on marker and map", function () { + var called = 0; + var layer = new L.Marker([1, 2]).addTo(map); + layer.on("preclick", function (e) { + expect(called++).to.eql(0); + expect(e.latlng).to.ok(); + }); + layer.on("click", function (e) { + expect(called++).to.eql(2); + expect(e.latlng).to.ok(); + }); + map.on("preclick", function (e) { + expect(called++).to.eql(1); + expect(e.latlng).to.ok(); + }); + map.on("click", function (e) { + expect(called++).to.eql(3); + expect(e.latlng).to.ok(); + }); + happen.click(layer._icon); + }); + + }); + + describe('#getScaleZoom && #getZoomScale', function () { + it("converts zoom to scale and vice versa and returns the same values", function () { + var toZoom = 6.25; + var fromZoom = 8.5; + var scale = map.getZoomScale(toZoom, fromZoom); + expect(Math.round(map.getScaleZoom(scale, fromZoom) * 100) / 100).to.eql(toZoom); + }); + + it("converts scale to zoom and returns Infinity if map crs.zoom returns NaN", function () { + var stub = sinon.stub(map.options.crs, "zoom"); + stub.returns(NaN); + var scale = 0.25; + var fromZoom = 8.5; + expect(map.getScaleZoom(scale, fromZoom)).to.eql(Infinity); + map.options.crs.zoom.restore(); + }); + }); + + describe('#getZoom', function () { + it("returns undefined if map not initialized", function () { + expect(map.getZoom()).to.be(undefined); + }); + + it("returns undefined if map not initialized but layers added", function () { + map.addLayer(L.tileLayer('file:///dev/null')); + expect(map.getZoom()).to.be(undefined); + }); + }); +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.DragSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.DragSpec.js new file mode 100644 index 000000000..3a66daaa2 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.DragSpec.js @@ -0,0 +1,448 @@ +describe("Map.Drag", function () { + describe("#addHook", function () { + it("calls the map with dragging enabled", function () { + var container = document.createElement('div'); + var map = new L.Map(container, { + dragging: true + }); + + expect(map.dragging.enabled()).to.be(true); + map.setView([0, 0], 0); + expect(map.dragging.enabled()).to.be(true); + }); + it("calls the map with dragging and worldCopyJump enabled", function () { + var container = document.createElement('div'); + var map = new L.Map(container, { + dragging: true, + worldCopyJump: true + }); + + expect(map.dragging.enabled()).to.be(true); + map.setView([0, 0], 0); + expect(map.dragging.enabled()).to.be(true); + }); + it("calls the map with dragging disabled and worldCopyJump enabled; " + + "enables dragging after setting center and zoom", function () { + var container = document.createElement('div'); + var map = new L.Map(container, { + dragging: false, + worldCopyJump: true + }); + + expect(map.dragging.enabled()).to.be(false); + map.setView([0, 0], 0); + map.dragging.enable(); + expect(map.dragging.enabled()).to.be(true); + }); + }); + + + describe("mouse events", function () { + var container; + + beforeEach(function () { + container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + document.body.appendChild(container); + }); + + afterEach(function () { + document.body.removeChild(container); + }); + + it("change the center of the map", function (done) { + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + map.setView([0, 0], 1); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + expect(center.lat).to.be.within(21.9430, 21.9431); + expect(center.lng).to.be(-180); + expect(zoom).to.be(1); + + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + mouse.wait(100).moveTo(200, 200, 0) + .down().moveBy(5, 0, 20).moveBy(256, 32, 200).up(); + }); + + describe("in CSS scaled container", function () { + var scaleX = 2; + var scaleY = 1.5; + + beforeEach(function () { + container.style.webkitTransformOrigin = 'top left'; + container.style.webkitTransform = 'scale(' + scaleX + ', ' + scaleY + ')'; + }); + + afterEach(function () { + container.style.webkitTransformOrigin = ''; + container.style.webkitTransform = ''; + }); + + it("change the center of the map, compensating for CSS scale", function (done) { + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + map.setView([0, 0], 1); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + expect(center.lat).to.be.within(21.9430, 21.9431); + expect(center.lng).to.be(-180); + expect(zoom).to.be(1); + + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + mouse.wait(100).moveTo(200, 200, 0) + .down().moveBy(5, 0, 20).moveBy(scaleX * 256, scaleY * 32, 200).up(); + }); + }); + + it("does not change the center of the map when mouse is moved less than the drag threshold", function (done) { + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + + var originalCenter = L.latLng(0, 0); + map.setView(originalCenter, 1); + + var spy = sinon.spy(); + map.on('drag', spy); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + expect(center).to.be(originalCenter); // Expect center point to be the same as before the click + expect(spy.callCount).to.eql(0); // No drag event should have been fired. + expect(zoom).to.be(1); + + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 2 pixels to stay below the default 3-pixel threshold of + // L.Draggable. This should result in a click and not a drag. + mouse.wait(100).moveTo(200, 200, 0) + .down().moveBy(1, 0, 20).moveBy(1, 0, 200).up(); + }); + + it("does not trigger preclick nor click", function (done) { + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + map.setView([0, 0], 1); + var clickSpy = sinon.spy(); + var preclickSpy = sinon.spy(); + var dragSpy = sinon.spy(); + map.on('click', clickSpy); + map.on('preclick', preclickSpy); + map.on('drag', dragSpy); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + // A real user scenario would trigger a click on mouseup. + // We want to be sure we are cancelling it after a drag. + happen.click(container); + expect(dragSpy.called).to.be(true); + expect(clickSpy.called).to.be(false); + expect(preclickSpy.called).to.be(false); + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + mouse.wait(100).moveTo(200, 200, 0) + .down().moveBy(5, 0, 20).moveBy(256, 32, 200).up(); + }); + + it("does not trigger preclick nor click when dragging on top of a static marker", function (done) { + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + map.setView([0, 0], 1); + var marker = L.marker(map.getCenter()).addTo(map); + var clickSpy = sinon.spy(); + var preclickSpy = sinon.spy(); + var markerDragSpy = sinon.spy(); + var mapDragSpy = sinon.spy(); + map.on('click', clickSpy); + map.on('preclick', preclickSpy); + map.on('drag', mapDragSpy); + marker.on('click', clickSpy); + marker.on('preclick', preclickSpy); + marker.on('drag', markerDragSpy); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + // A real user scenario would trigger a click on mouseup. + // We want to be sure we are cancelling it after a drag. + happen.click(container); + expect(mapDragSpy.called).to.be(true); + expect(markerDragSpy.called).to.be(false); + expect(clickSpy.called).to.be(false); + expect(preclickSpy.called).to.be(false); + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + mouse.moveTo(300, 280, 0) + .down().moveBy(5, 0, 20).moveBy(20, 20, 100).up(); + }); + + it("does not trigger preclick nor click when dragging a marker", function (done) { + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + map.setView([0, 0], 1); + var marker = L.marker(map.getCenter(), {draggable: true}).addTo(map); + var clickSpy = sinon.spy(); + var preclickSpy = sinon.spy(); + var markerDragSpy = sinon.spy(); + var mapDragSpy = sinon.spy(); + map.on('click', clickSpy); + map.on('preclick', preclickSpy); + map.on('drag', mapDragSpy); + marker.on('click', clickSpy); + marker.on('preclick', preclickSpy); + marker.on('drag', markerDragSpy); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + // A real user scenario would trigger a click on mouseup. + // We want to be sure we are cancelling it after a drag. + happen.click(marker._icon); + expect(markerDragSpy.called).to.be(true); + expect(mapDragSpy.called).to.be(false); + expect(clickSpy.called).to.be(false); + expect(preclickSpy.called).to.be(false); + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + mouse.moveTo(300, 280, 0) + .down().moveBy(5, 0, 20).moveBy(50, 50, 100).up(); + }); + + it("does not change the center of the map when drag is disabled on click", function (done) { + var container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + + document.body.appendChild(container); + + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + var originalCenter = L.latLng(0, 0); + map.setView(originalCenter, 1); + + map.on('mousedown', function () { + map.dragging.disable(); + }); + var spy = sinon.spy(); + map.on('drag', spy); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + document.body.removeChild(container); + expect(center).to.be(originalCenter); // Expect center point to be the same as before the click + expect(spy.callCount).to.eql(0); // No drag event should have been fired. + expect(zoom).to.be(1); + + done(); + } + }); + var mouse = hand.growFinger('mouse'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + mouse.wait(100).moveTo(200, 200, 0) + .down().moveBy(5, 0, 20).moveBy(256, 32, 200).up(); + }); + + }); + + describe("touch events", function () { + it.skipIfNotTouch("change the center of the map", function (done) { + var container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + // container.style.background = '#808080'; + + document.body.appendChild(container); + + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + map.setView([0, 0], 1); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + document.body.removeChild(container); + expect(center.lat).to.be.within(21.9430, 21.9431); + expect(center.lng).to.be(-180); + expect(zoom).to.be(1); + + done(); + } + }); + var toucher = hand.growFinger('touch'); + + // We move 5 pixels first to overcome the 3-pixel threshold of + // L.Draggable. + toucher.wait(100).moveTo(200, 200, 0) + .down().moveBy(5, 0, 20).moveBy(256, 32, 200).up(); + }); + + it.skipIfNotTouch("does not change the center of the map when finger is moved less than the drag threshold", function (done) { + var container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + + document.body.appendChild(container); + + var map = new L.Map(container, { + dragging: true, + inertia: false + }); + + var originalCenter = L.latLng(0, 0); + map.setView(originalCenter, 1); + + var spy = sinon.spy(); + map.on('drag', spy); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + document.body.removeChild(container); + expect(center).to.be(originalCenter); // Expect center point to be the same as before the click + expect(spy.callCount).to.eql(0); // No drag event should have been fired. + expect(zoom).to.be(1); + + done(); + } + }); + + var toucher = hand.growFinger('touch'); + + // We move 2 pixels to stay below the default 3-pixel threshold of + // L.Draggable. This should result in a click and not a drag. + toucher.wait(100).moveTo(200, 200, 0) + .down().moveBy(1, 0, 20).moveBy(1, 0, 200).up(); + }); + + it.skipIfNotTouch('reset itself after touchend', function (done) { + + var container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + document.body.appendChild(container); + var map = new L.Map(container, { + dragging: true, + inertia: false, + zoomAnimation: false // If true, the test has to wait extra 250msec + }); + map.setView([0, 0], 1); + + // Change default events order to make the tap comming before the touchzoom. + // See #4315 + map.dragging.disable(); + map.dragging.enable(); + + var center = map.getCenter(), + zoom = map.getZoom(); + + + var mouseHand = new Hand({ + timing: 'fastframe', + onStop: function () { + document.body.removeChild(container); + expect(map.getCenter()).to.eql(center); + expect(map.getZoom()).to.eql(zoom); + + done(); + } + }); + var mouse = mouseHand.growFinger('mouse'); + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + expect(map.getCenter()).not.to.eql(center); + expect(map.getZoom()).not.to.eql(zoom); + center = map.getCenter(); + zoom = map.getZoom(); + mouse.moveTo(220, 220, 0).moveBy(200, 0, 2000); + } + }); + + var f1 = hand.growFinger('touch'); + var f2 = hand.growFinger('touch'); + + hand.sync(5); + f1.wait(100).moveTo(275, 300, 0) + .down().moveBy(-200, 0, 1000).up(200); + // This finger should touch me map after the other one. + f2.wait(110).moveTo(325, 300, 0) + .down().moveBy(210, 0, 1000).up(200); + + }); + + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.KeyboardSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.KeyboardSpec.js new file mode 100644 index 000000000..21942560a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.KeyboardSpec.js @@ -0,0 +1,166 @@ +describe("Map.Keyboard", function () { + + var map, container; + + beforeEach(function () { + container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + document.body.appendChild(container); + map = L.map(container, { + zoomAnimation: false // If true, the test has to wait extra 250msec + }); + + map.setView([0, 0], 5); + + // Keyboard functionality expects the map to be focused (clicked or cycle-tabbed) + // However this can only happen with trusted events (non-synthetic), so + // this bit has to be faked. + map.keyboard._onFocus(); + }); + + afterEach(function () { + map.remove(); + document.body.removeChild(container); + }); + + describe("cursor keys", function () { + it("move the map north", function (done) { + + happen.keydown(document, {keyCode: 38}); // 38 = cursor up + happen.keypress(document, {keyCode: 38}); + happen.keyup(document, {keyCode: 38}); + + setTimeout(function () { + expect(map.getCenter().lat).to.be.greaterThan(0); + done(); + }, 300); + }); + + it("move the map south", function (done) { + + happen.keydown(document, {keyCode: 40}); // 40 = cursor down + happen.keypress(document, {keyCode: 40}); + happen.keyup(document, {keyCode: 40}); + + setTimeout(function () { + expect(map.getCenter().lat).to.be.lessThan(0); + done(); + }, 300); + }); + + it("move the map west", function (done) { + + happen.keydown(document, {keyCode: 37}); // 37 = cursor left + happen.keypress(document, {keyCode: 37}); + happen.keyup(document, {keyCode: 37}); + + setTimeout(function () { + expect(map.getCenter().lng).to.be.lessThan(0); + done(); + }, 300); + }); + + it("move the map east", function (done) { + + happen.keydown(document, {keyCode: 39}); // 39 = cursor right + happen.keypress(document, {keyCode: 39}); + happen.keyup(document, {keyCode: 39}); + + setTimeout(function () { + expect(map.getCenter().lng).to.be.greaterThan(0); + done(); + }, 300); + }); + }); + + describe("plus/minus keys", function () { + it("zoom in", function (done) { + + happen.keydown(document, {keyCode: 171}); // 171 = + + happen.keypress(document, {keyCode: 171}); + happen.keyup(document, {keyCode: 171}); + + setTimeout(function () { + expect(map.getZoom()).to.be.greaterThan(5); + done(); + }, 300); + }); + + it("zoom out", function (done) { + + happen.keydown(document, {keyCode: 173}); // 173 = - (in firefox) + happen.keypress(document, {keyCode: 173}); + happen.keyup(document, {keyCode: 173}); + + setTimeout(function () { + expect(map.getZoom()).to.be.lessThan(5); + done(); + }, 300); + }); + }); + + describe("does not move the map if disabled", function () { + it("no zoom in", function (done) { + + map.keyboard.disable(); + + happen.keydown(document, {keyCode: 171}); // 171 = + + happen.keypress(document, {keyCode: 171}); + happen.keyup(document, {keyCode: 171}); + + setTimeout(function () { + expect(map.getZoom()).to.eql(5); + done(); + }, 300); + }); + + it("no move north", function (done) { + + map.keyboard.disable(); + + happen.keydown(document, {keyCode: 38}); // 38 = cursor up + happen.keypress(document, {keyCode: 38}); + happen.keyup(document, {keyCode: 38}); + + setTimeout(function () { + expect(map.getCenter().lat).to.eql(0); + done(); + }, 300); + }); + }); + + + describe("popup closing", function () { + it("closes a popup when pressing escape", function () { + + var popup = L.popup().setLatLng([0, 0]).setContent('Null Island'); + map.openPopup(popup); + + expect(popup.isOpen()).to.be(true); + + happen.keydown(document, {keyCode: 27}); // 27 = Esc + // happen.keypress(document, {keyCode: 27}); + happen.keyup(document, {keyCode: 27}); + + expect(popup.isOpen()).to.be(false); + }); + }); + + describe("popup closing disabled", function () { + it("close of popup when pressing escape disabled via options", function () { + + var popup = L.popup({closeOnEscapeKey: false}).setLatLng([0, 0]).setContent('Null Island'); + map.openPopup(popup); + + expect(popup.isOpen()).to.be(true); + + happen.keydown(document, {keyCode: 27}); + happen.keyup(document, {keyCode: 27}); + + expect(popup.isOpen()).to.be(true); + }); + }); + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.TouchZoomSpec.js b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.TouchZoomSpec.js new file mode 100644 index 000000000..553417f11 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/spec/suites/map/handler/Map.TouchZoomSpec.js @@ -0,0 +1,87 @@ +describe("Map.TouchZoom", function () { + it.skipIfNotTouch("Increases zoom when pinching out", function (done) { + var container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + document.body.appendChild(container); + + var map = new L.Map(container, { + touchZoom: true, + inertia: false, + zoomAnimation: false // If true, the test has to wait extra 250msec + }); + map.setView([0, 0], 1); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + map.once('zoomend', function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + document.body.removeChild(container); + expect(center.lat).to.be(0); + expect(center.lng).to.be(0); + + // Initial zoom 1, initial distance 50px, final distance 450px + expect(zoom).to.be(4); + + done(); + }); + } + }); + var f1 = hand.growFinger('touch'); + var f2 = hand.growFinger('touch'); + + hand.sync(5); + f1.wait(100).moveTo(275, 300, 0) + .down().moveBy(-200, 0, 500).up(100); + f2.wait(100).moveTo(325, 300, 0) + .down().moveBy(200, 0, 500).up(100); + }); + + + it.skipIfNotTouch("Decreases zoom when pinching in", function (done) { + var container = document.createElement('div'); + container.style.width = container.style.height = '600px'; + container.style.top = container.style.left = 0; + container.style.position = 'absolute'; + document.body.appendChild(container); + + var map = new L.Map(container, { + touchZoom: true, + inertia: false, + zoomAnimation: false // If true, the test has to wait extra 250msec + }); + map.setView([0, 0], 4); + + var hand = new Hand({ + timing: 'fastframe', + onStop: function () { + map.once('zoomend', function () { + var center = map.getCenter(); + var zoom = map.getZoom(); + document.body.removeChild(container); + expect(center.lat).to.be(0); + expect(center.lng).to.be(0); + + // Initial zoom 4, initial distance 450px, final distance 50px + expect(zoom).to.be(1); + + done(); + }); + } + }); + var f1 = hand.growFinger('touch'); + var f2 = hand.growFinger('touch'); + + hand.sync(5); + f1.wait(100).moveTo(75, 300, 0) + .down().moveBy(200, 0, 500).up(100); + f2.wait(100).moveTo(525, 300, 0) + .down().moveBy(-200, 0, 500).up(100); + }); + + + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/Leaflet.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/Leaflet.js new file mode 100644 index 000000000..2b1845027 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/Leaflet.js @@ -0,0 +1,27 @@ + +import {version} from '../package.json'; +export {version}; + +// control +export * from './control/index'; + +// core +export * from './core/index'; + +// dom +export * from './dom/index'; + +// geometry +export * from './geometry/index'; + +// geo +export * from './geo/index'; + +// layer +export * from './layer/index'; + +// map +export * from './map/index'; + +import {freeze} from './core/Util'; +Object.freeze = freeze; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Attribution.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Attribution.js new file mode 100644 index 000000000..49cd478e8 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Attribution.js @@ -0,0 +1,129 @@ + +import {Control} from './Control'; +import {Map} from '../map/Map'; +import * as Util from '../core/Util'; +import * as DomEvent from '../dom/DomEvent'; +import * as DomUtil from '../dom/DomUtil'; + +/* + * @class Control.Attribution + * @aka L.Control.Attribution + * @inherits Control + * + * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control. + */ + +export var Attribution = Control.extend({ + // @section + // @aka Control.Attribution options + options: { + position: 'bottomright', + + // @option prefix: String = 'Leaflet' + // The HTML text shown before the attributions. Pass `false` to disable. + prefix: 'Leaflet' + }, + + initialize: function (options) { + Util.setOptions(this, options); + + this._attributions = {}; + }, + + onAdd: function (map) { + map.attributionControl = this; + this._container = DomUtil.create('div', 'leaflet-control-attribution'); + DomEvent.disableClickPropagation(this._container); + + // TODO ugly, refactor + for (var i in map._layers) { + if (map._layers[i].getAttribution) { + this.addAttribution(map._layers[i].getAttribution()); + } + } + + this._update(); + + return this._container; + }, + + // @method setPrefix(prefix: String): this + // Sets the text before the attributions. + setPrefix: function (prefix) { + this.options.prefix = prefix; + this._update(); + return this; + }, + + // @method addAttribution(text: String): this + // Adds an attribution text (e.g. `'Vector data © Mapbox'`). + addAttribution: function (text) { + if (!text) { return this; } + + if (!this._attributions[text]) { + this._attributions[text] = 0; + } + this._attributions[text]++; + + this._update(); + + return this; + }, + + // @method removeAttribution(text: String): this + // Removes an attribution text. + removeAttribution: function (text) { + if (!text) { return this; } + + if (this._attributions[text]) { + this._attributions[text]--; + this._update(); + } + + return this; + }, + + _update: function () { + if (!this._map) { return; } + + var attribs = []; + + for (var i in this._attributions) { + if (this._attributions[i]) { + attribs.push(i); + } + } + + var prefixAndAttribs = []; + + if (this.options.prefix) { + prefixAndAttribs.push(this.options.prefix); + } + if (attribs.length) { + prefixAndAttribs.push(attribs.join(', ')); + } + + this._container.innerHTML = prefixAndAttribs.join(' | '); + } +}); + +// @namespace Map +// @section Control options +// @option attributionControl: Boolean = true +// Whether a [attribution control](#control-attribution) is added to the map by default. +Map.mergeOptions({ + attributionControl: true +}); + +Map.addInitHook(function () { + if (this.options.attributionControl) { + new Attribution().addTo(this); + } +}); + +// @namespace Control.Attribution +// @factory L.control.attribution(options: Control.Attribution options) +// Creates an attribution control. +export var attribution = function (options) { + return new Attribution(options); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Layers.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Layers.js new file mode 100644 index 000000000..832305a33 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Layers.js @@ -0,0 +1,431 @@ + +import {Control} from './Control'; +import * as Util from '../core/Util'; +import * as Browser from '../core/Browser'; +import * as DomEvent from '../dom/DomEvent'; +import * as DomUtil from '../dom/DomUtil'; + +/* + * @class Control.Layers + * @aka L.Control.Layers + * @inherits Control + * + * The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the [detailed example](http://leafletjs.com/examples/layers-control/)). Extends `Control`. + * + * @example + * + * ```js + * var baseLayers = { + * "Mapbox": mapbox, + * "OpenStreetMap": osm + * }; + * + * var overlays = { + * "Marker": marker, + * "Roads": roadsLayer + * }; + * + * L.control.layers(baseLayers, overlays).addTo(map); + * ``` + * + * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values: + * + * ```js + * { + * "": layer1, + * "": layer2 + * } + * ``` + * + * The layer names can contain HTML, which allows you to add additional styling to the items: + * + * ```js + * {" My Layer": myLayer} + * ``` + */ + +export var Layers = Control.extend({ + // @section + // @aka Control.Layers options + options: { + // @option collapsed: Boolean = true + // If `true`, the control will be collapsed into an icon and expanded on mouse hover or touch. + collapsed: true, + position: 'topright', + + // @option autoZIndex: Boolean = true + // If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off. + autoZIndex: true, + + // @option hideSingleBase: Boolean = false + // If `true`, the base layers in the control will be hidden when there is only one. + hideSingleBase: false, + + // @option sortLayers: Boolean = false + // Whether to sort the layers. When `false`, layers will keep the order + // in which they were added to the control. + sortLayers: false, + + // @option sortFunction: Function = * + // A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) + // that will be used for sorting the layers, when `sortLayers` is `true`. + // The function receives both the `L.Layer` instances and their names, as in + // `sortFunction(layerA, layerB, nameA, nameB)`. + // By default, it sorts layers alphabetically by their name. + sortFunction: function (layerA, layerB, nameA, nameB) { + return nameA < nameB ? -1 : (nameB < nameA ? 1 : 0); + } + }, + + initialize: function (baseLayers, overlays, options) { + Util.setOptions(this, options); + + this._layerControlInputs = []; + this._layers = []; + this._lastZIndex = 0; + this._handlingClick = false; + + for (var i in baseLayers) { + this._addLayer(baseLayers[i], i); + } + + for (i in overlays) { + this._addLayer(overlays[i], i, true); + } + }, + + onAdd: function (map) { + this._initLayout(); + this._update(); + + this._map = map; + map.on('zoomend', this._checkDisabledLayers, this); + + for (var i = 0; i < this._layers.length; i++) { + this._layers[i].layer.on('add remove', this._onLayerChange, this); + } + + return this._container; + }, + + addTo: function (map) { + Control.prototype.addTo.call(this, map); + // Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height. + return this._expandIfNotCollapsed(); + }, + + onRemove: function () { + this._map.off('zoomend', this._checkDisabledLayers, this); + + for (var i = 0; i < this._layers.length; i++) { + this._layers[i].layer.off('add remove', this._onLayerChange, this); + } + }, + + // @method addBaseLayer(layer: Layer, name: String): this + // Adds a base layer (radio button entry) with the given name to the control. + addBaseLayer: function (layer, name) { + this._addLayer(layer, name); + return (this._map) ? this._update() : this; + }, + + // @method addOverlay(layer: Layer, name: String): this + // Adds an overlay (checkbox entry) with the given name to the control. + addOverlay: function (layer, name) { + this._addLayer(layer, name, true); + return (this._map) ? this._update() : this; + }, + + // @method removeLayer(layer: Layer): this + // Remove the given layer from the control. + removeLayer: function (layer) { + layer.off('add remove', this._onLayerChange, this); + + var obj = this._getLayer(Util.stamp(layer)); + if (obj) { + this._layers.splice(this._layers.indexOf(obj), 1); + } + return (this._map) ? this._update() : this; + }, + + // @method expand(): this + // Expand the control container if collapsed. + expand: function () { + DomUtil.addClass(this._container, 'leaflet-control-layers-expanded'); + this._section.style.height = null; + var acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50); + if (acceptableHeight < this._section.clientHeight) { + DomUtil.addClass(this._section, 'leaflet-control-layers-scrollbar'); + this._section.style.height = acceptableHeight + 'px'; + } else { + DomUtil.removeClass(this._section, 'leaflet-control-layers-scrollbar'); + } + this._checkDisabledLayers(); + return this; + }, + + // @method collapse(): this + // Collapse the control container if expanded. + collapse: function () { + DomUtil.removeClass(this._container, 'leaflet-control-layers-expanded'); + return this; + }, + + _initLayout: function () { + var className = 'leaflet-control-layers', + container = this._container = DomUtil.create('div', className), + collapsed = this.options.collapsed; + + // makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released + container.setAttribute('aria-haspopup', true); + + DomEvent.disableClickPropagation(container); + DomEvent.disableScrollPropagation(container); + + var section = this._section = DomUtil.create('section', className + '-list'); + + if (collapsed) { + this._map.on('click', this.collapse, this); + + if (!Browser.android) { + DomEvent.on(container, { + mouseenter: this.expand, + mouseleave: this.collapse + }, this); + } + } + + var link = this._layersLink = DomUtil.create('a', className + '-toggle', container); + link.href = '#'; + link.title = 'Layers'; + + if (Browser.touch) { + DomEvent.on(link, 'click', DomEvent.stop); + DomEvent.on(link, 'click', this.expand, this); + } else { + DomEvent.on(link, 'focus', this.expand, this); + } + + if (!collapsed) { + this.expand(); + } + + this._baseLayersList = DomUtil.create('div', className + '-base', section); + this._separator = DomUtil.create('div', className + '-separator', section); + this._overlaysList = DomUtil.create('div', className + '-overlays', section); + + container.appendChild(section); + }, + + _getLayer: function (id) { + for (var i = 0; i < this._layers.length; i++) { + + if (this._layers[i] && Util.stamp(this._layers[i].layer) === id) { + return this._layers[i]; + } + } + }, + + _addLayer: function (layer, name, overlay) { + if (this._map) { + layer.on('add remove', this._onLayerChange, this); + } + + this._layers.push({ + layer: layer, + name: name, + overlay: overlay + }); + + if (this.options.sortLayers) { + this._layers.sort(Util.bind(function (a, b) { + return this.options.sortFunction(a.layer, b.layer, a.name, b.name); + }, this)); + } + + if (this.options.autoZIndex && layer.setZIndex) { + this._lastZIndex++; + layer.setZIndex(this._lastZIndex); + } + + this._expandIfNotCollapsed(); + }, + + _update: function () { + if (!this._container) { return this; } + + DomUtil.empty(this._baseLayersList); + DomUtil.empty(this._overlaysList); + + this._layerControlInputs = []; + var baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0; + + for (i = 0; i < this._layers.length; i++) { + obj = this._layers[i]; + this._addItem(obj); + overlaysPresent = overlaysPresent || obj.overlay; + baseLayersPresent = baseLayersPresent || !obj.overlay; + baseLayersCount += !obj.overlay ? 1 : 0; + } + + // Hide base layers section if there's only one layer. + if (this.options.hideSingleBase) { + baseLayersPresent = baseLayersPresent && baseLayersCount > 1; + this._baseLayersList.style.display = baseLayersPresent ? '' : 'none'; + } + + this._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none'; + + return this; + }, + + _onLayerChange: function (e) { + if (!this._handlingClick) { + this._update(); + } + + var obj = this._getLayer(Util.stamp(e.target)); + + // @namespace Map + // @section Layer events + // @event baselayerchange: LayersControlEvent + // Fired when the base layer is changed through the [layer control](#control-layers). + // @event overlayadd: LayersControlEvent + // Fired when an overlay is selected through the [layer control](#control-layers). + // @event overlayremove: LayersControlEvent + // Fired when an overlay is deselected through the [layer control](#control-layers). + // @namespace Control.Layers + var type = obj.overlay ? + (e.type === 'add' ? 'overlayadd' : 'overlayremove') : + (e.type === 'add' ? 'baselayerchange' : null); + + if (type) { + this._map.fire(type, obj); + } + }, + + // IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe) + _createRadioElement: function (name, checked) { + + var radioHtml = ''; + + var radioFragment = document.createElement('div'); + radioFragment.innerHTML = radioHtml; + + return radioFragment.firstChild; + }, + + _addItem: function (obj) { + var label = document.createElement('label'), + checked = this._map.hasLayer(obj.layer), + input; + + if (obj.overlay) { + input = document.createElement('input'); + input.type = 'checkbox'; + input.className = 'leaflet-control-layers-selector'; + input.defaultChecked = checked; + } else { + input = this._createRadioElement('leaflet-base-layers', checked); + } + + this._layerControlInputs.push(input); + input.layerId = Util.stamp(obj.layer); + + DomEvent.on(input, 'click', this._onInputClick, this); + + var name = document.createElement('span'); + name.innerHTML = ' ' + obj.name; + + // Helps from preventing layer control flicker when checkboxes are disabled + // https://github.com/Leaflet/Leaflet/issues/2771 + var holder = document.createElement('div'); + + label.appendChild(holder); + holder.appendChild(input); + holder.appendChild(name); + + var container = obj.overlay ? this._overlaysList : this._baseLayersList; + container.appendChild(label); + + this._checkDisabledLayers(); + return label; + }, + + _onInputClick: function () { + var inputs = this._layerControlInputs, + input, layer; + var addedLayers = [], + removedLayers = []; + + this._handlingClick = true; + + for (var i = inputs.length - 1; i >= 0; i--) { + input = inputs[i]; + layer = this._getLayer(input.layerId).layer; + + if (input.checked) { + addedLayers.push(layer); + } else if (!input.checked) { + removedLayers.push(layer); + } + } + + // Bugfix issue 2318: Should remove all old layers before readding new ones + for (i = 0; i < removedLayers.length; i++) { + if (this._map.hasLayer(removedLayers[i])) { + this._map.removeLayer(removedLayers[i]); + } + } + for (i = 0; i < addedLayers.length; i++) { + if (!this._map.hasLayer(addedLayers[i])) { + this._map.addLayer(addedLayers[i]); + } + } + + this._handlingClick = false; + + this._refocusOnMap(); + }, + + _checkDisabledLayers: function () { + var inputs = this._layerControlInputs, + input, + layer, + zoom = this._map.getZoom(); + + for (var i = inputs.length - 1; i >= 0; i--) { + input = inputs[i]; + layer = this._getLayer(input.layerId).layer; + input.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) || + (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom); + + } + }, + + _expandIfNotCollapsed: function () { + if (this._map && !this.options.collapsed) { + this.expand(); + } + return this; + }, + + _expand: function () { + // Backward compatibility, remove me in 1.1. + return this.expand(); + }, + + _collapse: function () { + // Backward compatibility, remove me in 1.1. + return this.collapse(); + } + +}); + + +// @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options) +// Creates an attribution control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation. +export var layers = function (baseLayers, overlays, options) { + return new Layers(baseLayers, overlays, options); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Scale.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Scale.js new file mode 100644 index 000000000..dffe4d05e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Scale.js @@ -0,0 +1,132 @@ + +import {Control} from './Control'; +import * as DomUtil from '../dom/DomUtil'; + +/* + * @class Control.Scale + * @aka L.Control.Scale + * @inherits Control + * + * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`. + * + * @example + * + * ```js + * L.control.scale().addTo(map); + * ``` + */ + +export var Scale = Control.extend({ + // @section + // @aka Control.Scale options + options: { + position: 'bottomleft', + + // @option maxWidth: Number = 100 + // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500). + maxWidth: 100, + + // @option metric: Boolean = True + // Whether to show the metric scale line (m/km). + metric: true, + + // @option imperial: Boolean = True + // Whether to show the imperial scale line (mi/ft). + imperial: true + + // @option updateWhenIdle: Boolean = false + // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)). + }, + + onAdd: function (map) { + var className = 'leaflet-control-scale', + container = DomUtil.create('div', className), + options = this.options; + + this._addScales(options, className + '-line', container); + + map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); + map.whenReady(this._update, this); + + return container; + }, + + onRemove: function (map) { + map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); + }, + + _addScales: function (options, className, container) { + if (options.metric) { + this._mScale = DomUtil.create('div', className, container); + } + if (options.imperial) { + this._iScale = DomUtil.create('div', className, container); + } + }, + + _update: function () { + var map = this._map, + y = map.getSize().y / 2; + + var maxMeters = map.distance( + map.containerPointToLatLng([0, y]), + map.containerPointToLatLng([this.options.maxWidth, y])); + + this._updateScales(maxMeters); + }, + + _updateScales: function (maxMeters) { + if (this.options.metric && maxMeters) { + this._updateMetric(maxMeters); + } + if (this.options.imperial && maxMeters) { + this._updateImperial(maxMeters); + } + }, + + _updateMetric: function (maxMeters) { + var meters = this._getRoundNum(maxMeters), + label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; + + this._updateScale(this._mScale, label, meters / maxMeters); + }, + + _updateImperial: function (maxMeters) { + var maxFeet = maxMeters * 3.2808399, + maxMiles, miles, feet; + + if (maxFeet > 5280) { + maxMiles = maxFeet / 5280; + miles = this._getRoundNum(maxMiles); + this._updateScale(this._iScale, miles + ' mi', miles / maxMiles); + + } else { + feet = this._getRoundNum(maxFeet); + this._updateScale(this._iScale, feet + ' ft', feet / maxFeet); + } + }, + + _updateScale: function (scale, text, ratio) { + scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px'; + scale.innerHTML = text; + }, + + _getRoundNum: function (num) { + var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), + d = num / pow10; + + d = d >= 10 ? 10 : + d >= 5 ? 5 : + d >= 3 ? 3 : + d >= 2 ? 2 : 1; + + return pow10 * d; + } +}); + + +// @factory L.control.scale(options?: Control.Scale options) +// Creates an scale control with the given options. +export var scale = function (options) { + return new Scale(options); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Zoom.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Zoom.js new file mode 100644 index 000000000..07525863c --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.Zoom.js @@ -0,0 +1,142 @@ + +import {Control} from './Control'; +import {Map} from '../map/Map'; +import * as DomUtil from '../dom/DomUtil'; +import * as DomEvent from '../dom/DomEvent'; + +/* + * @class Control.Zoom + * @aka L.Control.Zoom + * @inherits Control + * + * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`. + */ + +export var Zoom = Control.extend({ + // @section + // @aka Control.Zoom options + options: { + position: 'topleft', + + // @option zoomInText: String = '+' + // The text set on the 'zoom in' button. + zoomInText: '+', + + // @option zoomInTitle: String = 'Zoom in' + // The title set on the 'zoom in' button. + zoomInTitle: 'Zoom in', + + // @option zoomOutText: String = '−' + // The text set on the 'zoom out' button. + zoomOutText: '−', + + // @option zoomOutTitle: String = 'Zoom out' + // The title set on the 'zoom out' button. + zoomOutTitle: 'Zoom out' + }, + + onAdd: function (map) { + var zoomName = 'leaflet-control-zoom', + container = DomUtil.create('div', zoomName + ' leaflet-bar'), + options = this.options; + + this._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle, + zoomName + '-in', container, this._zoomIn); + this._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle, + zoomName + '-out', container, this._zoomOut); + + this._updateDisabled(); + map.on('zoomend zoomlevelschange', this._updateDisabled, this); + + return container; + }, + + onRemove: function (map) { + map.off('zoomend zoomlevelschange', this._updateDisabled, this); + }, + + disable: function () { + this._disabled = true; + this._updateDisabled(); + return this; + }, + + enable: function () { + this._disabled = false; + this._updateDisabled(); + return this; + }, + + _zoomIn: function (e) { + if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) { + this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); + } + }, + + _zoomOut: function (e) { + if (!this._disabled && this._map._zoom > this._map.getMinZoom()) { + this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); + } + }, + + _createButton: function (html, title, className, container, fn) { + var link = DomUtil.create('a', className, container); + link.innerHTML = html; + link.href = '#'; + link.title = title; + + /* + * Will force screen readers like VoiceOver to read this as "Zoom in - button" + */ + link.setAttribute('role', 'button'); + link.setAttribute('aria-label', title); + + DomEvent.disableClickPropagation(link); + DomEvent.on(link, 'click', DomEvent.stop); + DomEvent.on(link, 'click', fn, this); + DomEvent.on(link, 'click', this._refocusOnMap, this); + + return link; + }, + + _updateDisabled: function () { + var map = this._map, + className = 'leaflet-disabled'; + + DomUtil.removeClass(this._zoomInButton, className); + DomUtil.removeClass(this._zoomOutButton, className); + + if (this._disabled || map._zoom === map.getMinZoom()) { + DomUtil.addClass(this._zoomOutButton, className); + } + if (this._disabled || map._zoom === map.getMaxZoom()) { + DomUtil.addClass(this._zoomInButton, className); + } + } +}); + +// @namespace Map +// @section Control options +// @option zoomControl: Boolean = true +// Whether a [zoom control](#control-zoom) is added to the map by default. +Map.mergeOptions({ + zoomControl: true +}); + +Map.addInitHook(function () { + if (this.options.zoomControl) { + // @section Controls + // @property zoomControl: Control.Zoom + // The default zoom control (only available if the + // [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map). + this.zoomControl = new Zoom(); + this.addControl(this.zoomControl); + } +}); + +// @namespace Control.Zoom +// @factory L.control.zoom(options: Control.Zoom options) +// Creates a zoom control +export var zoom = function (options) { + return new Zoom(options); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.js new file mode 100644 index 000000000..6db9f4bb0 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/Control.js @@ -0,0 +1,171 @@ + +import {Class} from '../core/Class'; +import {Map} from '../map/Map'; +import * as Util from '../core/Util'; +import * as DomUtil from '../dom/DomUtil'; + +/* + * @class Control + * @aka L.Control + * @inherits Class + * + * L.Control is a base class for implementing map controls. Handles positioning. + * All other controls extend from this class. + */ + +export var Control = Class.extend({ + // @section + // @aka Control options + options: { + // @option position: String = 'topright' + // The position of the control (one of the map corners). Possible values are `'topleft'`, + // `'topright'`, `'bottomleft'` or `'bottomright'` + position: 'topright' + }, + + initialize: function (options) { + Util.setOptions(this, options); + }, + + /* @section + * Classes extending L.Control will inherit the following methods: + * + * @method getPosition: string + * Returns the position of the control. + */ + getPosition: function () { + return this.options.position; + }, + + // @method setPosition(position: string): this + // Sets the position of the control. + setPosition: function (position) { + var map = this._map; + + if (map) { + map.removeControl(this); + } + + this.options.position = position; + + if (map) { + map.addControl(this); + } + + return this; + }, + + // @method getContainer: HTMLElement + // Returns the HTMLElement that contains the control. + getContainer: function () { + return this._container; + }, + + // @method addTo(map: Map): this + // Adds the control to the given map. + addTo: function (map) { + this.remove(); + this._map = map; + + var container = this._container = this.onAdd(map), + pos = this.getPosition(), + corner = map._controlCorners[pos]; + + DomUtil.addClass(container, 'leaflet-control'); + + if (pos.indexOf('bottom') !== -1) { + corner.insertBefore(container, corner.firstChild); + } else { + corner.appendChild(container); + } + + return this; + }, + + // @method remove: this + // Removes the control from the map it is currently active on. + remove: function () { + if (!this._map) { + return this; + } + + DomUtil.remove(this._container); + + if (this.onRemove) { + this.onRemove(this._map); + } + + this._map = null; + + return this; + }, + + _refocusOnMap: function (e) { + // if map exists and event is not a keyboard event + if (this._map && e && e.screenX > 0 && e.screenY > 0) { + this._map.getContainer().focus(); + } + } +}); + +export var control = function (options) { + return new Control(options); +}; + +/* @section Extension methods + * @uninheritable + * + * Every control should extend from `L.Control` and (re-)implement the following methods. + * + * @method onAdd(map: Map): HTMLElement + * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo). + * + * @method onRemove(map: Map) + * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove). + */ + +/* @namespace Map + * @section Methods for Layers and Controls + */ +Map.include({ + // @method addControl(control: Control): this + // Adds the given control to the map + addControl: function (control) { + control.addTo(this); + return this; + }, + + // @method removeControl(control: Control): this + // Removes the given control from the map + removeControl: function (control) { + control.remove(); + return this; + }, + + _initControlPos: function () { + var corners = this._controlCorners = {}, + l = 'leaflet-', + container = this._controlContainer = + DomUtil.create('div', l + 'control-container', this._container); + + function createCorner(vSide, hSide) { + var className = l + vSide + ' ' + l + hSide; + + corners[vSide + hSide] = DomUtil.create('div', className, container); + } + + createCorner('top', 'left'); + createCorner('top', 'right'); + createCorner('bottom', 'left'); + createCorner('bottom', 'right'); + }, + + _clearControlPos: function () { + for (var i in this._controlCorners) { + DomUtil.remove(this._controlCorners[i]); + } + DomUtil.remove(this._controlContainer); + delete this._controlCorners; + delete this._controlContainer; + } +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/control/index.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/index.js new file mode 100644 index 000000000..92d5205a6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/control/index.js @@ -0,0 +1,17 @@ +import {Control, control} from './Control'; +import {Layers, layers} from './Control.Layers'; +import {Zoom, zoom} from './Control.Zoom'; +import {Scale, scale} from './Control.Scale'; +import {Attribution, attribution} from './Control.Attribution'; + +Control.Layers = Layers; +Control.Zoom = Zoom; +Control.Scale = Scale; +Control.Attribution = Attribution; + +control.layers = layers; +control.zoom = zoom; +control.scale = scale; +control.attribution = attribution; + +export {Control, control}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Browser.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Browser.js new file mode 100644 index 000000000..cc8f859c2 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Browser.js @@ -0,0 +1,147 @@ +import {svgCreate} from '../layer/vector/SVG.Util'; + +/* + * @namespace Browser + * @aka L.Browser + * + * A namespace with static properties for browser/feature detection used by Leaflet internally. + * + * @example + * + * ```js + * if (L.Browser.ielt9) { + * alert('Upgrade your browser, dude!'); + * } + * ``` + */ + +var style = document.documentElement.style; + +// @property ie: Boolean; `true` for all Internet Explorer versions (not Edge). +export var ie = 'ActiveXObject' in window; + +// @property ielt9: Boolean; `true` for Internet Explorer versions less than 9. +export var ielt9 = ie && !document.addEventListener; + +// @property edge: Boolean; `true` for the Edge web browser. +export var edge = 'msLaunchUri' in navigator && !('documentMode' in document); + +// @property webkit: Boolean; +// `true` for webkit-based browsers like Chrome and Safari (including mobile versions). +export var webkit = userAgentContains('webkit'); + +// @property android: Boolean +// `true` for any browser running on an Android platform. +export var android = userAgentContains('android'); + +// @property android23: Boolean; `true` for browsers running on Android 2 or Android 3. +export var android23 = userAgentContains('android 2') || userAgentContains('android 3'); + +/* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */ +var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit +// @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome) +export var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window); + +// @property opera: Boolean; `true` for the Opera browser +export var opera = !!window.opera; + +// @property chrome: Boolean; `true` for the Chrome browser. +export var chrome = userAgentContains('chrome'); + +// @property gecko: Boolean; `true` for gecko-based browsers like Firefox. +export var gecko = userAgentContains('gecko') && !webkit && !opera && !ie; + +// @property safari: Boolean; `true` for the Safari browser. +export var safari = !chrome && userAgentContains('safari'); + +export var phantom = userAgentContains('phantom'); + +// @property opera12: Boolean +// `true` for the Opera browser supporting CSS transforms (version 12 or later). +export var opera12 = 'OTransition' in style; + +// @property win: Boolean; `true` when the browser is running in a Windows platform +export var win = navigator.platform.indexOf('Win') === 0; + +// @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms. +export var ie3d = ie && ('transition' in style); + +// @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms. +export var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23; + +// @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms. +export var gecko3d = 'MozPerspective' in style; + +// @property any3d: Boolean +// `true` for all browsers supporting CSS transforms. +export var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom; + +// @property mobile: Boolean; `true` for all browsers running in a mobile device. +export var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile'); + +// @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device. +export var mobileWebkit = mobile && webkit; + +// @property mobileWebkit3d: Boolean +// `true` for all webkit-based browsers in a mobile device supporting CSS transforms. +export var mobileWebkit3d = mobile && webkit3d; + +// @property msPointer: Boolean +// `true` for browsers implementing the Microsoft touch events model (notably IE10). +export var msPointer = !window.PointerEvent && window.MSPointerEvent; + +// @property pointer: Boolean +// `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx). +export var pointer = !!(window.PointerEvent || msPointer); + +// @property touch: Boolean +// `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events). +// This does not necessarily mean that the browser is running in a computer with +// a touchscreen, it only means that the browser is capable of understanding +// touch events. +export var touch = !window.L_NO_TOUCH && (pointer || 'ontouchstart' in window || + (window.DocumentTouch && document instanceof window.DocumentTouch)); + +// @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device. +export var mobileOpera = mobile && opera; + +// @property mobileGecko: Boolean +// `true` for gecko-based browsers running in a mobile device. +export var mobileGecko = mobile && gecko; + +// @property retina: Boolean +// `true` for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%. +export var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1; + + +// @property canvas: Boolean +// `true` when the browser supports [``](https://developer.mozilla.org/docs/Web/API/Canvas_API). +export var canvas = (function () { + return !!document.createElement('canvas').getContext; +}()); + +// @property svg: Boolean +// `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG). +export var svg = !!(document.createElementNS && svgCreate('svg').createSVGRect); + +// @property vml: Boolean +// `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language). +export var vml = !svg && (function () { + try { + var div = document.createElement('div'); + div.innerHTML = ''; + + var shape = div.firstChild; + shape.style.behavior = 'url(#default#VML)'; + + return shape && (typeof shape.adj === 'object'); + + } catch (e) { + return false; + } +}()); + + +function userAgentContains(str) { + return navigator.userAgent.toLowerCase().indexOf(str) >= 0; +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Class.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Class.js new file mode 100644 index 000000000..df367b617 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Class.js @@ -0,0 +1,126 @@ +import * as Util from './Util'; + +// @class Class +// @aka L.Class + +// @section +// @uninheritable + +// Thanks to John Resig and Dean Edwards for inspiration! + +export function Class() {} + +Class.extend = function (props) { + + // @function extend(props: Object): Function + // [Extends the current class](#class-inheritance) given the properties to be included. + // Returns a Javascript function that is a class constructor (to be called with `new`). + var NewClass = function () { + + // call the constructor + if (this.initialize) { + this.initialize.apply(this, arguments); + } + + // call all constructor hooks + this.callInitHooks(); + }; + + var parentProto = NewClass.__super__ = this.prototype; + + var proto = Util.create(parentProto); + proto.constructor = NewClass; + + NewClass.prototype = proto; + + // inherit parent's statics + for (var i in this) { + if (this.hasOwnProperty(i) && i !== 'prototype' && i !== '__super__') { + NewClass[i] = this[i]; + } + } + + // mix static properties into the class + if (props.statics) { + Util.extend(NewClass, props.statics); + delete props.statics; + } + + // mix includes into the prototype + if (props.includes) { + checkDeprecatedMixinEvents(props.includes); + Util.extend.apply(null, [proto].concat(props.includes)); + delete props.includes; + } + + // merge options + if (proto.options) { + props.options = Util.extend(Util.create(proto.options), props.options); + } + + // mix given properties into the prototype + Util.extend(proto, props); + + proto._initHooks = []; + + // add method for calling all hooks + proto.callInitHooks = function () { + + if (this._initHooksCalled) { return; } + + if (parentProto.callInitHooks) { + parentProto.callInitHooks.call(this); + } + + this._initHooksCalled = true; + + for (var i = 0, len = proto._initHooks.length; i < len; i++) { + proto._initHooks[i].call(this); + } + }; + + return NewClass; +}; + + +// @function include(properties: Object): this +// [Includes a mixin](#class-includes) into the current class. +Class.include = function (props) { + Util.extend(this.prototype, props); + return this; +}; + +// @function mergeOptions(options: Object): this +// [Merges `options`](#class-options) into the defaults of the class. +Class.mergeOptions = function (options) { + Util.extend(this.prototype.options, options); + return this; +}; + +// @function addInitHook(fn: Function): this +// Adds a [constructor hook](#class-constructor-hooks) to the class. +Class.addInitHook = function (fn) { // (Function) || (String, args...) + var args = Array.prototype.slice.call(arguments, 1); + + var init = typeof fn === 'function' ? fn : function () { + this[fn].apply(this, args); + }; + + this.prototype._initHooks = this.prototype._initHooks || []; + this.prototype._initHooks.push(init); + return this; +}; + +function checkDeprecatedMixinEvents(includes) { + if (typeof L === 'undefined' || !L || !L.Mixin) { return; } + + includes = Util.isArray(includes) ? includes : [includes]; + + for (var i = 0; i < includes.length; i++) { + if (includes[i] === L.Mixin.Events) { + console.warn('Deprecated include of L.Mixin.Events: ' + + 'this property will be removed in future releases, ' + + 'please inherit from L.Evented instead.', new Error().stack); + } + } +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Class.leafdoc b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Class.leafdoc new file mode 100644 index 000000000..dbcf85e7d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Class.leafdoc @@ -0,0 +1,197 @@ + +@class Class +@aka L.Class + +L.Class powers the OOP facilities of Leaflet and is used to create almost all of the Leaflet classes documented here. + +In addition to implementing a simple classical inheritance model, it introduces several special properties for convenient code organization — options, includes and statics. + + +@example + +```js +var MyClass = L.Class.extend({ +initialize: function (greeter) { + this.greeter = greeter; + // class constructor +}, + +greet: function (name) { + alert(this.greeter + ', ' + name) + } +}); + +// create instance of MyClass, passing "Hello" to the constructor +var a = new MyClass("Hello"); + +// call greet method, alerting "Hello, World" +a.greet("World"); +``` + +@section Class Factories +@example + +You may have noticed that Leaflet objects are created without using +the `new` keyword. This is achieved by complementing each class with a +lowercase factory method: + +```js +new L.Map('map'); // becomes: +L.map('map'); +``` + +The factories are implemented very easily, and you can do this for your own classes: + +```js +L.map = function (id, options) { + return new L.Map(id, options); +}; +``` +@section Inheritance +@example + +You use L.Class.extend to define new classes, but you can use the same method on any class to inherit from it: + +```js +var MyChildClass = MyClass.extend({ + // ... new properties and methods +}); +``` + +This will create a class that inherits all methods and properties of the parent class (through a proper prototype chain), adding or overriding the ones you pass to extend. It will also properly react to instanceof: + +```js +var a = new MyChildClass(); +a instanceof MyChildClass; // true +a instanceof MyClass; // true +``` + +You can call parent methods (including constructor) from corresponding child ones (as you do with super calls in other languages) by accessing parent class prototype and using JavaScript's call or apply: + +``` +var MyChildClass = MyClass.extend({ + initialize: function () { + MyClass.prototype.initialize.call(this, "Yo"); + }, + + greet: function (name) { + MyClass.prototype.greet.call(this, 'bro ' + name + '!'); + } +}); + +var a = new MyChildClass(); +a.greet('Jason'); // alerts "Yo, bro Jason!" +``` + +@section Options +@example + +`options` is a special property that unlike other objects that you pass +to `extend` will be merged with the parent one instead of overriding it +completely, which makes managing configuration of objects and default +values convenient: + +```js +var MyClass = L.Class.extend({ + options: { + myOption1: 'foo', + myOption2: 'bar' + } +}); + +var MyChildClass = MyClass.extend({ + options: { + myOption1: 'baz', + myOption3: 5 + } +}); + +var a = new MyChildClass(); +a.options.myOption1; // 'baz' +a.options.myOption2; // 'bar' +a.options.myOption3; // 5 +``` + +There's also [`L.Util.setOptions`](#util-setoptions), a method for +conveniently merging options passed to constructor with the defaults +defines in the class: + +```js +var MyClass = L.Class.extend({ + options: { + foo: 'bar', + bla: 5 + }, + + initialize: function (options) { + L.Util.setOptions(this, options); + ... + } +}); + +var a = new MyClass({bla: 10}); +a.options; // {foo: 'bar', bla: 10} +``` + +Note that the options object allows any keys, not just +the options defined by the class and its base classes. +This means you can use the options object to store +application specific information, as long as you avoid +keys that are already used by the class in question. + +@section Includes +@example + +`includes` is a special class property that merges all specified objects into the class (such objects are called mixins). + +```js + var MyMixin = { + foo: function () { ... }, + bar: 5 +}; + +var MyClass = L.Class.extend({ + includes: MyMixin +}); + +var a = new MyClass(); +a.foo(); +``` + +You can also do such includes in runtime with the `include` method: + +```js +MyClass.include(MyMixin); +``` + +`statics` is just a convenience property that injects specified object properties as the static properties of the class, useful for defining constants: + +```js +var MyClass = L.Class.extend({ + statics: { + FOO: 'bar', + BLA: 5 + } +}); + +MyClass.FOO; // 'bar' +``` + + +@section Constructor hooks +@example + +If you're a plugin developer, you often need to add additional initialization code to existing classes (e.g. editing hooks for `L.Polyline`). Leaflet comes with a way to do it easily using the `addInitHook` method: + +```js +MyClass.addInitHook(function () { + // ... do something in constructor additionally + // e.g. add event listeners, set custom properties etc. +}); +``` + +You can also use the following shortcut when you just need to make one additional method call: + +```js +MyClass.addInitHook('methodName', arg1, arg2, …); +``` diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Events.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Events.js new file mode 100644 index 000000000..fc78b2631 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Events.js @@ -0,0 +1,295 @@ +import {Class} from './Class'; +import * as Util from './Util'; + +/* + * @class Evented + * @aka L.Evented + * @inherits Class + * + * A set of methods shared between event-powered classes (like `Map` and `Marker`). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire `'click'` event). + * + * @example + * + * ```js + * map.on('click', function(e) { + * alert(e.latlng); + * } ); + * ``` + * + * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function: + * + * ```js + * function onClick(e) { ... } + * + * map.on('click', onClick); + * map.off('click', onClick); + * ``` + */ + +export var Events = { + /* @method on(type: String, fn: Function, context?: Object): this + * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`). + * + * @alternative + * @method on(eventMap: Object): this + * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` + */ + on: function (types, fn, context) { + + // types can be a map of types/handlers + if (typeof types === 'object') { + for (var type in types) { + // we don't process space-separated events here for performance; + // it's a hot path since Layer uses the on(obj) syntax + this._on(type, types[type], fn); + } + + } else { + // types can be a string of space-separated words + types = Util.splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + this._on(types[i], fn, context); + } + } + + return this; + }, + + /* @method off(type: String, fn?: Function, context?: Object): this + * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener. + * + * @alternative + * @method off(eventMap: Object): this + * Removes a set of type/listener pairs. + * + * @alternative + * @method off: this + * Removes all listeners to all events on the object. + */ + off: function (types, fn, context) { + + if (!types) { + // clear all listeners if called without arguments + delete this._events; + + } else if (typeof types === 'object') { + for (var type in types) { + this._off(type, types[type], fn); + } + + } else { + types = Util.splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + this._off(types[i], fn, context); + } + } + + return this; + }, + + // attach listener (without syntactic sugar now) + _on: function (type, fn, context) { + this._events = this._events || {}; + + /* get/init listeners for type */ + var typeListeners = this._events[type]; + if (!typeListeners) { + typeListeners = []; + this._events[type] = typeListeners; + } + + if (context === this) { + // Less memory footprint. + context = undefined; + } + var newListener = {fn: fn, ctx: context}, + listeners = typeListeners; + + // check if fn already there + for (var i = 0, len = listeners.length; i < len; i++) { + if (listeners[i].fn === fn && listeners[i].ctx === context) { + return; + } + } + + listeners.push(newListener); + }, + + _off: function (type, fn, context) { + var listeners, + i, + len; + + if (!this._events) { return; } + + listeners = this._events[type]; + + if (!listeners) { + return; + } + + if (!fn) { + // Set all removed listeners to noop so they are not called if remove happens in fire + for (i = 0, len = listeners.length; i < len; i++) { + listeners[i].fn = Util.falseFn; + } + // clear all listeners for a type if function isn't specified + delete this._events[type]; + return; + } + + if (context === this) { + context = undefined; + } + + if (listeners) { + + // find fn and remove it + for (i = 0, len = listeners.length; i < len; i++) { + var l = listeners[i]; + if (l.ctx !== context) { continue; } + if (l.fn === fn) { + + // set the removed listener to noop so that's not called if remove happens in fire + l.fn = Util.falseFn; + + if (this._firingCount) { + /* copy array in case events are being fired */ + this._events[type] = listeners = listeners.slice(); + } + listeners.splice(i, 1); + + return; + } + } + } + }, + + // @method fire(type: String, data?: Object, propagate?: Boolean): this + // Fires an event of the specified type. You can optionally provide an data + // object — the first argument of the listener function will contain its + // properties. The event can optionally be propagated to event parents. + fire: function (type, data, propagate) { + if (!this.listens(type, propagate)) { return this; } + + var event = Util.extend({}, data, { + type: type, + target: this, + sourceTarget: data && data.sourceTarget || this + }); + + if (this._events) { + var listeners = this._events[type]; + + if (listeners) { + this._firingCount = (this._firingCount + 1) || 1; + for (var i = 0, len = listeners.length; i < len; i++) { + var l = listeners[i]; + l.fn.call(l.ctx || this, event); + } + + this._firingCount--; + } + } + + if (propagate) { + // propagate the event to parents (set with addEventParent) + this._propagateEvent(event); + } + + return this; + }, + + // @method listens(type: String): Boolean + // Returns `true` if a particular event type has any listeners attached to it. + listens: function (type, propagate) { + var listeners = this._events && this._events[type]; + if (listeners && listeners.length) { return true; } + + if (propagate) { + // also check parents for listeners if event propagates + for (var id in this._eventParents) { + if (this._eventParents[id].listens(type, propagate)) { return true; } + } + } + return false; + }, + + // @method once(…): this + // Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed. + once: function (types, fn, context) { + + if (typeof types === 'object') { + for (var type in types) { + this.once(type, types[type], fn); + } + return this; + } + + var handler = Util.bind(function () { + this + .off(types, fn, context) + .off(types, handler, context); + }, this); + + // add a listener that's executed once and removed after that + return this + .on(types, fn, context) + .on(types, handler, context); + }, + + // @method addEventParent(obj: Evented): this + // Adds an event parent - an `Evented` that will receive propagated events + addEventParent: function (obj) { + this._eventParents = this._eventParents || {}; + this._eventParents[Util.stamp(obj)] = obj; + return this; + }, + + // @method removeEventParent(obj: Evented): this + // Removes an event parent, so it will stop receiving propagated events + removeEventParent: function (obj) { + if (this._eventParents) { + delete this._eventParents[Util.stamp(obj)]; + } + return this; + }, + + _propagateEvent: function (e) { + for (var id in this._eventParents) { + this._eventParents[id].fire(e.type, Util.extend({ + layer: e.target, + propagatedFrom: e.target + }, e), true); + } + } +}; + +// aliases; we should ditch those eventually + +// @method addEventListener(…): this +// Alias to [`on(…)`](#evented-on) +Events.addEventListener = Events.on; + +// @method removeEventListener(…): this +// Alias to [`off(…)`](#evented-off) + +// @method clearAllEventListeners(…): this +// Alias to [`off()`](#evented-off) +Events.removeEventListener = Events.clearAllEventListeners = Events.off; + +// @method addOneTimeEventListener(…): this +// Alias to [`once(…)`](#evented-once) +Events.addOneTimeEventListener = Events.once; + +// @method fireEvent(…): this +// Alias to [`fire(…)`](#evented-fire) +Events.fireEvent = Events.fire; + +// @method hasEventListeners(…): Boolean +// Alias to [`listens(…)`](#evented-listens) +Events.hasEventListeners = Events.listens; + +export var Evented = Class.extend(Events); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Events.leafdoc b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Events.leafdoc new file mode 100644 index 000000000..f5142e197 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Events.leafdoc @@ -0,0 +1,143 @@ + +@namespace Event objects + + +Whenever a class inheriting from `Evented` fires an event, a listener function +will be called with an event argument, which is a plain object containing +information about the event. For example: + +```js +map.on('click', function(ev) { + alert(ev.latlng); // ev is an event object (MouseEvent in this case) +}); +``` + +The information available depends on the event type: + + +@miniclass Event (Event objects) +@section +The base event object. All other event objects contain these properties too. +@property type: String +The event type (e.g. `'click'`). +@property target: Object +The object that fired the event. For propagated events, the last object in +the propagation chain that fired the event. +@property sourceTarget: Object +The object that originally fired the event. For non-propagated events, this will +be the same as the `target`. +@property propagatedFrom: Object +For propagated events, the last object that propagated the event to its +event parent. +@property layer: Object +**Deprecated.** The same as `propagatedFrom`. + + +@miniclass KeyboardEvent (Event objects) +@inherits Event +@property originalEvent: DOMEvent +The original [DOM `KeyboardEvent`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) that triggered this Leaflet event. + +@miniclass MouseEvent (Event objects) +@inherits Event +@property latlng: LatLng +The geographical point where the mouse event occured. +@property layerPoint: Point +Pixel coordinates of the point where the mouse event occured relative to the map layer. +@property containerPoint: Point +Pixel coordinates of the point where the mouse event occured relative to the map сontainer. +@property originalEvent: DOMEvent +The original [DOM `MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) or [DOM `TouchEvent`](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) that triggered this Leaflet event. + +@miniclass LocationEvent (Event objects) +@inherits Event +@property latlng: LatLng +Detected geographical location of the user. +@property bounds: LatLngBounds +Geographical bounds of the area user is located in (with respect to the accuracy of location). +@property accuracy: Number +Accuracy of location in meters. +@property altitude: Number +Height of the position above the WGS84 ellipsoid in meters. +@property altitudeAccuracy: Number +Accuracy of altitude in meters. +@property heading: Number +The direction of travel in degrees counting clockwise from true North. +@property speed: Number +Current velocity in meters per second. +@property timestamp: Number +The time when the position was acquired. + +@miniclass ErrorEvent (Event objects) +@inherits Event +@property message: String +Error message. +@property code: Number +Error code (if applicable). + +@miniclass LayerEvent (Event objects) +@inherits Event +@property layer: Layer +The layer that was added or removed. + +@miniclass LayersControlEvent (Event objects) +@inherits Event +@property layer: Layer +The layer that was added or removed. +@property name: String +The name of the layer that was added or removed. + +@miniclass TileEvent (Event objects) +@inherits Event +@property tile: HTMLElement +The tile element (image). +@property coords: Point +Point object with the tile's `x`, `y`, and `z` (zoom level) coordinates. + +@miniclass TileErrorEvent (Event objects) +@inherits Event +@property tile: HTMLElement +The tile element (image). +@property coords: Point +Point object with the tile's `x`, `y`, and `z` (zoom level) coordinates. +@property error: * +Error passed to the tile's `done()` callback. + +@miniclass ResizeEvent (Event objects) +@inherits Event +@property oldSize: Point +The old size before resize event. +@property newSize: Point +The new size after the resize event. + +@miniclass GeoJSONEvent (Event objects) +@inherits Event +@property layer: Layer +The layer for the GeoJSON feature that is being added to the map. +@property properties: Object +GeoJSON properties of the feature. +@property geometryType: String +GeoJSON geometry type of the feature. +@property id: String +GeoJSON ID of the feature (if present). + +@miniclass PopupEvent (Event objects) +@inherits Event +@property popup: Popup +The popup that was opened or closed. + +@miniclass TooltipEvent (Event objects) +@inherits Event +@property tooltip: Tooltip +The tooltip that was opened or closed. + +@miniclass DragEndEvent (Event objects) +@inherits Event +@property distance: Number +The distance in pixels the draggable element was moved by. + +@miniclass ZoomAnimEvent (Event objects) +@inherits Event +@property center: LatLng; The current center of the map +@property zoom: Number; The current zoom level of the map +@property noUpdate: Boolean; Whether layers should update their contents due to this event diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Handler.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Handler.js new file mode 100644 index 000000000..8ad639b3a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Handler.js @@ -0,0 +1,57 @@ +import {Class} from './Class'; + +/* + L.Handler is a base class for handler classes that are used internally to inject + interaction features like dragging to classes like Map and Marker. +*/ + +// @class Handler +// @aka L.Handler +// Abstract class for map interaction handlers + +export var Handler = Class.extend({ + initialize: function (map) { + this._map = map; + }, + + // @method enable(): this + // Enables the handler + enable: function () { + if (this._enabled) { return this; } + + this._enabled = true; + this.addHooks(); + return this; + }, + + // @method disable(): this + // Disables the handler + disable: function () { + if (!this._enabled) { return this; } + + this._enabled = false; + this.removeHooks(); + return this; + }, + + // @method enabled(): Boolean + // Returns `true` if the handler is enabled + enabled: function () { + return !!this._enabled; + } + + // @section Extension methods + // Classes inheriting from `Handler` must implement the two following methods: + // @method addHooks() + // Called when the handler is enabled, should add event hooks. + // @method removeHooks() + // Called when the handler is disabled, should remove the event hooks added previously. +}); + +// @section There is static function which can be called without instantiating L.Handler: +// @function addTo(map: Map, name: String): this +// Adds a new Handler to the given map with the given name. +Handler.addTo = function (map, name) { + map.addHandler(name, this); + return this; +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Util.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Util.js new file mode 100644 index 000000000..f3d22ece0 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/Util.js @@ -0,0 +1,241 @@ +/* + * @namespace Util + * + * Various utility functions, used by Leaflet internally. + */ + +export var freeze = Object.freeze; +Object.freeze = function (obj) { return obj; }; + +// @function extend(dest: Object, src?: Object): Object +// Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut. +export function extend(dest) { + var i, j, len, src; + + for (j = 1, len = arguments.length; j < len; j++) { + src = arguments[j]; + for (i in src) { + dest[i] = src[i]; + } + } + return dest; +} + +// @function create(proto: Object, properties?: Object): Object +// Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create) +export var create = Object.create || (function () { + function F() {} + return function (proto) { + F.prototype = proto; + return new F(); + }; +})(); + +// @function bind(fn: Function, …): Function +// Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). +// Has a `L.bind()` shortcut. +export function bind(fn, obj) { + var slice = Array.prototype.slice; + + if (fn.bind) { + return fn.bind.apply(fn, slice.call(arguments, 1)); + } + + var args = slice.call(arguments, 2); + + return function () { + return fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments); + }; +} + +// @property lastId: Number +// Last unique ID used by [`stamp()`](#util-stamp) +export var lastId = 0; + +// @function stamp(obj: Object): Number +// Returns the unique ID of an object, assigning it one if it doesn't have it. +export function stamp(obj) { + /*eslint-disable */ + obj._leaflet_id = obj._leaflet_id || ++lastId; + return obj._leaflet_id; + /* eslint-enable */ +} + +// @function throttle(fn: Function, time: Number, context: Object): Function +// Returns a function which executes function `fn` with the given scope `context` +// (so that the `this` keyword refers to `context` inside `fn`'s code). The function +// `fn` will be called no more than one time per given amount of `time`. The arguments +// received by the bound function will be any arguments passed when binding the +// function, followed by any arguments passed when invoking the bound function. +// Has an `L.throttle` shortcut. +export function throttle(fn, time, context) { + var lock, args, wrapperFn, later; + + later = function () { + // reset lock and call if queued + lock = false; + if (args) { + wrapperFn.apply(context, args); + args = false; + } + }; + + wrapperFn = function () { + if (lock) { + // called too soon, queue to call later + args = arguments; + + } else { + // call and lock until later + fn.apply(context, arguments); + setTimeout(later, time); + lock = true; + } + }; + + return wrapperFn; +} + +// @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number +// Returns the number `num` modulo `range` in such a way so it lies within +// `range[0]` and `range[1]`. The returned value will be always smaller than +// `range[1]` unless `includeMax` is set to `true`. +export function wrapNum(x, range, includeMax) { + var max = range[1], + min = range[0], + d = max - min; + return x === max && includeMax ? x : ((x - min) % d + d) % d + min; +} + +// @function falseFn(): Function +// Returns a function which always returns `false`. +export function falseFn() { return false; } + +// @function formatNum(num: Number, digits?: Number): Number +// Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default. +export function formatNum(num, digits) { + var pow = Math.pow(10, (digits === undefined ? 6 : digits)); + return Math.round(num * pow) / pow; +} + +// @function trim(str: String): String +// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim) +export function trim(str) { + return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, ''); +} + +// @function splitWords(str: String): String[] +// Trims and splits the string on whitespace and returns the array of parts. +export function splitWords(str) { + return trim(str).split(/\s+/); +} + +// @function setOptions(obj: Object, options: Object): Object +// Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut. +export function setOptions(obj, options) { + if (!obj.hasOwnProperty('options')) { + obj.options = obj.options ? create(obj.options) : {}; + } + for (var i in options) { + obj.options[i] = options[i]; + } + return obj.options; +} + +// @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String +// Converts an object into a parameter URL string, e.g. `{a: "foo", b: "bar"}` +// translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will +// be appended at the end. If `uppercase` is `true`, the parameter names will +// be uppercased (e.g. `'?A=foo&B=bar'`) +export function getParamString(obj, existingUrl, uppercase) { + var params = []; + for (var i in obj) { + params.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i])); + } + return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&'); +} + +var templateRe = /\{ *([\w_-]+) *\}/g; + +// @function template(str: String, data: Object): String +// Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'` +// and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string +// `('Hello foo, bar')`. You can also specify functions instead of strings for +// data values — they will be evaluated passing `data` as an argument. +export function template(str, data) { + return str.replace(templateRe, function (str, key) { + var value = data[key]; + + if (value === undefined) { + throw new Error('No value provided for variable ' + str); + + } else if (typeof value === 'function') { + value = value(data); + } + return value; + }); +} + +// @function isArray(obj): Boolean +// Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) +export var isArray = Array.isArray || function (obj) { + return (Object.prototype.toString.call(obj) === '[object Array]'); +}; + +// @function indexOf(array: Array, el: Object): Number +// Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) +export function indexOf(array, el) { + for (var i = 0; i < array.length; i++) { + if (array[i] === el) { return i; } + } + return -1; +} + +// @property emptyImageUrl: String +// Data URI string containing a base64-encoded empty GIF image. +// Used as a hack to free memory from unused images on WebKit-powered +// mobile devices (by setting image `src` to this string). +export var emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; + +// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + +function getPrefixed(name) { + return window['webkit' + name] || window['moz' + name] || window['ms' + name]; +} + +var lastTime = 0; + +// fallback for IE 7-8 +function timeoutDefer(fn) { + var time = +new Date(), + timeToCall = Math.max(0, 16 - (time - lastTime)); + + lastTime = time + timeToCall; + return window.setTimeout(fn, timeToCall); +} + +export var requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer; +export var cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') || + getPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); }; + +// @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number +// Schedules `fn` to be executed when the browser repaints. `fn` is bound to +// `context` if given. When `immediate` is set, `fn` is called immediately if +// the browser doesn't have native support for +// [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame), +// otherwise it's delayed. Returns a request ID that can be used to cancel the request. +export function requestAnimFrame(fn, context, immediate) { + if (immediate && requestFn === timeoutDefer) { + fn.call(context); + } else { + return requestFn.call(window, bind(fn, context)); + } +} + +// @function cancelAnimFrame(id: Number): undefined +// Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame). +export function cancelAnimFrame(id) { + if (id) { + cancelFn.call(window, id); + } +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/core/index.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/index.js new file mode 100644 index 000000000..ae9297d4a --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/core/index.js @@ -0,0 +1,15 @@ +import * as Browser from './Browser'; +export {Browser}; + +export {Class} from './Class'; + +import {Evented} from './Events'; +import {Events} from './Events'; +export {Evented}; +export var Mixin = {Events: Events}; + +export {Handler} from './Handler'; + +import * as Util from './Util'; +export {Util}; +export {extend, bind, stamp, setOptions} from './Util'; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.DoubleTap.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.DoubleTap.js new file mode 100644 index 000000000..a5fb25de6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.DoubleTap.js @@ -0,0 +1,86 @@ +import * as Browser from '../core/Browser'; +import {_pointersCount} from './DomEvent.Pointer'; + +/* + * Extends the event handling code with double tap support for mobile browsers. + */ + +var _touchstart = Browser.msPointer ? 'MSPointerDown' : Browser.pointer ? 'pointerdown' : 'touchstart'; +var _touchend = Browser.msPointer ? 'MSPointerUp' : Browser.pointer ? 'pointerup' : 'touchend'; +var _pre = '_leaflet_'; + +// inspired by Zepto touch code by Thomas Fuchs +export function addDoubleTapListener(obj, handler, id) { + var last, touch, + doubleTap = false, + delay = 250; + + function onTouchStart(e) { + var count; + + if (Browser.pointer) { + if ((!Browser.edge) || e.pointerType === 'mouse') { return; } + count = _pointersCount; + } else { + count = e.touches.length; + } + + if (count > 1) { return; } + + var now = Date.now(), + delta = now - (last || now); + + touch = e.touches ? e.touches[0] : e; + doubleTap = (delta > 0 && delta <= delay); + last = now; + } + + function onTouchEnd(e) { + if (doubleTap && !touch.cancelBubble) { + if (Browser.pointer) { + if ((!Browser.edge) || e.pointerType === 'mouse') { return; } + // work around .type being readonly with MSPointer* events + var newTouch = {}, + prop, i; + + for (i in touch) { + prop = touch[i]; + newTouch[i] = prop && prop.bind ? prop.bind(touch) : prop; + } + touch = newTouch; + } + touch.type = 'dblclick'; + handler(touch); + last = null; + } + } + + obj[_pre + _touchstart + id] = onTouchStart; + obj[_pre + _touchend + id] = onTouchEnd; + obj[_pre + 'dblclick' + id] = handler; + + obj.addEventListener(_touchstart, onTouchStart, false); + obj.addEventListener(_touchend, onTouchEnd, false); + + // On some platforms (notably, chrome<55 on win10 + touchscreen + mouse), + // the browser doesn't fire touchend/pointerup events but does fire + // native dblclicks. See #4127. + // Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180. + obj.addEventListener('dblclick', handler, false); + + return this; +} + +export function removeDoubleTapListener(obj, id) { + var touchstart = obj[_pre + _touchstart + id], + touchend = obj[_pre + _touchend + id], + dblclick = obj[_pre + 'dblclick' + id]; + + obj.removeEventListener(_touchstart, touchstart, false); + obj.removeEventListener(_touchend, touchend, false); + if (!Browser.edge) { + obj.removeEventListener('dblclick', dblclick, false); + } + + return this; +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.Pointer.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.Pointer.js new file mode 100644 index 000000000..e25703a01 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.Pointer.js @@ -0,0 +1,134 @@ +import * as DomEvent from './DomEvent'; +import * as Util from '../core/Util'; +import * as Browser from '../core/Browser'; + +/* + * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. + */ + + +var POINTER_DOWN = Browser.msPointer ? 'MSPointerDown' : 'pointerdown'; +var POINTER_MOVE = Browser.msPointer ? 'MSPointerMove' : 'pointermove'; +var POINTER_UP = Browser.msPointer ? 'MSPointerUp' : 'pointerup'; +var POINTER_CANCEL = Browser.msPointer ? 'MSPointerCancel' : 'pointercancel'; +var TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION']; + +var _pointers = {}; +var _pointerDocListener = false; + +// DomEvent.DoubleTap needs to know about this +export var _pointersCount = 0; + +// Provides a touch events wrapper for (ms)pointer events. +// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 + +export function addPointerListener(obj, type, handler, id) { + if (type === 'touchstart') { + _addPointerStart(obj, handler, id); + + } else if (type === 'touchmove') { + _addPointerMove(obj, handler, id); + + } else if (type === 'touchend') { + _addPointerEnd(obj, handler, id); + } + + return this; +} + +export function removePointerListener(obj, type, id) { + var handler = obj['_leaflet_' + type + id]; + + if (type === 'touchstart') { + obj.removeEventListener(POINTER_DOWN, handler, false); + + } else if (type === 'touchmove') { + obj.removeEventListener(POINTER_MOVE, handler, false); + + } else if (type === 'touchend') { + obj.removeEventListener(POINTER_UP, handler, false); + obj.removeEventListener(POINTER_CANCEL, handler, false); + } + + return this; +} + +function _addPointerStart(obj, handler, id) { + var onDown = Util.bind(function (e) { + if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { + // In IE11, some touch events needs to fire for form controls, or + // the controls will stop working. We keep a whitelist of tag names that + // need these events. For other target tags, we prevent default on the event. + if (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) { + DomEvent.preventDefault(e); + } else { + return; + } + } + + _handlePointer(e, handler); + }); + + obj['_leaflet_touchstart' + id] = onDown; + obj.addEventListener(POINTER_DOWN, onDown, false); + + // need to keep track of what pointers and how many are active to provide e.touches emulation + if (!_pointerDocListener) { + // we listen documentElement as any drags that end by moving the touch off the screen get fired there + document.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true); + document.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true); + document.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true); + document.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true); + + _pointerDocListener = true; + } +} + +function _globalPointerDown(e) { + _pointers[e.pointerId] = e; + _pointersCount++; +} + +function _globalPointerMove(e) { + if (_pointers[e.pointerId]) { + _pointers[e.pointerId] = e; + } +} + +function _globalPointerUp(e) { + delete _pointers[e.pointerId]; + _pointersCount--; +} + +function _handlePointer(e, handler) { + e.touches = []; + for (var i in _pointers) { + e.touches.push(_pointers[i]); + } + e.changedTouches = [e]; + + handler(e); +} + +function _addPointerMove(obj, handler, id) { + var onMove = function (e) { + // don't fire touch moves when mouse isn't down + if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } + + _handlePointer(e, handler); + }; + + obj['_leaflet_touchmove' + id] = onMove; + obj.addEventListener(POINTER_MOVE, onMove, false); +} + +function _addPointerEnd(obj, handler, id) { + var onUp = function (e) { + _handlePointer(e, handler); + }; + + obj['_leaflet_touchend' + id] = onUp; + obj.addEventListener(POINTER_UP, onUp, false); + obj.addEventListener(POINTER_CANCEL, onUp, false); +} + diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.js new file mode 100644 index 000000000..4eab15508 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomEvent.js @@ -0,0 +1,316 @@ +import {Point} from '../geometry/Point'; +import * as Util from '../core/Util'; +import * as Browser from '../core/Browser'; +import {addPointerListener, removePointerListener} from './DomEvent.Pointer'; +import {addDoubleTapListener, removeDoubleTapListener} from './DomEvent.DoubleTap'; +import {getScale} from './DomUtil'; + +/* + * @namespace DomEvent + * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally. + */ + +// Inspired by John Resig, Dean Edwards and YUI addEvent implementations. + +// @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this +// Adds a listener function (`fn`) to a particular DOM event type of the +// element `el`. You can optionally specify the context of the listener +// (object the `this` keyword will point to). You can also pass several +// space-separated types (e.g. `'click dblclick'`). + +// @alternative +// @function on(el: HTMLElement, eventMap: Object, context?: Object): this +// Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` +export function on(obj, types, fn, context) { + + if (typeof types === 'object') { + for (var type in types) { + addOne(obj, type, types[type], fn); + } + } else { + types = Util.splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + addOne(obj, types[i], fn, context); + } + } + + return this; +} + +var eventsKey = '_leaflet_events'; + +// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this +// Removes a previously added listener function. +// Note that if you passed a custom context to on, you must pass the same +// context to `off` in order to remove the listener. + +// @alternative +// @function off(el: HTMLElement, eventMap: Object, context?: Object): this +// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}` +export function off(obj, types, fn, context) { + + if (typeof types === 'object') { + for (var type in types) { + removeOne(obj, type, types[type], fn); + } + } else if (types) { + types = Util.splitWords(types); + + for (var i = 0, len = types.length; i < len; i++) { + removeOne(obj, types[i], fn, context); + } + } else { + for (var j in obj[eventsKey]) { + removeOne(obj, j, obj[eventsKey][j]); + } + delete obj[eventsKey]; + } + + return this; +} + +function addOne(obj, type, fn, context) { + var id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : ''); + + if (obj[eventsKey] && obj[eventsKey][id]) { return this; } + + var handler = function (e) { + return fn.call(context || obj, e || window.event); + }; + + var originalHandler = handler; + + if (Browser.pointer && type.indexOf('touch') === 0) { + // Needs DomEvent.Pointer.js + addPointerListener(obj, type, handler, id); + + } else if (Browser.touch && (type === 'dblclick') && addDoubleTapListener && + !(Browser.pointer && Browser.chrome)) { + // Chrome >55 does not need the synthetic dblclicks from addDoubleTapListener + // See #5180 + addDoubleTapListener(obj, handler, id); + + } else if ('addEventListener' in obj) { + + if (type === 'mousewheel') { + obj.addEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false); + + } else if ((type === 'mouseenter') || (type === 'mouseleave')) { + handler = function (e) { + e = e || window.event; + if (isExternalTarget(obj, e)) { + originalHandler(e); + } + }; + obj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false); + + } else { + if (type === 'click' && Browser.android) { + handler = function (e) { + filterClick(e, originalHandler); + }; + } + obj.addEventListener(type, handler, false); + } + + } else if ('attachEvent' in obj) { + obj.attachEvent('on' + type, handler); + } + + obj[eventsKey] = obj[eventsKey] || {}; + obj[eventsKey][id] = handler; +} + +function removeOne(obj, type, fn, context) { + + var id = type + Util.stamp(fn) + (context ? '_' + Util.stamp(context) : ''), + handler = obj[eventsKey] && obj[eventsKey][id]; + + if (!handler) { return this; } + + if (Browser.pointer && type.indexOf('touch') === 0) { + removePointerListener(obj, type, id); + + } else if (Browser.touch && (type === 'dblclick') && removeDoubleTapListener && + !(Browser.pointer && Browser.chrome)) { + removeDoubleTapListener(obj, id); + + } else if ('removeEventListener' in obj) { + + if (type === 'mousewheel') { + obj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false); + + } else { + obj.removeEventListener( + type === 'mouseenter' ? 'mouseover' : + type === 'mouseleave' ? 'mouseout' : type, handler, false); + } + + } else if ('detachEvent' in obj) { + obj.detachEvent('on' + type, handler); + } + + obj[eventsKey][id] = null; +} + +// @function stopPropagation(ev: DOMEvent): this +// Stop the given event from propagation to parent elements. Used inside the listener functions: +// ```js +// L.DomEvent.on(div, 'click', function (ev) { +// L.DomEvent.stopPropagation(ev); +// }); +// ``` +export function stopPropagation(e) { + + if (e.stopPropagation) { + e.stopPropagation(); + } else if (e.originalEvent) { // In case of Leaflet event. + e.originalEvent._stopped = true; + } else { + e.cancelBubble = true; + } + skipped(e); + + return this; +} + +// @function disableScrollPropagation(el: HTMLElement): this +// Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants). +export function disableScrollPropagation(el) { + addOne(el, 'mousewheel', stopPropagation); + return this; +} + +// @function disableClickPropagation(el: HTMLElement): this +// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`, +// `'mousedown'` and `'touchstart'` events (plus browser variants). +export function disableClickPropagation(el) { + on(el, 'mousedown touchstart dblclick', stopPropagation); + addOne(el, 'click', fakeStop); + return this; +} + +// @function preventDefault(ev: DOMEvent): this +// Prevents the default action of the DOM Event `ev` from happening (such as +// following a link in the href of the a element, or doing a POST request +// with page reload when a `
` is submitted). +// Use it inside listener functions. +export function preventDefault(e) { + if (e.preventDefault) { + e.preventDefault(); + } else { + e.returnValue = false; + } + return this; +} + +// @function stop(ev: DOMEvent): this +// Does `stopPropagation` and `preventDefault` at the same time. +export function stop(e) { + preventDefault(e); + stopPropagation(e); + return this; +} + +// @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point +// Gets normalized mouse position from a DOM event relative to the +// `container` (border excluded) or to the whole page if not specified. +export function getMousePosition(e, container) { + if (!container) { + return new Point(e.clientX, e.clientY); + } + + var scale = getScale(container), + offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y) + + return new Point( + // offset.left/top values are in page scale (like clientX/Y), + // whereas clientLeft/Top (border width) values are the original values (before CSS scale applies). + (e.clientX - offset.left) / scale.x - container.clientLeft, + (e.clientY - offset.top) / scale.y - container.clientTop + ); +} + +// Chrome on Win scrolls double the pixels as in other platforms (see #4538), +// and Firefox scrolls device pixels, not CSS pixels +var wheelPxFactor = + (Browser.win && Browser.chrome) ? 2 * window.devicePixelRatio : + Browser.gecko ? window.devicePixelRatio : 1; + +// @function getWheelDelta(ev: DOMEvent): Number +// Gets normalized wheel delta from a mousewheel DOM event, in vertical +// pixels scrolled (negative if scrolling down). +// Events from pointing devices without precise scrolling are mapped to +// a best guess of 60 pixels. +export function getWheelDelta(e) { + return (Browser.edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta + (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels + (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines + (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages + (e.deltaX || e.deltaZ) ? 0 : // Skip horizontal/depth wheel events + e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels + (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines + e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages + 0; +} + +var skipEvents = {}; + +export function fakeStop(e) { + // fakes stopPropagation by setting a special event flag, checked/reset with skipped(e) + skipEvents[e.type] = true; +} + +export function skipped(e) { + var events = skipEvents[e.type]; + // reset when checking, as it's only used in map container and propagates outside of the map + skipEvents[e.type] = false; + return events; +} + +// check if element really left/entered the event target (for mouseenter/mouseleave) +export function isExternalTarget(el, e) { + + var related = e.relatedTarget; + + if (!related) { return true; } + + try { + while (related && (related !== el)) { + related = related.parentNode; + } + } catch (err) { + return false; + } + return (related !== el); +} + +var lastClick; + +// this is a horrible workaround for a bug in Android where a single touch triggers two click events +function filterClick(e, handler) { + var timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)), + elapsed = lastClick && (timeStamp - lastClick); + + // are they closer together than 500ms yet more than 100ms? + // Android typically triggers them ~300ms apart while multiple listeners + // on the same event should be triggered far faster; + // or check if click is simulated on the element, and if it is, reject any non-simulated events + + if ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) { + stop(e); + return; + } + lastClick = timeStamp; + + handler(e); +} + +// @function addListener(…): this +// Alias to [`L.DomEvent.on`](#domevent-on) +export {on as addListener}; + +// @function removeListener(…): this +// Alias to [`L.DomEvent.off`](#domevent-off) +export {off as removeListener}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomUtil.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomUtil.js new file mode 100644 index 000000000..aabcef31b --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/DomUtil.js @@ -0,0 +1,349 @@ +import * as DomEvent from './DomEvent'; +import * as Util from '../core/Util'; +import {Point} from '../geometry/Point'; +import * as Browser from '../core/Browser'; + +/* + * @namespace DomUtil + * + * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model) + * tree, used by Leaflet internally. + * + * Most functions expecting or returning a `HTMLElement` also work for + * SVG elements. The only difference is that classes refer to CSS classes + * in HTML and SVG classes in SVG. + */ + + +// @property TRANSFORM: String +// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit). +export var TRANSFORM = testProp( + ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']); + +// webkitTransition comes first because some browser versions that drop vendor prefix don't do +// the same for the transitionend event, in particular the Android 4.1 stock browser + +// @property TRANSITION: String +// Vendor-prefixed transition style name. +export var TRANSITION = testProp( + ['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']); + +// @property TRANSITION_END: String +// Vendor-prefixed transitionend event name. +export var TRANSITION_END = + TRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend'; + + +// @function get(id: String|HTMLElement): HTMLElement +// Returns an element given its DOM id, or returns the element itself +// if it was passed directly. +export function get(id) { + return typeof id === 'string' ? document.getElementById(id) : id; +} + +// @function getStyle(el: HTMLElement, styleAttrib: String): String +// Returns the value for a certain style attribute on an element, +// including computed values or values set through CSS. +export function getStyle(el, style) { + var value = el.style[style] || (el.currentStyle && el.currentStyle[style]); + + if ((!value || value === 'auto') && document.defaultView) { + var css = document.defaultView.getComputedStyle(el, null); + value = css ? css[style] : null; + } + return value === 'auto' ? null : value; +} + +// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement +// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element. +export function create(tagName, className, container) { + var el = document.createElement(tagName); + el.className = className || ''; + + if (container) { + container.appendChild(el); + } + return el; +} + +// @function remove(el: HTMLElement) +// Removes `el` from its parent element +export function remove(el) { + var parent = el.parentNode; + if (parent) { + parent.removeChild(el); + } +} + +// @function empty(el: HTMLElement) +// Removes all of `el`'s children elements from `el` +export function empty(el) { + while (el.firstChild) { + el.removeChild(el.firstChild); + } +} + +// @function toFront(el: HTMLElement) +// Makes `el` the last child of its parent, so it renders in front of the other children. +export function toFront(el) { + var parent = el.parentNode; + if (parent && parent.lastChild !== el) { + parent.appendChild(el); + } +} + +// @function toBack(el: HTMLElement) +// Makes `el` the first child of its parent, so it renders behind the other children. +export function toBack(el) { + var parent = el.parentNode; + if (parent && parent.firstChild !== el) { + parent.insertBefore(el, parent.firstChild); + } +} + +// @function hasClass(el: HTMLElement, name: String): Boolean +// Returns `true` if the element's class attribute contains `name`. +export function hasClass(el, name) { + if (el.classList !== undefined) { + return el.classList.contains(name); + } + var className = getClass(el); + return className.length > 0 && new RegExp('(^|\\s)' + name + '(\\s|$)').test(className); +} + +// @function addClass(el: HTMLElement, name: String) +// Adds `name` to the element's class attribute. +export function addClass(el, name) { + if (el.classList !== undefined) { + var classes = Util.splitWords(name); + for (var i = 0, len = classes.length; i < len; i++) { + el.classList.add(classes[i]); + } + } else if (!hasClass(el, name)) { + var className = getClass(el); + setClass(el, (className ? className + ' ' : '') + name); + } +} + +// @function removeClass(el: HTMLElement, name: String) +// Removes `name` from the element's class attribute. +export function removeClass(el, name) { + if (el.classList !== undefined) { + el.classList.remove(name); + } else { + setClass(el, Util.trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' '))); + } +} + +// @function setClass(el: HTMLElement, name: String) +// Sets the element's class. +export function setClass(el, name) { + if (el.className.baseVal === undefined) { + el.className = name; + } else { + // in case of SVG element + el.className.baseVal = name; + } +} + +// @function getClass(el: HTMLElement): String +// Returns the element's class. +export function getClass(el) { + // Check if the element is an SVGElementInstance and use the correspondingElement instead + // (Required for linked SVG elements in IE11.) + if (el.correspondingElement) { + el = el.correspondingElement; + } + return el.className.baseVal === undefined ? el.className : el.className.baseVal; +} + +// @function setOpacity(el: HTMLElement, opacity: Number) +// Set the opacity of an element (including old IE support). +// `opacity` must be a number from `0` to `1`. +export function setOpacity(el, value) { + if ('opacity' in el.style) { + el.style.opacity = value; + } else if ('filter' in el.style) { + _setOpacityIE(el, value); + } +} + +function _setOpacityIE(el, value) { + var filter = false, + filterName = 'DXImageTransform.Microsoft.Alpha'; + + // filters collection throws an error if we try to retrieve a filter that doesn't exist + try { + filter = el.filters.item(filterName); + } catch (e) { + // don't set opacity to 1 if we haven't already set an opacity, + // it isn't needed and breaks transparent pngs. + if (value === 1) { return; } + } + + value = Math.round(value * 100); + + if (filter) { + filter.Enabled = (value !== 100); + filter.Opacity = value; + } else { + el.style.filter += ' progid:' + filterName + '(opacity=' + value + ')'; + } +} + +// @function testProp(props: String[]): String|false +// Goes through the array of style names and returns the first name +// that is a valid style name for an element. If no such name is found, +// it returns false. Useful for vendor-prefixed styles like `transform`. +export function testProp(props) { + var style = document.documentElement.style; + + for (var i = 0; i < props.length; i++) { + if (props[i] in style) { + return props[i]; + } + } + return false; +} + +// @function setTransform(el: HTMLElement, offset: Point, scale?: Number) +// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels +// and optionally scaled by `scale`. Does not have an effect if the +// browser doesn't support 3D CSS transforms. +export function setTransform(el, offset, scale) { + var pos = offset || new Point(0, 0); + + el.style[TRANSFORM] = + (Browser.ie3d ? + 'translate(' + pos.x + 'px,' + pos.y + 'px)' : + 'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') + + (scale ? ' scale(' + scale + ')' : ''); +} + +// @function setPosition(el: HTMLElement, position: Point) +// Sets the position of `el` to coordinates specified by `position`, +// using CSS translate or top/left positioning depending on the browser +// (used by Leaflet internally to position its layers). +export function setPosition(el, point) { + + /*eslint-disable */ + el._leaflet_pos = point; + /* eslint-enable */ + + if (Browser.any3d) { + setTransform(el, point); + } else { + el.style.left = point.x + 'px'; + el.style.top = point.y + 'px'; + } +} + +// @function getPosition(el: HTMLElement): Point +// Returns the coordinates of an element previously positioned with setPosition. +export function getPosition(el) { + // this method is only used for elements previously positioned using setPosition, + // so it's safe to cache the position for performance + + return el._leaflet_pos || new Point(0, 0); +} + +// @function disableTextSelection() +// Prevents the user from generating `selectstart` DOM events, usually generated +// when the user drags the mouse through a page with text. Used internally +// by Leaflet to override the behaviour of any click-and-drag interaction on +// the map. Affects drag interactions on the whole document. + +// @function enableTextSelection() +// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection). +export var disableTextSelection; +export var enableTextSelection; +var _userSelect; +if ('onselectstart' in document) { + disableTextSelection = function () { + DomEvent.on(window, 'selectstart', DomEvent.preventDefault); + }; + enableTextSelection = function () { + DomEvent.off(window, 'selectstart', DomEvent.preventDefault); + }; +} else { + var userSelectProperty = testProp( + ['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']); + + disableTextSelection = function () { + if (userSelectProperty) { + var style = document.documentElement.style; + _userSelect = style[userSelectProperty]; + style[userSelectProperty] = 'none'; + } + }; + enableTextSelection = function () { + if (userSelectProperty) { + document.documentElement.style[userSelectProperty] = _userSelect; + _userSelect = undefined; + } + }; +} + +// @function disableImageDrag() +// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but +// for `dragstart` DOM events, usually generated when the user drags an image. +export function disableImageDrag() { + DomEvent.on(window, 'dragstart', DomEvent.preventDefault); +} + +// @function enableImageDrag() +// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection). +export function enableImageDrag() { + DomEvent.off(window, 'dragstart', DomEvent.preventDefault); +} + +var _outlineElement, _outlineStyle; +// @function preventOutline(el: HTMLElement) +// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline) +// of the element `el` invisible. Used internally by Leaflet to prevent +// focusable elements from displaying an outline when the user performs a +// drag interaction on them. +export function preventOutline(element) { + while (element.tabIndex === -1) { + element = element.parentNode; + } + if (!element.style) { return; } + restoreOutline(); + _outlineElement = element; + _outlineStyle = element.style.outline; + element.style.outline = 'none'; + DomEvent.on(window, 'keydown', restoreOutline); +} + +// @function restoreOutline() +// Cancels the effects of a previous [`L.DomUtil.preventOutline`](). +export function restoreOutline() { + if (!_outlineElement) { return; } + _outlineElement.style.outline = _outlineStyle; + _outlineElement = undefined; + _outlineStyle = undefined; + DomEvent.off(window, 'keydown', restoreOutline); +} + +// @function getSizedParentNode(el: HTMLElement): HTMLElement +// Finds the closest parent node which size (width and height) is not null. +export function getSizedParentNode(element) { + do { + element = element.parentNode; + } while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body); + return element; +} + +// @function getScale(el: HTMLElement): Object +// Computes the CSS scale currently applied on the element. +// Returns an object with `x` and `y` members as horizontal and vertical scales respectively, +// and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect). +export function getScale(element) { + var rect = element.getBoundingClientRect(); // Read-only in old browsers. + + return { + x: rect.width / element.offsetWidth || 1, + y: rect.height / element.offsetHeight || 1, + boundingClientRect: rect + }; +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/Draggable.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/Draggable.js new file mode 100644 index 000000000..52b875bc6 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/Draggable.js @@ -0,0 +1,236 @@ +import {Evented} from '../core/Events'; +import * as Browser from '../core/Browser'; +import * as DomEvent from './DomEvent'; +import * as DomUtil from './DomUtil'; +import * as Util from '../core/Util'; +import {Point} from '../geometry/Point'; + +/* + * @class Draggable + * @aka L.Draggable + * @inherits Evented + * + * A class for making DOM elements draggable (including touch support). + * Used internally for map and marker dragging. Only works for elements + * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition). + * + * @example + * ```js + * var draggable = new L.Draggable(elementToDrag); + * draggable.enable(); + * ``` + */ + +var START = Browser.touch ? 'touchstart mousedown' : 'mousedown'; +var END = { + mousedown: 'mouseup', + touchstart: 'touchend', + pointerdown: 'touchend', + MSPointerDown: 'touchend' +}; +var MOVE = { + mousedown: 'mousemove', + touchstart: 'touchmove', + pointerdown: 'touchmove', + MSPointerDown: 'touchmove' +}; + + +export var Draggable = Evented.extend({ + + options: { + // @section + // @aka Draggable options + // @option clickTolerance: Number = 3 + // The max number of pixels a user can shift the mouse pointer during a click + // for it to be considered a valid click (as opposed to a mouse drag). + clickTolerance: 3 + }, + + // @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options) + // Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default). + initialize: function (element, dragStartTarget, preventOutline, options) { + Util.setOptions(this, options); + + this._element = element; + this._dragStartTarget = dragStartTarget || element; + this._preventOutline = preventOutline; + }, + + // @method enable() + // Enables the dragging ability + enable: function () { + if (this._enabled) { return; } + + DomEvent.on(this._dragStartTarget, START, this._onDown, this); + + this._enabled = true; + }, + + // @method disable() + // Disables the dragging ability + disable: function () { + if (!this._enabled) { return; } + + // If we're currently dragging this draggable, + // disabling it counts as first ending the drag. + if (Draggable._dragging === this) { + this.finishDrag(); + } + + DomEvent.off(this._dragStartTarget, START, this._onDown, this); + + this._enabled = false; + this._moved = false; + }, + + _onDown: function (e) { + // Ignore simulated events, since we handle both touch and + // mouse explicitly; otherwise we risk getting duplicates of + // touch events, see #4315. + // Also ignore the event if disabled; this happens in IE11 + // under some circumstances, see #3666. + if (e._simulated || !this._enabled) { return; } + + this._moved = false; + + if (DomUtil.hasClass(this._element, 'leaflet-zoom-anim')) { return; } + + if (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; } + Draggable._dragging = this; // Prevent dragging multiple objects at once. + + if (this._preventOutline) { + DomUtil.preventOutline(this._element); + } + + DomUtil.disableImageDrag(); + DomUtil.disableTextSelection(); + + if (this._moving) { return; } + + // @event down: Event + // Fired when a drag is about to start. + this.fire('down'); + + var first = e.touches ? e.touches[0] : e, + sizedParent = DomUtil.getSizedParentNode(this._element); + + this._startPoint = new Point(first.clientX, first.clientY); + + // Cache the scale, so that we can continuously compensate for it during drag (_onMove). + this._parentScale = DomUtil.getScale(sizedParent); + + DomEvent.on(document, MOVE[e.type], this._onMove, this); + DomEvent.on(document, END[e.type], this._onUp, this); + }, + + _onMove: function (e) { + // Ignore simulated events, since we handle both touch and + // mouse explicitly; otherwise we risk getting duplicates of + // touch events, see #4315. + // Also ignore the event if disabled; this happens in IE11 + // under some circumstances, see #3666. + if (e._simulated || !this._enabled) { return; } + + if (e.touches && e.touches.length > 1) { + this._moved = true; + return; + } + + var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e), + offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint); + + if (!offset.x && !offset.y) { return; } + if (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; } + + // We assume that the parent container's position, border and scale do not change for the duration of the drag. + // Therefore there is no need to account for the position and border (they are eliminated by the subtraction) + // and we can use the cached value for the scale. + offset.x /= this._parentScale.x; + offset.y /= this._parentScale.y; + + DomEvent.preventDefault(e); + + if (!this._moved) { + // @event dragstart: Event + // Fired when a drag starts + this.fire('dragstart'); + + this._moved = true; + this._startPos = DomUtil.getPosition(this._element).subtract(offset); + + DomUtil.addClass(document.body, 'leaflet-dragging'); + + this._lastTarget = e.target || e.srcElement; + // IE and Edge do not give the element, so fetch it + // if necessary + if ((window.SVGElementInstance) && (this._lastTarget instanceof SVGElementInstance)) { + this._lastTarget = this._lastTarget.correspondingUseElement; + } + DomUtil.addClass(this._lastTarget, 'leaflet-drag-target'); + } + + this._newPos = this._startPos.add(offset); + this._moving = true; + + Util.cancelAnimFrame(this._animRequest); + this._lastEvent = e; + this._animRequest = Util.requestAnimFrame(this._updatePosition, this, true); + }, + + _updatePosition: function () { + var e = {originalEvent: this._lastEvent}; + + // @event predrag: Event + // Fired continuously during dragging *before* each corresponding + // update of the element's position. + this.fire('predrag', e); + DomUtil.setPosition(this._element, this._newPos); + + // @event drag: Event + // Fired continuously during dragging. + this.fire('drag', e); + }, + + _onUp: function (e) { + // Ignore simulated events, since we handle both touch and + // mouse explicitly; otherwise we risk getting duplicates of + // touch events, see #4315. + // Also ignore the event if disabled; this happens in IE11 + // under some circumstances, see #3666. + if (e._simulated || !this._enabled) { return; } + this.finishDrag(); + }, + + finishDrag: function () { + DomUtil.removeClass(document.body, 'leaflet-dragging'); + + if (this._lastTarget) { + DomUtil.removeClass(this._lastTarget, 'leaflet-drag-target'); + this._lastTarget = null; + } + + for (var i in MOVE) { + DomEvent.off(document, MOVE[i], this._onMove, this); + DomEvent.off(document, END[i], this._onUp, this); + } + + DomUtil.enableImageDrag(); + DomUtil.enableTextSelection(); + + if (this._moved && this._moving) { + // ensure drag is not fired after dragend + Util.cancelAnimFrame(this._animRequest); + + // @event dragend: DragEndEvent + // Fired when the drag ends. + this.fire('dragend', { + distance: this._newPos.distanceTo(this._startPos) + }); + } + + this._moving = false; + Draggable._dragging = false; + } + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/PosAnimation.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/PosAnimation.js new file mode 100644 index 000000000..05290c113 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/PosAnimation.js @@ -0,0 +1,100 @@ +import * as Util from '../core/Util'; +import {Evented} from '../core/Events'; +import * as DomUtil from '../dom/DomUtil'; + + +/* + * @class PosAnimation + * @aka L.PosAnimation + * @inherits Evented + * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9. + * + * @example + * ```js + * var fx = new L.PosAnimation(); + * fx.run(el, [300, 500], 0.5); + * ``` + * + * @constructor L.PosAnimation() + * Creates a `PosAnimation` object. + * + */ + +export var PosAnimation = Evented.extend({ + + // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number) + // Run an animation of a given element to a new position, optionally setting + // duration in seconds (`0.25` by default) and easing linearity factor (3rd + // argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1), + // `0.5` by default). + run: function (el, newPos, duration, easeLinearity) { + this.stop(); + + this._el = el; + this._inProgress = true; + this._duration = duration || 0.25; + this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); + + this._startPos = DomUtil.getPosition(el); + this._offset = newPos.subtract(this._startPos); + this._startTime = +new Date(); + + // @event start: Event + // Fired when the animation starts + this.fire('start'); + + this._animate(); + }, + + // @method stop() + // Stops the animation (if currently running). + stop: function () { + if (!this._inProgress) { return; } + + this._step(true); + this._complete(); + }, + + _animate: function () { + // animation loop + this._animId = Util.requestAnimFrame(this._animate, this); + this._step(); + }, + + _step: function (round) { + var elapsed = (+new Date()) - this._startTime, + duration = this._duration * 1000; + + if (elapsed < duration) { + this._runFrame(this._easeOut(elapsed / duration), round); + } else { + this._runFrame(1); + this._complete(); + } + }, + + _runFrame: function (progress, round) { + var pos = this._startPos.add(this._offset.multiplyBy(progress)); + if (round) { + pos._round(); + } + DomUtil.setPosition(this._el, pos); + + // @event step: Event + // Fired continuously during the animation. + this.fire('step'); + }, + + _complete: function () { + Util.cancelAnimFrame(this._animId); + + this._inProgress = false; + // @event end: Event + // Fired when the animation ends. + this.fire('end'); + }, + + _easeOut: function (t) { + return 1 - Math.pow(1 - t, this._easeOutPower); + } +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/index.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/index.js new file mode 100644 index 000000000..07e333174 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/dom/index.js @@ -0,0 +1,9 @@ +export {PosAnimation} from './PosAnimation'; + +import * as DomEvent from './DomEvent'; +export {DomEvent}; + +import * as DomUtil from './DomUtil'; +export {DomUtil}; + +export {Draggable} from './Draggable'; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/LatLng.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/LatLng.js new file mode 100644 index 000000000..9fafca93f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/LatLng.js @@ -0,0 +1,137 @@ +import * as Util from '../core/Util'; +import {Earth} from './crs/CRS.Earth'; +import {toLatLngBounds} from './LatLngBounds'; + +/* @class LatLng + * @aka L.LatLng + * + * Represents a geographical point with a certain latitude and longitude. + * + * @example + * + * ``` + * var latlng = L.latLng(50.5, 30.5); + * ``` + * + * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent: + * + * ``` + * map.panTo([50, 30]); + * map.panTo({lon: 30, lat: 50}); + * map.panTo({lat: 50, lng: 30}); + * map.panTo(L.latLng(50, 30)); + * ``` + * + * Note that `LatLng` does not inherit from Leaflet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +export function LatLng(lat, lng, alt) { + if (isNaN(lat) || isNaN(lng)) { + throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); + } + + // @property lat: Number + // Latitude in degrees + this.lat = +lat; + + // @property lng: Number + // Longitude in degrees + this.lng = +lng; + + // @property alt: Number + // Altitude in meters (optional) + if (alt !== undefined) { + this.alt = +alt; + } +} + +LatLng.prototype = { + // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean + // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number. + equals: function (obj, maxMargin) { + if (!obj) { return false; } + + obj = toLatLng(obj); + + var margin = Math.max( + Math.abs(this.lat - obj.lat), + Math.abs(this.lng - obj.lng)); + + return margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin); + }, + + // @method toString(): String + // Returns a string representation of the point (for debugging purposes). + toString: function (precision) { + return 'LatLng(' + + Util.formatNum(this.lat, precision) + ', ' + + Util.formatNum(this.lng, precision) + ')'; + }, + + // @method distanceTo(otherLatLng: LatLng): Number + // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines). + distanceTo: function (other) { + return Earth.distance(this, toLatLng(other)); + }, + + // @method wrap(): LatLng + // Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees. + wrap: function () { + return Earth.wrapLatLng(this); + }, + + // @method toBounds(sizeInMeters: Number): LatLngBounds + // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`. + toBounds: function (sizeInMeters) { + var latAccuracy = 180 * sizeInMeters / 40075017, + lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat); + + return toLatLngBounds( + [this.lat - latAccuracy, this.lng - lngAccuracy], + [this.lat + latAccuracy, this.lng + lngAccuracy]); + }, + + clone: function () { + return new LatLng(this.lat, this.lng, this.alt); + } +}; + + + +// @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng +// Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude). + +// @alternative +// @factory L.latLng(coords: Array): LatLng +// Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead. + +// @alternative +// @factory L.latLng(coords: Object): LatLng +// Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead. + +export function toLatLng(a, b, c) { + if (a instanceof LatLng) { + return a; + } + if (Util.isArray(a) && typeof a[0] !== 'object') { + if (a.length === 3) { + return new LatLng(a[0], a[1], a[2]); + } + if (a.length === 2) { + return new LatLng(a[0], a[1]); + } + return null; + } + if (a === undefined || a === null) { + return a; + } + if (typeof a === 'object' && 'lat' in a) { + return new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt); + } + if (b === undefined) { + return null; + } + return new LatLng(a, b, c); +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/LatLngBounds.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/LatLngBounds.js new file mode 100644 index 000000000..8fc03c3a9 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/LatLngBounds.js @@ -0,0 +1,251 @@ +import {LatLng, toLatLng} from './LatLng'; + +/* + * @class LatLngBounds + * @aka L.LatLngBounds + * + * Represents a rectangular geographical area on a map. + * + * @example + * + * ```js + * var corner1 = L.latLng(40.712, -74.227), + * corner2 = L.latLng(40.774, -74.125), + * bounds = L.latLngBounds(corner1, corner2); + * ``` + * + * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this: + * + * ```js + * map.fitBounds([ + * [40.712, -74.227], + * [40.774, -74.125] + * ]); + * ``` + * + * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range. + * + * Note that `LatLngBounds` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +export function LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[]) + if (!corner1) { return; } + + var latlngs = corner2 ? [corner1, corner2] : corner1; + + for (var i = 0, len = latlngs.length; i < len; i++) { + this.extend(latlngs[i]); + } +} + +LatLngBounds.prototype = { + + // @method extend(latlng: LatLng): this + // Extend the bounds to contain the given point + + // @alternative + // @method extend(otherBounds: LatLngBounds): this + // Extend the bounds to contain the given bounds + extend: function (obj) { + var sw = this._southWest, + ne = this._northEast, + sw2, ne2; + + if (obj instanceof LatLng) { + sw2 = obj; + ne2 = obj; + + } else if (obj instanceof LatLngBounds) { + sw2 = obj._southWest; + ne2 = obj._northEast; + + if (!sw2 || !ne2) { return this; } + + } else { + return obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this; + } + + if (!sw && !ne) { + this._southWest = new LatLng(sw2.lat, sw2.lng); + this._northEast = new LatLng(ne2.lat, ne2.lng); + } else { + sw.lat = Math.min(sw2.lat, sw.lat); + sw.lng = Math.min(sw2.lng, sw.lng); + ne.lat = Math.max(ne2.lat, ne.lat); + ne.lng = Math.max(ne2.lng, ne.lng); + } + + return this; + }, + + // @method pad(bufferRatio: Number): LatLngBounds + // Returns bounds created by extending or retracting the current bounds by a given ratio in each direction. + // For example, a ratio of 0.5 extends the bounds by 50% in each direction. + // Negative values will retract the bounds. + pad: function (bufferRatio) { + var sw = this._southWest, + ne = this._northEast, + heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio, + widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio; + + return new LatLngBounds( + new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer), + new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer)); + }, + + // @method getCenter(): LatLng + // Returns the center point of the bounds. + getCenter: function () { + return new LatLng( + (this._southWest.lat + this._northEast.lat) / 2, + (this._southWest.lng + this._northEast.lng) / 2); + }, + + // @method getSouthWest(): LatLng + // Returns the south-west point of the bounds. + getSouthWest: function () { + return this._southWest; + }, + + // @method getNorthEast(): LatLng + // Returns the north-east point of the bounds. + getNorthEast: function () { + return this._northEast; + }, + + // @method getNorthWest(): LatLng + // Returns the north-west point of the bounds. + getNorthWest: function () { + return new LatLng(this.getNorth(), this.getWest()); + }, + + // @method getSouthEast(): LatLng + // Returns the south-east point of the bounds. + getSouthEast: function () { + return new LatLng(this.getSouth(), this.getEast()); + }, + + // @method getWest(): Number + // Returns the west longitude of the bounds + getWest: function () { + return this._southWest.lng; + }, + + // @method getSouth(): Number + // Returns the south latitude of the bounds + getSouth: function () { + return this._southWest.lat; + }, + + // @method getEast(): Number + // Returns the east longitude of the bounds + getEast: function () { + return this._northEast.lng; + }, + + // @method getNorth(): Number + // Returns the north latitude of the bounds + getNorth: function () { + return this._northEast.lat; + }, + + // @method contains(otherBounds: LatLngBounds): Boolean + // Returns `true` if the rectangle contains the given one. + + // @alternative + // @method contains (latlng: LatLng): Boolean + // Returns `true` if the rectangle contains the given point. + contains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean + if (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) { + obj = toLatLng(obj); + } else { + obj = toLatLngBounds(obj); + } + + var sw = this._southWest, + ne = this._northEast, + sw2, ne2; + + if (obj instanceof LatLngBounds) { + sw2 = obj.getSouthWest(); + ne2 = obj.getNorthEast(); + } else { + sw2 = ne2 = obj; + } + + return (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) && + (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng); + }, + + // @method intersects(otherBounds: LatLngBounds): Boolean + // Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common. + intersects: function (bounds) { + bounds = toLatLngBounds(bounds); + + var sw = this._southWest, + ne = this._northEast, + sw2 = bounds.getSouthWest(), + ne2 = bounds.getNorthEast(), + + latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat), + lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng); + + return latIntersects && lngIntersects; + }, + + // @method overlaps(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area. + overlaps: function (bounds) { + bounds = toLatLngBounds(bounds); + + var sw = this._southWest, + ne = this._northEast, + sw2 = bounds.getSouthWest(), + ne2 = bounds.getNorthEast(), + + latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat), + lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng); + + return latOverlaps && lngOverlaps; + }, + + // @method toBBoxString(): String + // Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data. + toBBoxString: function () { + return [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(','); + }, + + // @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean + // Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number. + equals: function (bounds, maxMargin) { + if (!bounds) { return false; } + + bounds = toLatLngBounds(bounds); + + return this._southWest.equals(bounds.getSouthWest(), maxMargin) && + this._northEast.equals(bounds.getNorthEast(), maxMargin); + }, + + // @method isValid(): Boolean + // Returns `true` if the bounds are properly initialized. + isValid: function () { + return !!(this._southWest && this._northEast); + } +}; + +// TODO International date line? + +// @factory L.latLngBounds(corner1: LatLng, corner2: LatLng) +// Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle. + +// @alternative +// @factory L.latLngBounds(latlngs: LatLng[]) +// Creates a `LatLngBounds` object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with [`fitBounds`](#map-fitbounds). +export function toLatLngBounds(a, b) { + if (a instanceof LatLngBounds) { + return a; + } + return new LatLngBounds(a, b); +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG3395.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG3395.js new file mode 100644 index 000000000..05a2977ce --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG3395.js @@ -0,0 +1,20 @@ +import {Earth} from './CRS.Earth'; +import {Mercator} from '../projection/Projection.Mercator'; +import {toTransformation} from '../../geometry/Transformation'; +import * as Util from '../../core/Util'; + +/* + * @namespace CRS + * @crs L.CRS.EPSG3395 + * + * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection. + */ +export var EPSG3395 = Util.extend({}, Earth, { + code: 'EPSG:3395', + projection: Mercator, + + transformation: (function () { + var scale = 0.5 / (Math.PI * Mercator.R); + return toTransformation(scale, 0.5, -scale, 0.5); + }()) +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG3857.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG3857.js new file mode 100644 index 000000000..d2b4a7575 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG3857.js @@ -0,0 +1,27 @@ +import {Earth} from './CRS.Earth'; +import {SphericalMercator} from '../projection/Projection.SphericalMercator'; +import {toTransformation} from '../../geometry/Transformation'; +import * as Util from '../../core/Util'; + +/* + * @namespace CRS + * @crs L.CRS.EPSG3857 + * + * The most common CRS for online maps, used by almost all free and commercial + * tile providers. Uses Spherical Mercator projection. Set in by default in + * Map's `crs` option. + */ + +export var EPSG3857 = Util.extend({}, Earth, { + code: 'EPSG:3857', + projection: SphericalMercator, + + transformation: (function () { + var scale = 0.5 / (Math.PI * SphericalMercator.R); + return toTransformation(scale, 0.5, -scale, 0.5); + }()) +}); + +export var EPSG900913 = Util.extend({}, EPSG3857, { + code: 'EPSG:900913' +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG4326.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG4326.js new file mode 100644 index 000000000..55978dbd9 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.EPSG4326.js @@ -0,0 +1,23 @@ +import {Earth} from './CRS.Earth'; +import {LonLat} from '../projection/Projection.LonLat'; +import {toTransformation} from '../../geometry/Transformation'; +import * as Util from '../../core/Util'; + +/* + * @namespace CRS + * @crs L.CRS.EPSG4326 + * + * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. + * + * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic), + * which is a breaking change from 0.7.x behaviour. If you are using a `TileLayer` + * with this CRS, ensure that there are two 256x256 pixel tiles covering the + * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), + * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set. + */ + +export var EPSG4326 = Util.extend({}, Earth, { + code: 'EPSG:4326', + projection: LonLat, + transformation: toTransformation(1 / 180, 1, -1 / 180, 0.5) +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.Earth.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.Earth.js new file mode 100755 index 000000000..6ecff6589 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.Earth.js @@ -0,0 +1,33 @@ +import {CRS} from './CRS'; +import * as Util from '../../core/Util'; + +/* + * @namespace CRS + * @crs L.CRS.Earth + * + * Serves as the base for CRS that are global such that they cover the earth. + * Can only be used as the base for other CRS and cannot be used directly, + * since it does not have a `code`, `projection` or `transformation`. `distance()` returns + * meters. + */ + +export var Earth = Util.extend({}, CRS, { + wrapLng: [-180, 180], + + // Mean Earth Radius, as recommended for use by + // the International Union of Geodesy and Geophysics, + // see http://rosettacode.org/wiki/Haversine_formula + R: 6371000, + + // distance between two geographical points using spherical law of cosines approximation + distance: function (latlng1, latlng2) { + var rad = Math.PI / 180, + lat1 = latlng1.lat * rad, + lat2 = latlng2.lat * rad, + sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2), + sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2), + a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon, + c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return this.R * c; + } +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.Simple.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.Simple.js new file mode 100644 index 000000000..634baa293 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.Simple.js @@ -0,0 +1,36 @@ +import {CRS} from './CRS'; +import {LonLat} from '../projection/Projection.LonLat'; +import {toTransformation} from '../../geometry/Transformation'; +import * as Util from '../../core/Util'; + +/* + * @namespace CRS + * @crs L.CRS.Simple + * + * A simple CRS that maps longitude and latitude into `x` and `y` directly. + * May be used for maps of flat surfaces (e.g. game maps). Note that the `y` + * axis should still be inverted (going from bottom to top). `distance()` returns + * simple euclidean distance. + */ + +export var Simple = Util.extend({}, CRS, { + projection: LonLat, + transformation: toTransformation(1, 0, -1, 0), + + scale: function (zoom) { + return Math.pow(2, zoom); + }, + + zoom: function (scale) { + return Math.log(scale) / Math.LN2; + }, + + distance: function (latlng1, latlng2) { + var dx = latlng2.lng - latlng1.lng, + dy = latlng2.lat - latlng1.lat; + + return Math.sqrt(dx * dx + dy * dy); + }, + + infinite: true +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.js new file mode 100644 index 000000000..1c4041c14 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/CRS.js @@ -0,0 +1,139 @@ + +import {Bounds} from '../../geometry/Bounds'; +import {LatLng} from '../LatLng'; +import {LatLngBounds} from '../LatLngBounds'; +import * as Util from '../../core/Util'; + +/* + * @namespace CRS + * @crs L.CRS.Base + * Object that defines coordinate reference systems for projecting + * geographical points into pixel (screen) coordinates and back (and to + * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See + * [spatial reference system](http://en.wikipedia.org/wiki/Coordinate_reference_system). + * + * Leaflet defines the most usual CRSs by default. If you want to use a + * CRS not defined by default, take a look at the + * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin. + * + * Note that the CRS instances do not inherit from Leafet's `Class` object, + * and can't be instantiated. Also, new classes can't inherit from them, + * and methods can't be added to them with the `include` function. + */ + +export var CRS = { + // @method latLngToPoint(latlng: LatLng, zoom: Number): Point + // Projects geographical coordinates into pixel coordinates for a given zoom. + latLngToPoint: function (latlng, zoom) { + var projectedPoint = this.projection.project(latlng), + scale = this.scale(zoom); + + return this.transformation._transform(projectedPoint, scale); + }, + + // @method pointToLatLng(point: Point, zoom: Number): LatLng + // The inverse of `latLngToPoint`. Projects pixel coordinates on a given + // zoom into geographical coordinates. + pointToLatLng: function (point, zoom) { + var scale = this.scale(zoom), + untransformedPoint = this.transformation.untransform(point, scale); + + return this.projection.unproject(untransformedPoint); + }, + + // @method project(latlng: LatLng): Point + // Projects geographical coordinates into coordinates in units accepted for + // this CRS (e.g. meters for EPSG:3857, for passing it to WMS services). + project: function (latlng) { + return this.projection.project(latlng); + }, + + // @method unproject(point: Point): LatLng + // Given a projected coordinate returns the corresponding LatLng. + // The inverse of `project`. + unproject: function (point) { + return this.projection.unproject(point); + }, + + // @method scale(zoom: Number): Number + // Returns the scale used when transforming projected coordinates into + // pixel coordinates for a particular zoom. For example, it returns + // `256 * 2^zoom` for Mercator-based CRS. + scale: function (zoom) { + return 256 * Math.pow(2, zoom); + }, + + // @method zoom(scale: Number): Number + // Inverse of `scale()`, returns the zoom level corresponding to a scale + // factor of `scale`. + zoom: function (scale) { + return Math.log(scale / 256) / Math.LN2; + }, + + // @method getProjectedBounds(zoom: Number): Bounds + // Returns the projection's bounds scaled and transformed for the provided `zoom`. + getProjectedBounds: function (zoom) { + if (this.infinite) { return null; } + + var b = this.projection.bounds, + s = this.scale(zoom), + min = this.transformation.transform(b.min, s), + max = this.transformation.transform(b.max, s); + + return new Bounds(min, max); + }, + + // @method distance(latlng1: LatLng, latlng2: LatLng): Number + // Returns the distance between two geographical coordinates. + + // @property code: String + // Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`) + // + // @property wrapLng: Number[] + // An array of two numbers defining whether the longitude (horizontal) coordinate + // axis wraps around a given range and how. Defaults to `[-180, 180]` in most + // geographical CRSs. If `undefined`, the longitude axis does not wrap around. + // + // @property wrapLat: Number[] + // Like `wrapLng`, but for the latitude (vertical) axis. + + // wrapLng: [min, max], + // wrapLat: [min, max], + + // @property infinite: Boolean + // If true, the coordinate space will be unbounded (infinite in both axes) + infinite: false, + + // @method wrapLatLng(latlng: LatLng): LatLng + // Returns a `LatLng` where lat and lng has been wrapped according to the + // CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds. + wrapLatLng: function (latlng) { + var lng = this.wrapLng ? Util.wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng, + lat = this.wrapLat ? Util.wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat, + alt = latlng.alt; + + return new LatLng(lat, lng, alt); + }, + + // @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds + // Returns a `LatLngBounds` with the same size as the given one, ensuring + // that its center is within the CRS's bounds. + // Only accepts actual `L.LatLngBounds` instances, not arrays. + wrapLatLngBounds: function (bounds) { + var center = bounds.getCenter(), + newCenter = this.wrapLatLng(center), + latShift = center.lat - newCenter.lat, + lngShift = center.lng - newCenter.lng; + + if (latShift === 0 && lngShift === 0) { + return bounds; + } + + var sw = bounds.getSouthWest(), + ne = bounds.getNorthEast(), + newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift), + newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift); + + return new LatLngBounds(newSw, newNe); + } +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/index.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/index.js new file mode 100644 index 000000000..c0370bafa --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/crs/index.js @@ -0,0 +1,15 @@ +import {CRS} from './CRS'; +import {Earth} from './CRS.Earth'; +import {EPSG3395} from './CRS.EPSG3395'; +import {EPSG3857, EPSG900913} from './CRS.EPSG3857'; +import {EPSG4326} from './CRS.EPSG4326'; +import {Simple} from './CRS.Simple'; + +CRS.Earth = Earth; +CRS.EPSG3395 = EPSG3395; +CRS.EPSG3857 = EPSG3857; +CRS.EPSG900913 = EPSG900913; +CRS.EPSG4326 = EPSG4326; +CRS.Simple = Simple; + +export {CRS}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/index.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/index.js new file mode 100644 index 000000000..d957914f5 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/index.js @@ -0,0 +1,7 @@ +export {LatLng, toLatLng as latLng} from './LatLng'; +export {LatLngBounds, toLatLngBounds as latLngBounds} from './LatLngBounds'; + +import * as Projection from './projection/index'; +export {Projection}; + +export * from './crs/index'; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.LonLat.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.LonLat.js new file mode 100644 index 000000000..774f66f61 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.LonLat.js @@ -0,0 +1,28 @@ +import {LatLng} from '../LatLng'; +import {Bounds} from '../../geometry/Bounds'; +import {Point} from '../../geometry/Point'; + +/* + * @namespace Projection + * @section + * Leaflet comes with a set of already defined Projections out of the box: + * + * @projection L.Projection.LonLat + * + * Equirectangular, or Plate Carree projection — the most simple projection, + * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as + * latitude. Also suitable for flat worlds, e.g. game maps. Used by the + * `EPSG:4326` and `Simple` CRS. + */ + +export var LonLat = { + project: function (latlng) { + return new Point(latlng.lng, latlng.lat); + }, + + unproject: function (point) { + return new LatLng(point.y, point.x); + }, + + bounds: new Bounds([-180, -90], [180, 90]) +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.Mercator.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.Mercator.js new file mode 100644 index 000000000..00ab52a85 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.Mercator.js @@ -0,0 +1,49 @@ +import {LatLng} from '../LatLng'; +import {Bounds} from '../../geometry/Bounds'; +import {Point} from '../../geometry/Point'; + +/* + * @namespace Projection + * @projection L.Projection.Mercator + * + * Elliptical Mercator projection — more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS. + */ + +export var Mercator = { + R: 6378137, + R_MINOR: 6356752.314245179, + + bounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]), + + project: function (latlng) { + var d = Math.PI / 180, + r = this.R, + y = latlng.lat * d, + tmp = this.R_MINOR / r, + e = Math.sqrt(1 - tmp * tmp), + con = e * Math.sin(y); + + var ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2); + y = -r * Math.log(Math.max(ts, 1E-10)); + + return new Point(latlng.lng * d * r, y); + }, + + unproject: function (point) { + var d = 180 / Math.PI, + r = this.R, + tmp = this.R_MINOR / r, + e = Math.sqrt(1 - tmp * tmp), + ts = Math.exp(-point.y / r), + phi = Math.PI / 2 - 2 * Math.atan(ts); + + for (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) { + con = e * Math.sin(phi); + con = Math.pow((1 - con) / (1 + con), e / 2); + dphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi; + phi += dphi; + } + + return new LatLng(phi * d, point.x * d / r); + } +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.SphericalMercator.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.SphericalMercator.js new file mode 100644 index 000000000..b6f6539f8 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/Projection.SphericalMercator.js @@ -0,0 +1,42 @@ +import {LatLng} from '../LatLng'; +import {Bounds} from '../../geometry/Bounds'; +import {Point} from '../../geometry/Point'; + +/* + * @namespace Projection + * @projection L.Projection.SphericalMercator + * + * Spherical Mercator projection — the most common projection for online maps, + * used by almost all free and commercial tile providers. Assumes that Earth is + * a sphere. Used by the `EPSG:3857` CRS. + */ + +export var SphericalMercator = { + + R: 6378137, + MAX_LATITUDE: 85.0511287798, + + project: function (latlng) { + var d = Math.PI / 180, + max = this.MAX_LATITUDE, + lat = Math.max(Math.min(max, latlng.lat), -max), + sin = Math.sin(lat * d); + + return new Point( + this.R * latlng.lng * d, + this.R * Math.log((1 + sin) / (1 - sin)) / 2); + }, + + unproject: function (point) { + var d = 180 / Math.PI; + + return new LatLng( + (2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d, + point.x * d / this.R); + }, + + bounds: (function () { + var d = 6378137 * Math.PI; + return new Bounds([-d, -d], [d, d]); + })() +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/index.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/index.js new file mode 100644 index 000000000..feee60101 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geo/projection/index.js @@ -0,0 +1,26 @@ +/* + * @class Projection + + * An object with methods for projecting geographical coordinates of the world onto + * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection). + + * @property bounds: Bounds + * The bounds (specified in CRS units) where the projection is valid + + * @method project(latlng: LatLng): Point + * Projects geographical coordinates into a 2D point. + * Only accepts actual `L.LatLng` instances, not arrays. + + * @method unproject(point: Point): LatLng + * The inverse of `project`. Projects a 2D point into a geographical location. + * Only accepts actual `L.Point` instances, not arrays. + + * Note that the projection instances do not inherit from Leafet's `Class` object, + * and can't be instantiated. Also, new classes can't inherit from them, + * and methods can't be added to them with the `include` function. + + */ + +export {LonLat} from './Projection.LonLat'; +export {Mercator} from './Projection.Mercator'; +export {SphericalMercator} from './Projection.SphericalMercator'; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Bounds.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Bounds.js new file mode 100644 index 000000000..2b3286b86 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Bounds.js @@ -0,0 +1,173 @@ +import {Point, toPoint} from './Point'; + +/* + * @class Bounds + * @aka L.Bounds + * + * Represents a rectangular area in pixel coordinates. + * + * @example + * + * ```js + * var p1 = L.point(10, 10), + * p2 = L.point(40, 60), + * bounds = L.bounds(p1, p2); + * ``` + * + * All Leaflet methods that accept `Bounds` objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this: + * + * ```js + * otherBounds.intersects([[10, 10], [40, 60]]); + * ``` + * + * Note that `Bounds` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +export function Bounds(a, b) { + if (!a) { return; } + + var points = b ? [a, b] : a; + + for (var i = 0, len = points.length; i < len; i++) { + this.extend(points[i]); + } +} + +Bounds.prototype = { + // @method extend(point: Point): this + // Extends the bounds to contain the given point. + extend: function (point) { // (Point) + point = toPoint(point); + + // @property min: Point + // The top left corner of the rectangle. + // @property max: Point + // The bottom right corner of the rectangle. + if (!this.min && !this.max) { + this.min = point.clone(); + this.max = point.clone(); + } else { + this.min.x = Math.min(point.x, this.min.x); + this.max.x = Math.max(point.x, this.max.x); + this.min.y = Math.min(point.y, this.min.y); + this.max.y = Math.max(point.y, this.max.y); + } + return this; + }, + + // @method getCenter(round?: Boolean): Point + // Returns the center point of the bounds. + getCenter: function (round) { + return new Point( + (this.min.x + this.max.x) / 2, + (this.min.y + this.max.y) / 2, round); + }, + + // @method getBottomLeft(): Point + // Returns the bottom-left point of the bounds. + getBottomLeft: function () { + return new Point(this.min.x, this.max.y); + }, + + // @method getTopRight(): Point + // Returns the top-right point of the bounds. + getTopRight: function () { // -> Point + return new Point(this.max.x, this.min.y); + }, + + // @method getTopLeft(): Point + // Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)). + getTopLeft: function () { + return this.min; // left, top + }, + + // @method getBottomRight(): Point + // Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)). + getBottomRight: function () { + return this.max; // right, bottom + }, + + // @method getSize(): Point + // Returns the size of the given bounds + getSize: function () { + return this.max.subtract(this.min); + }, + + // @method contains(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle contains the given one. + // @alternative + // @method contains(point: Point): Boolean + // Returns `true` if the rectangle contains the given point. + contains: function (obj) { + var min, max; + + if (typeof obj[0] === 'number' || obj instanceof Point) { + obj = toPoint(obj); + } else { + obj = toBounds(obj); + } + + if (obj instanceof Bounds) { + min = obj.min; + max = obj.max; + } else { + min = max = obj; + } + + return (min.x >= this.min.x) && + (max.x <= this.max.x) && + (min.y >= this.min.y) && + (max.y <= this.max.y); + }, + + // @method intersects(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle intersects the given bounds. Two bounds + // intersect if they have at least one point in common. + intersects: function (bounds) { // (Bounds) -> Boolean + bounds = toBounds(bounds); + + var min = this.min, + max = this.max, + min2 = bounds.min, + max2 = bounds.max, + xIntersects = (max2.x >= min.x) && (min2.x <= max.x), + yIntersects = (max2.y >= min.y) && (min2.y <= max.y); + + return xIntersects && yIntersects; + }, + + // @method overlaps(otherBounds: Bounds): Boolean + // Returns `true` if the rectangle overlaps the given bounds. Two bounds + // overlap if their intersection is an area. + overlaps: function (bounds) { // (Bounds) -> Boolean + bounds = toBounds(bounds); + + var min = this.min, + max = this.max, + min2 = bounds.min, + max2 = bounds.max, + xOverlaps = (max2.x > min.x) && (min2.x < max.x), + yOverlaps = (max2.y > min.y) && (min2.y < max.y); + + return xOverlaps && yOverlaps; + }, + + isValid: function () { + return !!(this.min && this.max); + } +}; + + +// @factory L.bounds(corner1: Point, corner2: Point) +// Creates a Bounds object from two corners coordinate pairs. +// @alternative +// @factory L.bounds(points: Point[]) +// Creates a Bounds object from the given array of points. +export function toBounds(a, b) { + if (!a || a instanceof Bounds) { + return a; + } + return new Bounds(a, b); +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/LineUtil.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/LineUtil.js new file mode 100644 index 000000000..8e291259f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/LineUtil.js @@ -0,0 +1,242 @@ +import {Point} from './Point'; +import * as Util from '../core/Util'; + + +/* + * @namespace LineUtil + * + * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast. + */ + +// Simplify polyline with vertex reduction and Douglas-Peucker simplification. +// Improves rendering performance dramatically by lessening the number of points to draw. + +// @function simplify(points: Point[], tolerance: Number): Point[] +// Dramatically reduces the number of points in a polyline while retaining +// its shape and returns a new array of simplified points, using the +// [Douglas-Peucker algorithm](http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm). +// Used for a huge performance boost when processing/displaying Leaflet polylines for +// each zoom level and also reducing visual noise. tolerance affects the amount of +// simplification (lesser value means higher quality but slower and with more points). +// Also released as a separated micro-library [Simplify.js](http://mourner.github.com/simplify-js/). +export function simplify(points, tolerance) { + if (!tolerance || !points.length) { + return points.slice(); + } + + var sqTolerance = tolerance * tolerance; + + // stage 1: vertex reduction + points = _reducePoints(points, sqTolerance); + + // stage 2: Douglas-Peucker simplification + points = _simplifyDP(points, sqTolerance); + + return points; +} + +// @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number +// Returns the distance between point `p` and segment `p1` to `p2`. +export function pointToSegmentDistance(p, p1, p2) { + return Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true)); +} + +// @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number +// Returns the closest point from a point `p` on a segment `p1` to `p2`. +export function closestPointOnSegment(p, p1, p2) { + return _sqClosestPointOnSegment(p, p1, p2); +} + +// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm +function _simplifyDP(points, sqTolerance) { + + var len = points.length, + ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array, + markers = new ArrayConstructor(len); + + markers[0] = markers[len - 1] = 1; + + _simplifyDPStep(points, markers, sqTolerance, 0, len - 1); + + var i, + newPoints = []; + + for (i = 0; i < len; i++) { + if (markers[i]) { + newPoints.push(points[i]); + } + } + + return newPoints; +} + +function _simplifyDPStep(points, markers, sqTolerance, first, last) { + + var maxSqDist = 0, + index, i, sqDist; + + for (i = first + 1; i <= last - 1; i++) { + sqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true); + + if (sqDist > maxSqDist) { + index = i; + maxSqDist = sqDist; + } + } + + if (maxSqDist > sqTolerance) { + markers[index] = 1; + + _simplifyDPStep(points, markers, sqTolerance, first, index); + _simplifyDPStep(points, markers, sqTolerance, index, last); + } +} + +// reduce points that are too close to each other to a single point +function _reducePoints(points, sqTolerance) { + var reducedPoints = [points[0]]; + + for (var i = 1, prev = 0, len = points.length; i < len; i++) { + if (_sqDist(points[i], points[prev]) > sqTolerance) { + reducedPoints.push(points[i]); + prev = i; + } + } + if (prev < len - 1) { + reducedPoints.push(points[len - 1]); + } + return reducedPoints; +} + +var _lastCode; + +// @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, round?: Boolean): Point[]|Boolean +// Clips the segment a to b by rectangular bounds with the +// [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm) +// (modifying the segment points directly!). Used by Leaflet to only show polyline +// points that are on the screen or near, increasing performance. +export function clipSegment(a, b, bounds, useLastCode, round) { + var codeA = useLastCode ? _lastCode : _getBitCode(a, bounds), + codeB = _getBitCode(b, bounds), + + codeOut, p, newCode; + + // save 2nd code to avoid calculating it on the next segment + _lastCode = codeB; + + while (true) { + // if a,b is inside the clip window (trivial accept) + if (!(codeA | codeB)) { + return [a, b]; + } + + // if a,b is outside the clip window (trivial reject) + if (codeA & codeB) { + return false; + } + + // other cases + codeOut = codeA || codeB; + p = _getEdgeIntersection(a, b, codeOut, bounds, round); + newCode = _getBitCode(p, bounds); + + if (codeOut === codeA) { + a = p; + codeA = newCode; + } else { + b = p; + codeB = newCode; + } + } +} + +export function _getEdgeIntersection(a, b, code, bounds, round) { + var dx = b.x - a.x, + dy = b.y - a.y, + min = bounds.min, + max = bounds.max, + x, y; + + if (code & 8) { // top + x = a.x + dx * (max.y - a.y) / dy; + y = max.y; + + } else if (code & 4) { // bottom + x = a.x + dx * (min.y - a.y) / dy; + y = min.y; + + } else if (code & 2) { // right + x = max.x; + y = a.y + dy * (max.x - a.x) / dx; + + } else if (code & 1) { // left + x = min.x; + y = a.y + dy * (min.x - a.x) / dx; + } + + return new Point(x, y, round); +} + +export function _getBitCode(p, bounds) { + var code = 0; + + if (p.x < bounds.min.x) { // left + code |= 1; + } else if (p.x > bounds.max.x) { // right + code |= 2; + } + + if (p.y < bounds.min.y) { // bottom + code |= 4; + } else if (p.y > bounds.max.y) { // top + code |= 8; + } + + return code; +} + +// square distance (to avoid unnecessary Math.sqrt calls) +function _sqDist(p1, p2) { + var dx = p2.x - p1.x, + dy = p2.y - p1.y; + return dx * dx + dy * dy; +} + +// return closest point on segment or distance to that point +export function _sqClosestPointOnSegment(p, p1, p2, sqDist) { + var x = p1.x, + y = p1.y, + dx = p2.x - x, + dy = p2.y - y, + dot = dx * dx + dy * dy, + t; + + if (dot > 0) { + t = ((p.x - x) * dx + (p.y - y) * dy) / dot; + + if (t > 1) { + x = p2.x; + y = p2.y; + } else if (t > 0) { + x += dx * t; + y += dy * t; + } + } + + dx = p.x - x; + dy = p.y - y; + + return sqDist ? dx * dx + dy * dy : new Point(x, y); +} + + +// @function isFlat(latlngs: LatLng[]): Boolean +// Returns true if `latlngs` is a flat array, false is nested. +export function isFlat(latlngs) { + return !Util.isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined'); +} + +export function _flat(latlngs) { + console.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.'); + return isFlat(latlngs); +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Point.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Point.js new file mode 100644 index 000000000..3d9d473e1 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Point.js @@ -0,0 +1,222 @@ +import {isArray, formatNum} from '../core/Util'; + +/* + * @class Point + * @aka L.Point + * + * Represents a point with `x` and `y` coordinates in pixels. + * + * @example + * + * ```js + * var point = L.point(200, 300); + * ``` + * + * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent: + * + * ```js + * map.panBy([200, 300]); + * map.panBy(L.point(200, 300)); + * ``` + * + * Note that `Point` does not inherit from Leafet's `Class` object, + * which means new classes can't inherit from it, and new methods + * can't be added to it with the `include` function. + */ + +export function Point(x, y, round) { + // @property x: Number; The `x` coordinate of the point + this.x = (round ? Math.round(x) : x); + // @property y: Number; The `y` coordinate of the point + this.y = (round ? Math.round(y) : y); +} + +var trunc = Math.trunc || function (v) { + return v > 0 ? Math.floor(v) : Math.ceil(v); +}; + +Point.prototype = { + + // @method clone(): Point + // Returns a copy of the current point. + clone: function () { + return new Point(this.x, this.y); + }, + + // @method add(otherPoint: Point): Point + // Returns the result of addition of the current and the given points. + add: function (point) { + // non-destructive, returns a new point + return this.clone()._add(toPoint(point)); + }, + + _add: function (point) { + // destructive, used directly for performance in situations where it's safe to modify existing point + this.x += point.x; + this.y += point.y; + return this; + }, + + // @method subtract(otherPoint: Point): Point + // Returns the result of subtraction of the given point from the current. + subtract: function (point) { + return this.clone()._subtract(toPoint(point)); + }, + + _subtract: function (point) { + this.x -= point.x; + this.y -= point.y; + return this; + }, + + // @method divideBy(num: Number): Point + // Returns the result of division of the current point by the given number. + divideBy: function (num) { + return this.clone()._divideBy(num); + }, + + _divideBy: function (num) { + this.x /= num; + this.y /= num; + return this; + }, + + // @method multiplyBy(num: Number): Point + // Returns the result of multiplication of the current point by the given number. + multiplyBy: function (num) { + return this.clone()._multiplyBy(num); + }, + + _multiplyBy: function (num) { + this.x *= num; + this.y *= num; + return this; + }, + + // @method scaleBy(scale: Point): Point + // Multiply each coordinate of the current point by each coordinate of + // `scale`. In linear algebra terms, multiply the point by the + // [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation) + // defined by `scale`. + scaleBy: function (point) { + return new Point(this.x * point.x, this.y * point.y); + }, + + // @method unscaleBy(scale: Point): Point + // Inverse of `scaleBy`. Divide each coordinate of the current point by + // each coordinate of `scale`. + unscaleBy: function (point) { + return new Point(this.x / point.x, this.y / point.y); + }, + + // @method round(): Point + // Returns a copy of the current point with rounded coordinates. + round: function () { + return this.clone()._round(); + }, + + _round: function () { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + return this; + }, + + // @method floor(): Point + // Returns a copy of the current point with floored coordinates (rounded down). + floor: function () { + return this.clone()._floor(); + }, + + _floor: function () { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + return this; + }, + + // @method ceil(): Point + // Returns a copy of the current point with ceiled coordinates (rounded up). + ceil: function () { + return this.clone()._ceil(); + }, + + _ceil: function () { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + return this; + }, + + // @method trunc(): Point + // Returns a copy of the current point with truncated coordinates (rounded towards zero). + trunc: function () { + return this.clone()._trunc(); + }, + + _trunc: function () { + this.x = trunc(this.x); + this.y = trunc(this.y); + return this; + }, + + // @method distanceTo(otherPoint: Point): Number + // Returns the cartesian distance between the current and the given points. + distanceTo: function (point) { + point = toPoint(point); + + var x = point.x - this.x, + y = point.y - this.y; + + return Math.sqrt(x * x + y * y); + }, + + // @method equals(otherPoint: Point): Boolean + // Returns `true` if the given point has the same coordinates. + equals: function (point) { + point = toPoint(point); + + return point.x === this.x && + point.y === this.y; + }, + + // @method contains(otherPoint: Point): Boolean + // Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values). + contains: function (point) { + point = toPoint(point); + + return Math.abs(point.x) <= Math.abs(this.x) && + Math.abs(point.y) <= Math.abs(this.y); + }, + + // @method toString(): String + // Returns a string representation of the point for debugging purposes. + toString: function () { + return 'Point(' + + formatNum(this.x) + ', ' + + formatNum(this.y) + ')'; + } +}; + +// @factory L.point(x: Number, y: Number, round?: Boolean) +// Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values. + +// @alternative +// @factory L.point(coords: Number[]) +// Expects an array of the form `[x, y]` instead. + +// @alternative +// @factory L.point(coords: Object) +// Expects a plain object of the form `{x: Number, y: Number}` instead. +export function toPoint(x, y, round) { + if (x instanceof Point) { + return x; + } + if (isArray(x)) { + return new Point(x[0], x[1]); + } + if (x === undefined || x === null) { + return x; + } + if (typeof x === 'object' && 'x' in x && 'y' in x) { + return new Point(x.x, x.y); + } + return new Point(x, y, round); +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/PolyUtil.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/PolyUtil.js new file mode 100644 index 000000000..87aa4b19e --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/PolyUtil.js @@ -0,0 +1,55 @@ +import * as LineUtil from './LineUtil'; + +/* + * @namespace PolyUtil + * Various utility functions for polygon geometries. + */ + +/* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[] + * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)). + * Used by Leaflet to only show polygon points that are on the screen or near, increasing + * performance. Note that polygon points needs different algorithm for clipping + * than polyline, so there's a separate method for it. + */ +export function clipPolygon(points, bounds, round) { + var clippedPoints, + edges = [1, 4, 2, 8], + i, j, k, + a, b, + len, edge, p; + + for (i = 0, len = points.length; i < len; i++) { + points[i]._code = LineUtil._getBitCode(points[i], bounds); + } + + // for each edge (left, bottom, right, top) + for (k = 0; k < 4; k++) { + edge = edges[k]; + clippedPoints = []; + + for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { + a = points[i]; + b = points[j]; + + // if a is inside the clip window + if (!(a._code & edge)) { + // if b is outside the clip window (a->b goes out of screen) + if (b._code & edge) { + p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round); + p._code = LineUtil._getBitCode(p, bounds); + clippedPoints.push(p); + } + clippedPoints.push(a); + + // else if b is inside the clip window (a->b enters the screen) + } else if (!(b._code & edge)) { + p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round); + p._code = LineUtil._getBitCode(p, bounds); + clippedPoints.push(p); + } + } + points = clippedPoints; + } + + return points; +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Transformation.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Transformation.js new file mode 100644 index 000000000..8f1147e45 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/Transformation.js @@ -0,0 +1,79 @@ +import {Point} from './Point'; +import * as Util from '../core/Util'; + +/* + * @class Transformation + * @aka L.Transformation + * + * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d` + * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing + * the reverse. Used by Leaflet in its projections code. + * + * @example + * + * ```js + * var transformation = L.transformation(2, 5, -1, 10), + * p = L.point(1, 2), + * p2 = transformation.transform(p), // L.point(7, 8) + * p3 = transformation.untransform(p2); // L.point(1, 2) + * ``` + */ + + +// factory new L.Transformation(a: Number, b: Number, c: Number, d: Number) +// Creates a `Transformation` object with the given coefficients. +export function Transformation(a, b, c, d) { + if (Util.isArray(a)) { + // use array properties + this._a = a[0]; + this._b = a[1]; + this._c = a[2]; + this._d = a[3]; + return; + } + this._a = a; + this._b = b; + this._c = c; + this._d = d; +} + +Transformation.prototype = { + // @method transform(point: Point, scale?: Number): Point + // Returns a transformed point, optionally multiplied by the given scale. + // Only accepts actual `L.Point` instances, not arrays. + transform: function (point, scale) { // (Point, Number) -> Point + return this._transform(point.clone(), scale); + }, + + // destructive transform (faster) + _transform: function (point, scale) { + scale = scale || 1; + point.x = scale * (this._a * point.x + this._b); + point.y = scale * (this._c * point.y + this._d); + return point; + }, + + // @method untransform(point: Point, scale?: Number): Point + // Returns the reverse transformation of the given point, optionally divided + // by the given scale. Only accepts actual `L.Point` instances, not arrays. + untransform: function (point, scale) { + scale = scale || 1; + return new Point( + (point.x / scale - this._b) / this._a, + (point.y / scale - this._d) / this._c); + } +}; + +// factory L.transformation(a: Number, b: Number, c: Number, d: Number) + +// @factory L.transformation(a: Number, b: Number, c: Number, d: Number) +// Instantiates a Transformation object with the given coefficients. + +// @alternative +// @factory L.transformation(coefficients: Array): Transformation +// Expects an coefficients array of the form +// `[a: Number, b: Number, c: Number, d: Number]`. + +export function toTransformation(a, b, c, d) { + return new Transformation(a, b, c, d); +} diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/index.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/index.js new file mode 100644 index 000000000..55a6fe5be --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/geometry/index.js @@ -0,0 +1,8 @@ +export {Point, toPoint as point} from './Point'; +export {Bounds, toBounds as bounds} from './Bounds'; +export {Transformation, toTransformation as transformation} from './Transformation'; + +import * as LineUtil from './LineUtil'; +export {LineUtil}; +import * as PolyUtil from './PolyUtil'; +export {PolyUtil}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/images/layers.svg b/vendor/assets/javascripts/Leaflet-1.4.0/src/images/layers.svg new file mode 100644 index 000000000..1a9ebef87 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/images/layers.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/images/logo.svg b/vendor/assets/javascripts/Leaflet-1.4.0/src/images/logo.svg new file mode 100644 index 000000000..6adc68bd4 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/images/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/images/marker.svg b/vendor/assets/javascripts/Leaflet-1.4.0/src/images/marker.svg new file mode 100644 index 000000000..d9ee408c7 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/images/marker.svg @@ -0,0 +1 @@ + Use this one. Select it and the area around with box select. should be exactly 25x41 at 90dpi How to do the inset border: Delete the existing inset border. Select the background, duplicate. Path, Dynamic offset. Fill: None, Stroke Paint: RGBA #ffffff1f Zoom down to the top and grab the diamond, drag it down and fiddle it untill it looks in line with the main color layers border. \ No newline at end of file diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/DivOverlay.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/DivOverlay.js new file mode 100644 index 000000000..efd76f1bb --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/DivOverlay.js @@ -0,0 +1,203 @@ +import {Layer} from './Layer'; +import * as Util from '../core/Util'; +import {toLatLng} from '../geo/LatLng'; +import {toPoint} from '../geometry/Point'; +import * as DomUtil from '../dom/DomUtil'; + +/* + * @class DivOverlay + * @inherits Layer + * @aka L.DivOverlay + * Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins. + */ + +// @namespace DivOverlay +export var DivOverlay = Layer.extend({ + + // @section + // @aka DivOverlay options + options: { + // @option offset: Point = Point(0, 7) + // The offset of the popup position. Useful to control the anchor + // of the popup when opening it on some overlays. + offset: [0, 7], + + // @option className: String = '' + // A custom CSS class name to assign to the popup. + className: '', + + // @option pane: String = 'popupPane' + // `Map pane` where the popup will be added. + pane: 'popupPane' + }, + + initialize: function (options, source) { + Util.setOptions(this, options); + + this._source = source; + }, + + onAdd: function (map) { + this._zoomAnimated = map._zoomAnimated; + + if (!this._container) { + this._initLayout(); + } + + if (map._fadeAnimated) { + DomUtil.setOpacity(this._container, 0); + } + + clearTimeout(this._removeTimeout); + this.getPane().appendChild(this._container); + this.update(); + + if (map._fadeAnimated) { + DomUtil.setOpacity(this._container, 1); + } + + this.bringToFront(); + }, + + onRemove: function (map) { + if (map._fadeAnimated) { + DomUtil.setOpacity(this._container, 0); + this._removeTimeout = setTimeout(Util.bind(DomUtil.remove, undefined, this._container), 200); + } else { + DomUtil.remove(this._container); + } + }, + + // @namespace Popup + // @method getLatLng: LatLng + // Returns the geographical point of popup. + getLatLng: function () { + return this._latlng; + }, + + // @method setLatLng(latlng: LatLng): this + // Sets the geographical point where the popup will open. + setLatLng: function (latlng) { + this._latlng = toLatLng(latlng); + if (this._map) { + this._updatePosition(); + this._adjustPan(); + } + return this; + }, + + // @method getContent: String|HTMLElement + // Returns the content of the popup. + getContent: function () { + return this._content; + }, + + // @method setContent(htmlContent: String|HTMLElement|Function): this + // Sets the HTML content of the popup. If a function is passed the source layer will be passed to the function. The function should return a `String` or `HTMLElement` to be used in the popup. + setContent: function (content) { + this._content = content; + this.update(); + return this; + }, + + // @method getElement: String|HTMLElement + // Alias for [getContent()](#popup-getcontent) + getElement: function () { + return this._container; + }, + + // @method update: null + // Updates the popup content, layout and position. Useful for updating the popup after something inside changed, e.g. image loaded. + update: function () { + if (!this._map) { return; } + + this._container.style.visibility = 'hidden'; + + this._updateContent(); + this._updateLayout(); + this._updatePosition(); + + this._container.style.visibility = ''; + + this._adjustPan(); + }, + + getEvents: function () { + var events = { + zoom: this._updatePosition, + viewreset: this._updatePosition + }; + + if (this._zoomAnimated) { + events.zoomanim = this._animateZoom; + } + return events; + }, + + // @method isOpen: Boolean + // Returns `true` when the popup is visible on the map. + isOpen: function () { + return !!this._map && this._map.hasLayer(this); + }, + + // @method bringToFront: this + // Brings this popup in front of other popups (in the same map pane). + bringToFront: function () { + if (this._map) { + DomUtil.toFront(this._container); + } + return this; + }, + + // @method bringToBack: this + // Brings this popup to the back of other popups (in the same map pane). + bringToBack: function () { + if (this._map) { + DomUtil.toBack(this._container); + } + return this; + }, + + _updateContent: function () { + if (!this._content) { return; } + + var node = this._contentNode; + var content = (typeof this._content === 'function') ? this._content(this._source || this) : this._content; + + if (typeof content === 'string') { + node.innerHTML = content; + } else { + while (node.hasChildNodes()) { + node.removeChild(node.firstChild); + } + node.appendChild(content); + } + this.fire('contentupdate'); + }, + + _updatePosition: function () { + if (!this._map) { return; } + + var pos = this._map.latLngToLayerPoint(this._latlng), + offset = toPoint(this.options.offset), + anchor = this._getAnchor(); + + if (this._zoomAnimated) { + DomUtil.setPosition(this._container, pos.add(anchor)); + } else { + offset = offset.add(pos).add(anchor); + } + + var bottom = this._containerBottom = -offset.y, + left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x; + + // bottom position the popup in case the height of the popup changes (images loading etc) + this._container.style.bottom = bottom + 'px'; + this._container.style.left = left + 'px'; + }, + + _getAnchor: function () { + return [0, 0]; + } + +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/FeatureGroup.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/FeatureGroup.js new file mode 100644 index 000000000..5913ff95f --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/FeatureGroup.js @@ -0,0 +1,94 @@ +import {LayerGroup} from './LayerGroup'; +import {LatLngBounds} from '../geo/LatLngBounds'; + +/* + * @class FeatureGroup + * @aka L.FeatureGroup + * @inherits LayerGroup + * + * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers: + * * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip)) + * * Events are propagated to the `FeatureGroup`, so if the group has an event + * handler, it will handle events from any of the layers. This includes mouse events + * and custom events. + * * Has `layeradd` and `layerremove` events + * + * @example + * + * ```js + * L.featureGroup([marker1, marker2, polyline]) + * .bindPopup('Hello world!') + * .on('click', function() { alert('Clicked on a member of the group!'); }) + * .addTo(map); + * ``` + */ + +export var FeatureGroup = LayerGroup.extend({ + + addLayer: function (layer) { + if (this.hasLayer(layer)) { + return this; + } + + layer.addEventParent(this); + + LayerGroup.prototype.addLayer.call(this, layer); + + // @event layeradd: LayerEvent + // Fired when a layer is added to this `FeatureGroup` + return this.fire('layeradd', {layer: layer}); + }, + + removeLayer: function (layer) { + if (!this.hasLayer(layer)) { + return this; + } + if (layer in this._layers) { + layer = this._layers[layer]; + } + + layer.removeEventParent(this); + + LayerGroup.prototype.removeLayer.call(this, layer); + + // @event layerremove: LayerEvent + // Fired when a layer is removed from this `FeatureGroup` + return this.fire('layerremove', {layer: layer}); + }, + + // @method setStyle(style: Path options): this + // Sets the given path options to each layer of the group that has a `setStyle` method. + setStyle: function (style) { + return this.invoke('setStyle', style); + }, + + // @method bringToFront(): this + // Brings the layer group to the top of all other layers + bringToFront: function () { + return this.invoke('bringToFront'); + }, + + // @method bringToBack(): this + // Brings the layer group to the back of all other layers + bringToBack: function () { + return this.invoke('bringToBack'); + }, + + // @method getBounds(): LatLngBounds + // Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children). + getBounds: function () { + var bounds = new LatLngBounds(); + + for (var id in this._layers) { + var layer = this._layers[id]; + bounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng()); + } + return bounds; + } +}); + +// @factory L.featureGroup(layers: Layer[]) +// Create a feature group, optionally given an initial set of layers. +export var featureGroup = function (layers) { + return new FeatureGroup(layers); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/GeoJSON.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/GeoJSON.js new file mode 100644 index 000000000..017ae27fc --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/GeoJSON.js @@ -0,0 +1,419 @@ +import {LayerGroup} from './LayerGroup'; +import {FeatureGroup} from './FeatureGroup'; +import * as Util from '../core/Util'; +import {Marker} from './marker/Marker'; +import {Circle} from './vector/Circle'; +import {CircleMarker} from './vector/CircleMarker'; +import {Polyline} from './vector/Polyline'; +import {Polygon} from './vector/Polygon'; +import {LatLng} from '../geo/LatLng'; +import * as LineUtil from '../geometry/LineUtil'; + + +/* + * @class GeoJSON + * @aka L.GeoJSON + * @inherits FeatureGroup + * + * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse + * GeoJSON data and display it on the map. Extends `FeatureGroup`. + * + * @example + * + * ```js + * L.geoJSON(data, { + * style: function (feature) { + * return {color: feature.properties.color}; + * } + * }).bindPopup(function (layer) { + * return layer.feature.properties.description; + * }).addTo(map); + * ``` + */ + +export var GeoJSON = FeatureGroup.extend({ + + /* @section + * @aka GeoJSON options + * + * @option pointToLayer: Function = * + * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally + * called when data is added, passing the GeoJSON point feature and its `LatLng`. + * The default is to spawn a default `Marker`: + * ```js + * function(geoJsonPoint, latlng) { + * return L.marker(latlng); + * } + * ``` + * + * @option style: Function = * + * A `Function` defining the `Path options` for styling GeoJSON lines and polygons, + * called internally when data is added. + * The default value is to not override any defaults: + * ```js + * function (geoJsonFeature) { + * return {} + * } + * ``` + * + * @option onEachFeature: Function = * + * A `Function` that will be called once for each created `Feature`, after it has + * been created and styled. Useful for attaching events and popups to features. + * The default is to do nothing with the newly created layers: + * ```js + * function (feature, layer) {} + * ``` + * + * @option filter: Function = * + * A `Function` that will be used to decide whether to include a feature or not. + * The default is to include all features: + * ```js + * function (geoJsonFeature) { + * return true; + * } + * ``` + * Note: dynamically changing the `filter` option will have effect only on newly + * added data. It will _not_ re-evaluate already included features. + * + * @option coordsToLatLng: Function = * + * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s. + * The default is the `coordsToLatLng` static method. + */ + + initialize: function (geojson, options) { + Util.setOptions(this, options); + + this._layers = {}; + + if (geojson) { + this.addData(geojson); + } + }, + + // @method addData( data ): this + // Adds a GeoJSON object to the layer. + addData: function (geojson) { + var features = Util.isArray(geojson) ? geojson : geojson.features, + i, len, feature; + + if (features) { + for (i = 0, len = features.length; i < len; i++) { + // only add this if geometry or geometries are set and not null + feature = features[i]; + if (feature.geometries || feature.geometry || feature.features || feature.coordinates) { + this.addData(feature); + } + } + return this; + } + + var options = this.options; + + if (options.filter && !options.filter(geojson)) { return this; } + + var layer = geometryToLayer(geojson, options); + if (!layer) { + return this; + } + layer.feature = asFeature(geojson); + + layer.defaultOptions = layer.options; + this.resetStyle(layer); + + if (options.onEachFeature) { + options.onEachFeature(geojson, layer); + } + + return this.addLayer(layer); + }, + + // @method resetStyle( layer ): this + // Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events. + resetStyle: function (layer) { + // reset any custom styles + layer.options = Util.extend({}, layer.defaultOptions); + this._setLayerStyle(layer, this.options.style); + return this; + }, + + // @method setStyle( style ): this + // Changes styles of GeoJSON vector layers with the given style function. + setStyle: function (style) { + return this.eachLayer(function (layer) { + this._setLayerStyle(layer, style); + }, this); + }, + + _setLayerStyle: function (layer, style) { + if (typeof style === 'function') { + style = style(layer.feature); + } + if (layer.setStyle) { + layer.setStyle(style); + } + } +}); + +// @section +// There are several static functions which can be called without instantiating L.GeoJSON: + +// @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer +// Creates a `Layer` from a given GeoJSON feature. Can use a custom +// [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng) +// functions if provided as options. +export function geometryToLayer(geojson, options) { + + var geometry = geojson.type === 'Feature' ? geojson.geometry : geojson, + coords = geometry ? geometry.coordinates : null, + layers = [], + pointToLayer = options && options.pointToLayer, + _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng, + latlng, latlngs, i, len; + + if (!coords && !geometry) { + return null; + } + + switch (geometry.type) { + case 'Point': + latlng = _coordsToLatLng(coords); + return pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng); + + case 'MultiPoint': + for (i = 0, len = coords.length; i < len; i++) { + latlng = _coordsToLatLng(coords[i]); + layers.push(pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng)); + } + return new FeatureGroup(layers); + + case 'LineString': + case 'MultiLineString': + latlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng); + return new Polyline(latlngs, options); + + case 'Polygon': + case 'MultiPolygon': + latlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng); + return new Polygon(latlngs, options); + + case 'GeometryCollection': + for (i = 0, len = geometry.geometries.length; i < len; i++) { + var layer = geometryToLayer({ + geometry: geometry.geometries[i], + type: 'Feature', + properties: geojson.properties + }, options); + + if (layer) { + layers.push(layer); + } + } + return new FeatureGroup(layers); + + default: + throw new Error('Invalid GeoJSON object.'); + } +} + +// @function coordsToLatLng(coords: Array): LatLng +// Creates a `LatLng` object from an array of 2 numbers (longitude, latitude) +// or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points. +export function coordsToLatLng(coords) { + return new LatLng(coords[1], coords[0], coords[2]); +} + +// @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array +// Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array. +// `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default). +// Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function. +export function coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) { + var latlngs = []; + + for (var i = 0, len = coords.length, latlng; i < len; i++) { + latlng = levelsDeep ? + coordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) : + (_coordsToLatLng || coordsToLatLng)(coords[i]); + + latlngs.push(latlng); + } + + return latlngs; +} + +// @function latLngToCoords(latlng: LatLng, precision?: Number): Array +// Reverse of [`coordsToLatLng`](#geojson-coordstolatlng) +export function latLngToCoords(latlng, precision) { + precision = typeof precision === 'number' ? precision : 6; + return latlng.alt !== undefined ? + [Util.formatNum(latlng.lng, precision), Util.formatNum(latlng.lat, precision), Util.formatNum(latlng.alt, precision)] : + [Util.formatNum(latlng.lng, precision), Util.formatNum(latlng.lat, precision)]; +} + +// @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array +// Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs) +// `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default. +export function latLngsToCoords(latlngs, levelsDeep, closed, precision) { + var coords = []; + + for (var i = 0, len = latlngs.length; i < len; i++) { + coords.push(levelsDeep ? + latLngsToCoords(latlngs[i], levelsDeep - 1, closed, precision) : + latLngToCoords(latlngs[i], precision)); + } + + if (!levelsDeep && closed) { + coords.push(coords[0]); + } + + return coords; +} + +export function getFeature(layer, newGeometry) { + return layer.feature ? + Util.extend({}, layer.feature, {geometry: newGeometry}) : + asFeature(newGeometry); +} + +// @function asFeature(geojson: Object): Object +// Normalize GeoJSON geometries/features into GeoJSON features. +export function asFeature(geojson) { + if (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') { + return geojson; + } + + return { + type: 'Feature', + properties: {}, + geometry: geojson + }; +} + +var PointToGeoJSON = { + toGeoJSON: function (precision) { + return getFeature(this, { + type: 'Point', + coordinates: latLngToCoords(this.getLatLng(), precision) + }); + } +}; + +// @namespace Marker +// @method toGeoJSON(): Object +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature). +Marker.include(PointToGeoJSON); + +// @namespace CircleMarker +// @method toGeoJSON(): Object +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature). +Circle.include(PointToGeoJSON); +CircleMarker.include(PointToGeoJSON); + + +// @namespace Polyline +// @method toGeoJSON(): Object +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature). +Polyline.include({ + toGeoJSON: function (precision) { + var multi = !LineUtil.isFlat(this._latlngs); + + var coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision); + + return getFeature(this, { + type: (multi ? 'Multi' : '') + 'LineString', + coordinates: coords + }); + } +}); + +// @namespace Polygon +// @method toGeoJSON(): Object +// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature). +Polygon.include({ + toGeoJSON: function (precision) { + var holes = !LineUtil.isFlat(this._latlngs), + multi = holes && !LineUtil.isFlat(this._latlngs[0]); + + var coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision); + + if (!holes) { + coords = [coords]; + } + + return getFeature(this, { + type: (multi ? 'Multi' : '') + 'Polygon', + coordinates: coords + }); + } +}); + + +// @namespace LayerGroup +LayerGroup.include({ + toMultiPoint: function (precision) { + var coords = []; + + this.eachLayer(function (layer) { + coords.push(layer.toGeoJSON(precision).geometry.coordinates); + }); + + return getFeature(this, { + type: 'MultiPoint', + coordinates: coords + }); + }, + + // @method toGeoJSON(): Object + // Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`). + toGeoJSON: function (precision) { + + var type = this.feature && this.feature.geometry && this.feature.geometry.type; + + if (type === 'MultiPoint') { + return this.toMultiPoint(precision); + } + + var isGeometryCollection = type === 'GeometryCollection', + jsons = []; + + this.eachLayer(function (layer) { + if (layer.toGeoJSON) { + var json = layer.toGeoJSON(precision); + if (isGeometryCollection) { + jsons.push(json.geometry); + } else { + var feature = asFeature(json); + // Squash nested feature collections + if (feature.type === 'FeatureCollection') { + jsons.push.apply(jsons, feature.features); + } else { + jsons.push(feature); + } + } + } + }); + + if (isGeometryCollection) { + return getFeature(this, { + geometries: jsons, + type: 'GeometryCollection' + }); + } + + return { + type: 'FeatureCollection', + features: jsons + }; + } +}); + +// @namespace GeoJSON +// @factory L.geoJSON(geojson?: Object, options?: GeoJSON options) +// Creates a GeoJSON layer. Optionally accepts an object in +// [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map +// (you can alternatively add it later with `addData` method) and an `options` object. +export function geoJSON(geojson, options) { + return new GeoJSON(geojson, options); +} + +// Backward compatibility. +export var geoJson = geoJSON; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/ImageOverlay.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/ImageOverlay.js new file mode 100644 index 000000000..4a543ad62 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/ImageOverlay.js @@ -0,0 +1,264 @@ +import {Layer} from './Layer'; +import * as Util from '../core/Util'; +import {toLatLngBounds} from '../geo/LatLngBounds'; +import {Bounds} from '../geometry/Bounds'; +import * as DomUtil from '../dom/DomUtil'; + +/* + * @class ImageOverlay + * @aka L.ImageOverlay + * @inherits Interactive layer + * + * Used to load and display a single image over specific bounds of the map. Extends `Layer`. + * + * @example + * + * ```js + * var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg', + * imageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]]; + * L.imageOverlay(imageUrl, imageBounds).addTo(map); + * ``` + */ + +export var ImageOverlay = Layer.extend({ + + // @section + // @aka ImageOverlay options + options: { + // @option opacity: Number = 1.0 + // The opacity of the image overlay. + opacity: 1, + + // @option alt: String = '' + // Text for the `alt` attribute of the image (useful for accessibility). + alt: '', + + // @option interactive: Boolean = false + // If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered. + interactive: false, + + // @option crossOrigin: Boolean|String = false + // Whether the crossOrigin attribute will be added to the image. + // If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data. + // Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values. + crossOrigin: false, + + // @option errorOverlayUrl: String = '' + // URL to the overlay image to show in place of the overlay that failed to load. + errorOverlayUrl: '', + + // @option zIndex: Number = 1 + // The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer. + zIndex: 1, + + // @option className: String = '' + // A custom class name to assign to the image. Empty by default. + className: '' + }, + + initialize: function (url, bounds, options) { // (String, LatLngBounds, Object) + this._url = url; + this._bounds = toLatLngBounds(bounds); + + Util.setOptions(this, options); + }, + + onAdd: function () { + if (!this._image) { + this._initImage(); + + if (this.options.opacity < 1) { + this._updateOpacity(); + } + } + + if (this.options.interactive) { + DomUtil.addClass(this._image, 'leaflet-interactive'); + this.addInteractiveTarget(this._image); + } + + this.getPane().appendChild(this._image); + this._reset(); + }, + + onRemove: function () { + DomUtil.remove(this._image); + if (this.options.interactive) { + this.removeInteractiveTarget(this._image); + } + }, + + // @method setOpacity(opacity: Number): this + // Sets the opacity of the overlay. + setOpacity: function (opacity) { + this.options.opacity = opacity; + + if (this._image) { + this._updateOpacity(); + } + return this; + }, + + setStyle: function (styleOpts) { + if (styleOpts.opacity) { + this.setOpacity(styleOpts.opacity); + } + return this; + }, + + // @method bringToFront(): this + // Brings the layer to the top of all overlays. + bringToFront: function () { + if (this._map) { + DomUtil.toFront(this._image); + } + return this; + }, + + // @method bringToBack(): this + // Brings the layer to the bottom of all overlays. + bringToBack: function () { + if (this._map) { + DomUtil.toBack(this._image); + } + return this; + }, + + // @method setUrl(url: String): this + // Changes the URL of the image. + setUrl: function (url) { + this._url = url; + + if (this._image) { + this._image.src = url; + } + return this; + }, + + // @method setBounds(bounds: LatLngBounds): this + // Update the bounds that this ImageOverlay covers + setBounds: function (bounds) { + this._bounds = toLatLngBounds(bounds); + + if (this._map) { + this._reset(); + } + return this; + }, + + getEvents: function () { + var events = { + zoom: this._reset, + viewreset: this._reset + }; + + if (this._zoomAnimated) { + events.zoomanim = this._animateZoom; + } + + return events; + }, + + // @method setZIndex(value: Number): this + // Changes the [zIndex](#imageoverlay-zindex) of the image overlay. + setZIndex: function (value) { + this.options.zIndex = value; + this._updateZIndex(); + return this; + }, + + // @method getBounds(): LatLngBounds + // Get the bounds that this ImageOverlay covers + getBounds: function () { + return this._bounds; + }, + + // @method getElement(): HTMLElement + // Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement) + // used by this overlay. + getElement: function () { + return this._image; + }, + + _initImage: function () { + var wasElementSupplied = this._url.tagName === 'IMG'; + var img = this._image = wasElementSupplied ? this._url : DomUtil.create('img'); + + DomUtil.addClass(img, 'leaflet-image-layer'); + if (this._zoomAnimated) { DomUtil.addClass(img, 'leaflet-zoom-animated'); } + if (this.options.className) { DomUtil.addClass(img, this.options.className); } + + img.onselectstart = Util.falseFn; + img.onmousemove = Util.falseFn; + + // @event load: Event + // Fired when the ImageOverlay layer has loaded its image + img.onload = Util.bind(this.fire, this, 'load'); + img.onerror = Util.bind(this._overlayOnError, this, 'error'); + + if (this.options.crossOrigin || this.options.crossOrigin === '') { + img.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin; + } + + if (this.options.zIndex) { + this._updateZIndex(); + } + + if (wasElementSupplied) { + this._url = img.src; + return; + } + + img.src = this._url; + img.alt = this.options.alt; + }, + + _animateZoom: function (e) { + var scale = this._map.getZoomScale(e.zoom), + offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min; + + DomUtil.setTransform(this._image, offset, scale); + }, + + _reset: function () { + var image = this._image, + bounds = new Bounds( + this._map.latLngToLayerPoint(this._bounds.getNorthWest()), + this._map.latLngToLayerPoint(this._bounds.getSouthEast())), + size = bounds.getSize(); + + DomUtil.setPosition(image, bounds.min); + + image.style.width = size.x + 'px'; + image.style.height = size.y + 'px'; + }, + + _updateOpacity: function () { + DomUtil.setOpacity(this._image, this.options.opacity); + }, + + _updateZIndex: function () { + if (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) { + this._image.style.zIndex = this.options.zIndex; + } + }, + + _overlayOnError: function () { + // @event error: Event + // Fired when the ImageOverlay layer fails to load its image + this.fire('error'); + + var errorUrl = this.options.errorOverlayUrl; + if (errorUrl && this._url !== errorUrl) { + this._url = errorUrl; + this._image.src = errorUrl; + } + } +}); + +// @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options) +// Instantiates an image overlay object given the URL of the image and the +// geographical bounds it is tied to. +export var imageOverlay = function (url, bounds, options) { + return new ImageOverlay(url, bounds, options); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Layer.Interactive.leafdoc b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Layer.Interactive.leafdoc new file mode 100644 index 000000000..11ed5a8cb --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Layer.Interactive.leafdoc @@ -0,0 +1,39 @@ +@class Interactive layer +@inherits Layer + +Some `Layer`s can be made interactive - when the user interacts +with such a layer, mouse events like `click` and `mouseover` can be handled. +Use the [event handling methods](#evented-method) to handle these events. + +@option interactive: Boolean = true +If `false`, the layer will not emit mouse events and will act as a part of the underlying map. + +@option bubblingMouseEvents: Boolean = true +When `true`, a mouse event on this layer will trigger the same event on the map +(unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used). + +@section Mouse events + +@event click: MouseEvent +Fired when the user clicks (or taps) the layer. + +@event dblclick: MouseEvent +Fired when the user double-clicks (or double-taps) the layer. + +@event mousedown: MouseEvent +Fired when the user pushes the mouse button on the layer. + +@event mouseup: MouseEvent +Fired when the user releases the mouse button pushed on the layer. + +@event mouseover: MouseEvent +Fired when the mouse enters the layer. + +@event mouseout: MouseEvent +Fired when the mouse leaves the layer. + +@event contextmenu: MouseEvent +Fired when the user right-clicks on the layer, prevents +default browser context menu from showing if there are listeners on +this event. Also fired on mobile when the user holds a single touch +for a second (also called long press). diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Layer.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Layer.js new file mode 100644 index 000000000..f8284a75d --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Layer.js @@ -0,0 +1,279 @@ +import {Evented} from '../core/Events'; +import {Map} from '../map/Map'; +import * as Util from '../core/Util'; + +/* + * @class Layer + * @inherits Evented + * @aka L.Layer + * @aka ILayer + * + * A set of methods from the Layer base class that all Leaflet layers use. + * Inherits all methods, options and events from `L.Evented`. + * + * @example + * + * ```js + * var layer = L.Marker(latlng).addTo(map); + * layer.addTo(map); + * layer.remove(); + * ``` + * + * @event add: Event + * Fired after the layer is added to a map + * + * @event remove: Event + * Fired after the layer is removed from a map + */ + + +export var Layer = Evented.extend({ + + // Classes extending `L.Layer` will inherit the following options: + options: { + // @option pane: String = 'overlayPane' + // By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default. + pane: 'overlayPane', + + // @option attribution: String = null + // String to be shown in the attribution control, e.g. "© OpenStreetMap contributors". It describes the layer data and is often a legal obligation towards copyright holders and tile providers. + attribution: null, + + bubblingMouseEvents: true + }, + + /* @section + * Classes extending `L.Layer` will inherit the following methods: + * + * @method addTo(map: Map|LayerGroup): this + * Adds the layer to the given map or layer group. + */ + addTo: function (map) { + map.addLayer(this); + return this; + }, + + // @method remove: this + // Removes the layer from the map it is currently active on. + remove: function () { + return this.removeFrom(this._map || this._mapToAdd); + }, + + // @method removeFrom(map: Map): this + // Removes the layer from the given map + removeFrom: function (obj) { + if (obj) { + obj.removeLayer(this); + } + return this; + }, + + // @method getPane(name? : String): HTMLElement + // Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer. + getPane: function (name) { + return this._map.getPane(name ? (this.options[name] || name) : this.options.pane); + }, + + addInteractiveTarget: function (targetEl) { + this._map._targets[Util.stamp(targetEl)] = this; + return this; + }, + + removeInteractiveTarget: function (targetEl) { + delete this._map._targets[Util.stamp(targetEl)]; + return this; + }, + + // @method getAttribution: String + // Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution). + getAttribution: function () { + return this.options.attribution; + }, + + _layerAdd: function (e) { + var map = e.target; + + // check in case layer gets added and then removed before the map is ready + if (!map.hasLayer(this)) { return; } + + this._map = map; + this._zoomAnimated = map._zoomAnimated; + + if (this.getEvents) { + var events = this.getEvents(); + map.on(events, this); + this.once('remove', function () { + map.off(events, this); + }, this); + } + + this.onAdd(map); + + if (this.getAttribution && map.attributionControl) { + map.attributionControl.addAttribution(this.getAttribution()); + } + + this.fire('add'); + map.fire('layeradd', {layer: this}); + } +}); + +/* @section Extension methods + * @uninheritable + * + * Every layer should extend from `L.Layer` and (re-)implement the following methods. + * + * @method onAdd(map: Map): this + * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer). + * + * @method onRemove(map: Map): this + * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer). + * + * @method getEvents(): Object + * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer. + * + * @method getAttribution(): String + * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible. + * + * @method beforeAdd(map: Map): this + * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only. + */ + + +/* @namespace Map + * @section Layer events + * + * @event layeradd: LayerEvent + * Fired when a new layer is added to the map. + * + * @event layerremove: LayerEvent + * Fired when some layer is removed from the map + * + * @section Methods for Layers and Controls + */ +Map.include({ + // @method addLayer(layer: Layer): this + // Adds the given layer to the map + addLayer: function (layer) { + if (!layer._layerAdd) { + throw new Error('The provided object is not a Layer.'); + } + + var id = Util.stamp(layer); + if (this._layers[id]) { return this; } + this._layers[id] = layer; + + layer._mapToAdd = this; + + if (layer.beforeAdd) { + layer.beforeAdd(this); + } + + this.whenReady(layer._layerAdd, layer); + + return this; + }, + + // @method removeLayer(layer: Layer): this + // Removes the given layer from the map. + removeLayer: function (layer) { + var id = Util.stamp(layer); + + if (!this._layers[id]) { return this; } + + if (this._loaded) { + layer.onRemove(this); + } + + if (layer.getAttribution && this.attributionControl) { + this.attributionControl.removeAttribution(layer.getAttribution()); + } + + delete this._layers[id]; + + if (this._loaded) { + this.fire('layerremove', {layer: layer}); + layer.fire('remove'); + } + + layer._map = layer._mapToAdd = null; + + return this; + }, + + // @method hasLayer(layer: Layer): Boolean + // Returns `true` if the given layer is currently added to the map + hasLayer: function (layer) { + return !!layer && (Util.stamp(layer) in this._layers); + }, + + /* @method eachLayer(fn: Function, context?: Object): this + * Iterates over the layers of the map, optionally specifying context of the iterator function. + * ``` + * map.eachLayer(function(layer){ + * layer.bindPopup('Hello'); + * }); + * ``` + */ + eachLayer: function (method, context) { + for (var i in this._layers) { + method.call(context, this._layers[i]); + } + return this; + }, + + _addLayers: function (layers) { + layers = layers ? (Util.isArray(layers) ? layers : [layers]) : []; + + for (var i = 0, len = layers.length; i < len; i++) { + this.addLayer(layers[i]); + } + }, + + _addZoomLimit: function (layer) { + if (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) { + this._zoomBoundLayers[Util.stamp(layer)] = layer; + this._updateZoomLevels(); + } + }, + + _removeZoomLimit: function (layer) { + var id = Util.stamp(layer); + + if (this._zoomBoundLayers[id]) { + delete this._zoomBoundLayers[id]; + this._updateZoomLevels(); + } + }, + + _updateZoomLevels: function () { + var minZoom = Infinity, + maxZoom = -Infinity, + oldZoomSpan = this._getZoomSpan(); + + for (var i in this._zoomBoundLayers) { + var options = this._zoomBoundLayers[i].options; + + minZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom); + maxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom); + } + + this._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom; + this._layersMinZoom = minZoom === Infinity ? undefined : minZoom; + + // @section Map state change events + // @event zoomlevelschange: Event + // Fired when the number of zoomlevels on the map is changed due + // to adding or removing a layer. + if (oldZoomSpan !== this._getZoomSpan()) { + this.fire('zoomlevelschange'); + } + + if (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) { + this.setZoom(this._layersMaxZoom); + } + if (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) { + this.setZoom(this._layersMinZoom); + } + } +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/LayerGroup.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/LayerGroup.js new file mode 100644 index 000000000..213ef2600 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/LayerGroup.js @@ -0,0 +1,158 @@ + +import {Layer} from './Layer'; +import * as Util from '../core/Util'; + +/* + * @class LayerGroup + * @aka L.LayerGroup + * @inherits Layer + * + * Used to group several layers and handle them as one. If you add it to the map, + * any layers added or removed from the group will be added/removed on the map as + * well. Extends `Layer`. + * + * @example + * + * ```js + * L.layerGroup([marker1, marker2]) + * .addLayer(polyline) + * .addTo(map); + * ``` + */ + +export var LayerGroup = Layer.extend({ + + initialize: function (layers, options) { + Util.setOptions(this, options); + + this._layers = {}; + + var i, len; + + if (layers) { + for (i = 0, len = layers.length; i < len; i++) { + this.addLayer(layers[i]); + } + } + }, + + // @method addLayer(layer: Layer): this + // Adds the given layer to the group. + addLayer: function (layer) { + var id = this.getLayerId(layer); + + this._layers[id] = layer; + + if (this._map) { + this._map.addLayer(layer); + } + + return this; + }, + + // @method removeLayer(layer: Layer): this + // Removes the given layer from the group. + // @alternative + // @method removeLayer(id: Number): this + // Removes the layer with the given internal ID from the group. + removeLayer: function (layer) { + var id = layer in this._layers ? layer : this.getLayerId(layer); + + if (this._map && this._layers[id]) { + this._map.removeLayer(this._layers[id]); + } + + delete this._layers[id]; + + return this; + }, + + // @method hasLayer(layer: Layer): Boolean + // Returns `true` if the given layer is currently added to the group. + // @alternative + // @method hasLayer(id: Number): Boolean + // Returns `true` if the given internal ID is currently added to the group. + hasLayer: function (layer) { + return !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers); + }, + + // @method clearLayers(): this + // Removes all the layers from the group. + clearLayers: function () { + return this.eachLayer(this.removeLayer, this); + }, + + // @method invoke(methodName: String, …): this + // Calls `methodName` on every layer contained in this group, passing any + // additional parameters. Has no effect if the layers contained do not + // implement `methodName`. + invoke: function (methodName) { + var args = Array.prototype.slice.call(arguments, 1), + i, layer; + + for (i in this._layers) { + layer = this._layers[i]; + + if (layer[methodName]) { + layer[methodName].apply(layer, args); + } + } + + return this; + }, + + onAdd: function (map) { + this.eachLayer(map.addLayer, map); + }, + + onRemove: function (map) { + this.eachLayer(map.removeLayer, map); + }, + + // @method eachLayer(fn: Function, context?: Object): this + // Iterates over the layers of the group, optionally specifying context of the iterator function. + // ```js + // group.eachLayer(function (layer) { + // layer.bindPopup('Hello'); + // }); + // ``` + eachLayer: function (method, context) { + for (var i in this._layers) { + method.call(context, this._layers[i]); + } + return this; + }, + + // @method getLayer(id: Number): Layer + // Returns the layer with the given internal ID. + getLayer: function (id) { + return this._layers[id]; + }, + + // @method getLayers(): Layer[] + // Returns an array of all the layers added to the group. + getLayers: function () { + var layers = []; + this.eachLayer(layers.push, layers); + return layers; + }, + + // @method setZIndex(zIndex: Number): this + // Calls `setZIndex` on every layer contained in this group, passing the z-index. + setZIndex: function (zIndex) { + return this.invoke('setZIndex', zIndex); + }, + + // @method getLayerId(layer: Layer): Number + // Returns the internal ID for a layer + getLayerId: function (layer) { + return Util.stamp(layer); + } +}); + + +// @factory L.layerGroup(layers?: Layer[], options?: Object) +// Create a layer group, optionally given an initial set of layers and an `options` object. +export var layerGroup = function (layers, options) { + return new LayerGroup(layers, options); +}; diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Popup.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Popup.js new file mode 100644 index 000000000..4eed622d1 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Popup.js @@ -0,0 +1,533 @@ +import {DivOverlay} from './DivOverlay'; +import * as DomEvent from '../dom/DomEvent'; +import * as DomUtil from '../dom/DomUtil'; +import {Point, toPoint} from '../geometry/Point'; +import {Map} from '../map/Map'; +import {Layer} from './Layer'; +import {FeatureGroup} from './FeatureGroup'; +import * as Util from '../core/Util'; +import {Path} from './vector/Path'; + +/* + * @class Popup + * @inherits DivOverlay + * @aka L.Popup + * Used to open popups in certain places of the map. Use [Map.openPopup](#map-openpopup) to + * open popups while making sure that only one popup is open at one time + * (recommended for usability), or use [Map.addLayer](#map-addlayer) to open as many as you want. + * + * @example + * + * If you want to just bind a popup to marker click and then open it, it's really easy: + * + * ```js + * marker.bindPopup(popupContent).openPopup(); + * ``` + * Path overlays like polylines also have a `bindPopup` method. + * Here's a more complicated way to open a popup on a map: + * + * ```js + * var popup = L.popup() + * .setLatLng(latlng) + * .setContent('

Hello world!
This is a nice popup.

') + * .openOn(map); + * ``` + */ + + +// @namespace Popup +export var Popup = DivOverlay.extend({ + + // @section + // @aka Popup options + options: { + // @option maxWidth: Number = 300 + // Max width of the popup, in pixels. + maxWidth: 300, + + // @option minWidth: Number = 50 + // Min width of the popup, in pixels. + minWidth: 50, + + // @option maxHeight: Number = null + // If set, creates a scrollable container of the given height + // inside a popup if its content exceeds it. + maxHeight: null, + + // @option autoPan: Boolean = true + // Set it to `false` if you don't want the map to do panning animation + // to fit the opened popup. + autoPan: true, + + // @option autoPanPaddingTopLeft: Point = null + // The margin between the popup and the top left corner of the map + // view after autopanning was performed. + autoPanPaddingTopLeft: null, + + // @option autoPanPaddingBottomRight: Point = null + // The margin between the popup and the bottom right corner of the map + // view after autopanning was performed. + autoPanPaddingBottomRight: null, + + // @option autoPanPadding: Point = Point(5, 5) + // Equivalent of setting both top left and bottom right autopan padding to the same value. + autoPanPadding: [5, 5], + + // @option keepInView: Boolean = false + // Set it to `true` if you want to prevent users from panning the popup + // off of the screen while it is open. + keepInView: false, + + // @option closeButton: Boolean = true + // Controls the presence of a close button in the popup. + closeButton: true, + + // @option autoClose: Boolean = true + // Set it to `false` if you want to override the default behavior of + // the popup closing when another popup is opened. + autoClose: true, + + // @option closeOnEscapeKey: Boolean = true + // Set it to `false` if you want to override the default behavior of + // the ESC key for closing of the popup. + closeOnEscapeKey: true, + + // @option closeOnClick: Boolean = * + // Set it if you want to override the default behavior of the popup closing when user clicks + // on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option. + + // @option className: String = '' + // A custom CSS class name to assign to the popup. + className: '' + }, + + // @namespace Popup + // @method openOn(map: Map): this + // Adds the popup to the map and closes the previous one. The same as `map.openPopup(popup)`. + openOn: function (map) { + map.openPopup(this); + return this; + }, + + onAdd: function (map) { + DivOverlay.prototype.onAdd.call(this, map); + + // @namespace Map + // @section Popup events + // @event popupopen: PopupEvent + // Fired when a popup is opened in the map + map.fire('popupopen', {popup: this}); + + if (this._source) { + // @namespace Layer + // @section Popup events + // @event popupopen: PopupEvent + // Fired when a popup bound to this layer is opened + this._source.fire('popupopen', {popup: this}, true); + // For non-path layers, we toggle the popup when clicking + // again the layer, so prevent the map to reopen it. + if (!(this._source instanceof Path)) { + this._source.on('preclick', DomEvent.stopPropagation); + } + } + }, + + onRemove: function (map) { + DivOverlay.prototype.onRemove.call(this, map); + + // @namespace Map + // @section Popup events + // @event popupclose: PopupEvent + // Fired when a popup in the map is closed + map.fire('popupclose', {popup: this}); + + if (this._source) { + // @namespace Layer + // @section Popup events + // @event popupclose: PopupEvent + // Fired when a popup bound to this layer is closed + this._source.fire('popupclose', {popup: this}, true); + if (!(this._source instanceof Path)) { + this._source.off('preclick', DomEvent.stopPropagation); + } + } + }, + + getEvents: function () { + var events = DivOverlay.prototype.getEvents.call(this); + + if (this.options.closeOnClick !== undefined ? this.options.closeOnClick : this._map.options.closePopupOnClick) { + events.preclick = this._close; + } + + if (this.options.keepInView) { + events.moveend = this._adjustPan; + } + + return events; + }, + + _close: function () { + if (this._map) { + this._map.closePopup(this); + } + }, + + _initLayout: function () { + var prefix = 'leaflet-popup', + container = this._container = DomUtil.create('div', + prefix + ' ' + (this.options.className || '') + + ' leaflet-zoom-animated'); + + var wrapper = this._wrapper = DomUtil.create('div', prefix + '-content-wrapper', container); + this._contentNode = DomUtil.create('div', prefix + '-content', wrapper); + + DomEvent.disableClickPropagation(wrapper); + DomEvent.disableScrollPropagation(this._contentNode); + DomEvent.on(wrapper, 'contextmenu', DomEvent.stopPropagation); + + this._tipContainer = DomUtil.create('div', prefix + '-tip-container', container); + this._tip = DomUtil.create('div', prefix + '-tip', this._tipContainer); + + if (this.options.closeButton) { + var closeButton = this._closeButton = DomUtil.create('a', prefix + '-close-button', container); + closeButton.href = '#close'; + closeButton.innerHTML = '×'; + + DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this); + } + }, + + _updateLayout: function () { + var container = this._contentNode, + style = container.style; + + style.width = ''; + style.whiteSpace = 'nowrap'; + + var width = container.offsetWidth; + width = Math.min(width, this.options.maxWidth); + width = Math.max(width, this.options.minWidth); + + style.width = (width + 1) + 'px'; + style.whiteSpace = ''; + + style.height = ''; + + var height = container.offsetHeight, + maxHeight = this.options.maxHeight, + scrolledClass = 'leaflet-popup-scrolled'; + + if (maxHeight && height > maxHeight) { + style.height = maxHeight + 'px'; + DomUtil.addClass(container, scrolledClass); + } else { + DomUtil.removeClass(container, scrolledClass); + } + + this._containerWidth = this._container.offsetWidth; + }, + + _animateZoom: function (e) { + var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center), + anchor = this._getAnchor(); + DomUtil.setPosition(this._container, pos.add(anchor)); + }, + + _adjustPan: function () { + if (!this.options.autoPan) { return; } + if (this._map._panAnim) { this._map._panAnim.stop(); } + + var map = this._map, + marginBottom = parseInt(DomUtil.getStyle(this._container, 'marginBottom'), 10) || 0, + containerHeight = this._container.offsetHeight + marginBottom, + containerWidth = this._containerWidth, + layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom); + + layerPos._add(DomUtil.getPosition(this._container)); + + var containerPos = map.layerPointToContainerPoint(layerPos), + padding = toPoint(this.options.autoPanPadding), + paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding), + paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding), + size = map.getSize(), + dx = 0, + dy = 0; + + if (containerPos.x + containerWidth + paddingBR.x > size.x) { // right + dx = containerPos.x + containerWidth - size.x + paddingBR.x; + } + if (containerPos.x - dx - paddingTL.x < 0) { // left + dx = containerPos.x - paddingTL.x; + } + if (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom + dy = containerPos.y + containerHeight - size.y + paddingBR.y; + } + if (containerPos.y - dy - paddingTL.y < 0) { // top + dy = containerPos.y - paddingTL.y; + } + + // @namespace Map + // @section Popup events + // @event autopanstart: Event + // Fired when the map starts autopanning when opening a popup. + if (dx || dy) { + map + .fire('autopanstart') + .panBy([dx, dy]); + } + }, + + _onCloseButtonClick: function (e) { + this._close(); + DomEvent.stop(e); + }, + + _getAnchor: function () { + // Where should we anchor the popup on the source layer? + return toPoint(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]); + } + +}); + +// @namespace Popup +// @factory L.popup(options?: Popup options, source?: Layer) +// Instantiates a `Popup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers. +export var popup = function (options, source) { + return new Popup(options, source); +}; + + +/* @namespace Map + * @section Interaction Options + * @option closePopupOnClick: Boolean = true + * Set it to `false` if you don't want popups to close when user clicks the map. + */ +Map.mergeOptions({ + closePopupOnClick: true +}); + + +// @namespace Map +// @section Methods for Layers and Controls +Map.include({ + // @method openPopup(popup: Popup): this + // Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability). + // @alternative + // @method openPopup(content: String|HTMLElement, latlng: LatLng, options?: Popup options): this + // Creates a popup with the specified content and options and opens it in the given point on a map. + openPopup: function (popup, latlng, options) { + if (!(popup instanceof Popup)) { + popup = new Popup(options).setContent(popup); + } + + if (latlng) { + popup.setLatLng(latlng); + } + + if (this.hasLayer(popup)) { + return this; + } + + if (this._popup && this._popup.options.autoClose) { + this.closePopup(); + } + + this._popup = popup; + return this.addLayer(popup); + }, + + // @method closePopup(popup?: Popup): this + // Closes the popup previously opened with [openPopup](#map-openpopup) (or the given one). + closePopup: function (popup) { + if (!popup || popup === this._popup) { + popup = this._popup; + this._popup = null; + } + if (popup) { + this.removeLayer(popup); + } + return this; + } +}); + +/* + * @namespace Layer + * @section Popup methods example + * + * All layers share a set of methods convenient for binding popups to it. + * + * ```js + * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map); + * layer.openPopup(); + * layer.closePopup(); + * ``` + * + * Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened. + */ + +// @section Popup methods +Layer.include({ + + // @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this + // Binds a popup to the layer with the passed `content` and sets up the + // necessary event listeners. If a `Function` is passed it will receive + // the layer as the first argument and should return a `String` or `HTMLElement`. + bindPopup: function (content, options) { + + if (content instanceof Popup) { + Util.setOptions(content, options); + this._popup = content; + content._source = this; + } else { + if (!this._popup || options) { + this._popup = new Popup(options, this); + } + this._popup.setContent(content); + } + + if (!this._popupHandlersAdded) { + this.on({ + click: this._openPopup, + keypress: this._onKeyPress, + remove: this.closePopup, + move: this._movePopup + }); + this._popupHandlersAdded = true; + } + + return this; + }, + + // @method unbindPopup(): this + // Removes the popup previously bound with `bindPopup`. + unbindPopup: function () { + if (this._popup) { + this.off({ + click: this._openPopup, + keypress: this._onKeyPress, + remove: this.closePopup, + move: this._movePopup + }); + this._popupHandlersAdded = false; + this._popup = null; + } + return this; + }, + + // @method openPopup(latlng?: LatLng): this + // Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed. + openPopup: function (layer, latlng) { + if (!(layer instanceof Layer)) { + latlng = layer; + layer = this; + } + + if (layer instanceof FeatureGroup) { + for (var id in this._layers) { + layer = this._layers[id]; + break; + } + } + + if (!latlng) { + latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng(); + } + + if (this._popup && this._map) { + // set popup source to this layer + this._popup._source = layer; + + // update the popup (content, layout, ect...) + this._popup.update(); + + // open the popup on the map + this._map.openPopup(this._popup, latlng); + } + + return this; + }, + + // @method closePopup(): this + // Closes the popup bound to this layer if it is open. + closePopup: function () { + if (this._popup) { + this._popup._close(); + } + return this; + }, + + // @method togglePopup(): this + // Opens or closes the popup bound to this layer depending on its current state. + togglePopup: function (target) { + if (this._popup) { + if (this._popup._map) { + this.closePopup(); + } else { + this.openPopup(target); + } + } + return this; + }, + + // @method isPopupOpen(): boolean + // Returns `true` if the popup bound to this layer is currently open. + isPopupOpen: function () { + return (this._popup ? this._popup.isOpen() : false); + }, + + // @method setPopupContent(content: String|HTMLElement|Popup): this + // Sets the content of the popup bound to this layer. + setPopupContent: function (content) { + if (this._popup) { + this._popup.setContent(content); + } + return this; + }, + + // @method getPopup(): Popup + // Returns the popup bound to this layer. + getPopup: function () { + return this._popup; + }, + + _openPopup: function (e) { + var layer = e.layer || e.target; + + if (!this._popup) { + return; + } + + if (!this._map) { + return; + } + + // prevent map click + DomEvent.stop(e); + + // if this inherits from Path its a vector and we can just + // open the popup at the new location + if (layer instanceof Path) { + this.openPopup(e.layer || e.target, e.latlng); + return; + } + + // otherwise treat it like a marker and figure out + // if we should toggle it open/closed + if (this._map.hasLayer(this._popup) && this._popup._source === layer) { + this.closePopup(); + } else { + this.openPopup(layer, e.latlng); + } + }, + + _movePopup: function (e) { + this._popup.setLatLng(e.latlng); + }, + + _onKeyPress: function (e) { + if (e.originalEvent.keyCode === 13) { + this._openPopup(e); + } + } +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Tooltip.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Tooltip.js new file mode 100644 index 000000000..5eb83f9bc --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/Tooltip.js @@ -0,0 +1,418 @@ + +import * as Browser from '../core/Browser'; +import {DivOverlay} from './DivOverlay'; +import {toPoint} from '../geometry/Point'; +import {Map} from '../map/Map'; +import {Layer} from './Layer'; +import {FeatureGroup} from './FeatureGroup'; +import * as Util from '../core/Util'; +import * as DomUtil from '../dom/DomUtil'; + +/* + * @class Tooltip + * @inherits DivOverlay + * @aka L.Tooltip + * Used to display small texts on top of map layers. + * + * @example + * + * ```js + * marker.bindTooltip("my tooltip text").openTooltip(); + * ``` + * Note about tooltip offset. Leaflet takes two options in consideration + * for computing tooltip offsetting: + * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip. + * Add a positive x offset to move the tooltip to the right, and a positive y offset to + * move it to the bottom. Negatives will move to the left and top. + * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You + * should adapt this value if you use a custom icon. + */ + + +// @namespace Tooltip +export var Tooltip = DivOverlay.extend({ + + // @section + // @aka Tooltip options + options: { + // @option pane: String = 'tooltipPane' + // `Map pane` where the tooltip will be added. + pane: 'tooltipPane', + + // @option offset: Point = Point(0, 0) + // Optional offset of the tooltip position. + offset: [0, 0], + + // @option direction: String = 'auto' + // Direction where to open the tooltip. Possible values are: `right`, `left`, + // `top`, `bottom`, `center`, `auto`. + // `auto` will dynamically switch between `right` and `left` according to the tooltip + // position on the map. + direction: 'auto', + + // @option permanent: Boolean = false + // Whether to open the tooltip permanently or only on mouseover. + permanent: false, + + // @option sticky: Boolean = false + // If true, the tooltip will follow the mouse instead of being fixed at the feature center. + sticky: false, + + // @option interactive: Boolean = false + // If true, the tooltip will listen to the feature events. + interactive: false, + + // @option opacity: Number = 0.9 + // Tooltip container opacity. + opacity: 0.9 + }, + + onAdd: function (map) { + DivOverlay.prototype.onAdd.call(this, map); + this.setOpacity(this.options.opacity); + + // @namespace Map + // @section Tooltip events + // @event tooltipopen: TooltipEvent + // Fired when a tooltip is opened in the map. + map.fire('tooltipopen', {tooltip: this}); + + if (this._source) { + // @namespace Layer + // @section Tooltip events + // @event tooltipopen: TooltipEvent + // Fired when a tooltip bound to this layer is opened. + this._source.fire('tooltipopen', {tooltip: this}, true); + } + }, + + onRemove: function (map) { + DivOverlay.prototype.onRemove.call(this, map); + + // @namespace Map + // @section Tooltip events + // @event tooltipclose: TooltipEvent + // Fired when a tooltip in the map is closed. + map.fire('tooltipclose', {tooltip: this}); + + if (this._source) { + // @namespace Layer + // @section Tooltip events + // @event tooltipclose: TooltipEvent + // Fired when a tooltip bound to this layer is closed. + this._source.fire('tooltipclose', {tooltip: this}, true); + } + }, + + getEvents: function () { + var events = DivOverlay.prototype.getEvents.call(this); + + if (Browser.touch && !this.options.permanent) { + events.preclick = this._close; + } + + return events; + }, + + _close: function () { + if (this._map) { + this._map.closeTooltip(this); + } + }, + + _initLayout: function () { + var prefix = 'leaflet-tooltip', + className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide'); + + this._contentNode = this._container = DomUtil.create('div', className); + }, + + _updateLayout: function () {}, + + _adjustPan: function () {}, + + _setPosition: function (pos) { + var map = this._map, + container = this._container, + centerPoint = map.latLngToContainerPoint(map.getCenter()), + tooltipPoint = map.layerPointToContainerPoint(pos), + direction = this.options.direction, + tooltipWidth = container.offsetWidth, + tooltipHeight = container.offsetHeight, + offset = toPoint(this.options.offset), + anchor = this._getAnchor(); + + if (direction === 'top') { + pos = pos.add(toPoint(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y, true)); + } else if (direction === 'bottom') { + pos = pos.subtract(toPoint(tooltipWidth / 2 - offset.x, -offset.y, true)); + } else if (direction === 'center') { + pos = pos.subtract(toPoint(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y, true)); + } else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) { + direction = 'right'; + pos = pos.add(toPoint(offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y, true)); + } else { + direction = 'left'; + pos = pos.subtract(toPoint(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y, true)); + } + + DomUtil.removeClass(container, 'leaflet-tooltip-right'); + DomUtil.removeClass(container, 'leaflet-tooltip-left'); + DomUtil.removeClass(container, 'leaflet-tooltip-top'); + DomUtil.removeClass(container, 'leaflet-tooltip-bottom'); + DomUtil.addClass(container, 'leaflet-tooltip-' + direction); + DomUtil.setPosition(container, pos); + }, + + _updatePosition: function () { + var pos = this._map.latLngToLayerPoint(this._latlng); + this._setPosition(pos); + }, + + setOpacity: function (opacity) { + this.options.opacity = opacity; + + if (this._container) { + DomUtil.setOpacity(this._container, opacity); + } + }, + + _animateZoom: function (e) { + var pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center); + this._setPosition(pos); + }, + + _getAnchor: function () { + // Where should we anchor the tooltip on the source layer? + return toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]); + } + +}); + +// @namespace Tooltip +// @factory L.tooltip(options?: Tooltip options, source?: Layer) +// Instantiates a Tooltip object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers. +export var tooltip = function (options, source) { + return new Tooltip(options, source); +}; + +// @namespace Map +// @section Methods for Layers and Controls +Map.include({ + + // @method openTooltip(tooltip: Tooltip): this + // Opens the specified tooltip. + // @alternative + // @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this + // Creates a tooltip with the specified content and options and open it. + openTooltip: function (tooltip, latlng, options) { + if (!(tooltip instanceof Tooltip)) { + tooltip = new Tooltip(options).setContent(tooltip); + } + + if (latlng) { + tooltip.setLatLng(latlng); + } + + if (this.hasLayer(tooltip)) { + return this; + } + + return this.addLayer(tooltip); + }, + + // @method closeTooltip(tooltip?: Tooltip): this + // Closes the tooltip given as parameter. + closeTooltip: function (tooltip) { + if (tooltip) { + this.removeLayer(tooltip); + } + return this; + } + +}); + +/* + * @namespace Layer + * @section Tooltip methods example + * + * All layers share a set of methods convenient for binding tooltips to it. + * + * ```js + * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map); + * layer.openTooltip(); + * layer.closeTooltip(); + * ``` + */ + +// @section Tooltip methods +Layer.include({ + + // @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this + // Binds a tooltip to the layer with the passed `content` and sets up the + // necessary event listeners. If a `Function` is passed it will receive + // the layer as the first argument and should return a `String` or `HTMLElement`. + bindTooltip: function (content, options) { + + if (content instanceof Tooltip) { + Util.setOptions(content, options); + this._tooltip = content; + content._source = this; + } else { + if (!this._tooltip || options) { + this._tooltip = new Tooltip(options, this); + } + this._tooltip.setContent(content); + + } + + this._initTooltipInteractions(); + + if (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) { + this.openTooltip(); + } + + return this; + }, + + // @method unbindTooltip(): this + // Removes the tooltip previously bound with `bindTooltip`. + unbindTooltip: function () { + if (this._tooltip) { + this._initTooltipInteractions(true); + this.closeTooltip(); + this._tooltip = null; + } + return this; + }, + + _initTooltipInteractions: function (remove) { + if (!remove && this._tooltipHandlersAdded) { return; } + var onOff = remove ? 'off' : 'on', + events = { + remove: this.closeTooltip, + move: this._moveTooltip + }; + if (!this._tooltip.options.permanent) { + events.mouseover = this._openTooltip; + events.mouseout = this.closeTooltip; + if (this._tooltip.options.sticky) { + events.mousemove = this._moveTooltip; + } + if (Browser.touch) { + events.click = this._openTooltip; + } + } else { + events.add = this._openTooltip; + } + this[onOff](events); + this._tooltipHandlersAdded = !remove; + }, + + // @method openTooltip(latlng?: LatLng): this + // Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed. + openTooltip: function (layer, latlng) { + if (!(layer instanceof Layer)) { + latlng = layer; + layer = this; + } + + if (layer instanceof FeatureGroup) { + for (var id in this._layers) { + layer = this._layers[id]; + break; + } + } + + if (!latlng) { + latlng = layer.getCenter ? layer.getCenter() : layer.getLatLng(); + } + + if (this._tooltip && this._map) { + + // set tooltip source to this layer + this._tooltip._source = layer; + + // update the tooltip (content, layout, ect...) + this._tooltip.update(); + + // open the tooltip on the map + this._map.openTooltip(this._tooltip, latlng); + + // Tooltip container may not be defined if not permanent and never + // opened. + if (this._tooltip.options.interactive && this._tooltip._container) { + DomUtil.addClass(this._tooltip._container, 'leaflet-clickable'); + this.addInteractiveTarget(this._tooltip._container); + } + } + + return this; + }, + + // @method closeTooltip(): this + // Closes the tooltip bound to this layer if it is open. + closeTooltip: function () { + if (this._tooltip) { + this._tooltip._close(); + if (this._tooltip.options.interactive && this._tooltip._container) { + DomUtil.removeClass(this._tooltip._container, 'leaflet-clickable'); + this.removeInteractiveTarget(this._tooltip._container); + } + } + return this; + }, + + // @method toggleTooltip(): this + // Opens or closes the tooltip bound to this layer depending on its current state. + toggleTooltip: function (target) { + if (this._tooltip) { + if (this._tooltip._map) { + this.closeTooltip(); + } else { + this.openTooltip(target); + } + } + return this; + }, + + // @method isTooltipOpen(): boolean + // Returns `true` if the tooltip bound to this layer is currently open. + isTooltipOpen: function () { + return this._tooltip.isOpen(); + }, + + // @method setTooltipContent(content: String|HTMLElement|Tooltip): this + // Sets the content of the tooltip bound to this layer. + setTooltipContent: function (content) { + if (this._tooltip) { + this._tooltip.setContent(content); + } + return this; + }, + + // @method getTooltip(): Tooltip + // Returns the tooltip bound to this layer. + getTooltip: function () { + return this._tooltip; + }, + + _openTooltip: function (e) { + var layer = e.layer || e.target; + + if (!this._tooltip || !this._map) { + return; + } + this.openTooltip(layer, this._tooltip.options.sticky ? e.latlng : undefined); + }, + + _moveTooltip: function (e) { + var latlng = e.latlng, containerPoint, layerPoint; + if (this._tooltip.options.sticky && e.originalEvent) { + containerPoint = this._map.mouseEventToContainerPoint(e.originalEvent); + layerPoint = this._map.containerPointToLayerPoint(containerPoint); + latlng = this._map.layerPointToLatLng(layerPoint); + } + this._tooltip.setLatLng(latlng); + } +}); diff --git a/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/VideoOverlay.js b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/VideoOverlay.js new file mode 100644 index 000000000..366e519a8 --- /dev/null +++ b/vendor/assets/javascripts/Leaflet-1.4.0/src/layer/VideoOverlay.js @@ -0,0 +1,86 @@ +import {ImageOverlay} from './ImageOverlay'; +import * as DomUtil from '../dom/DomUtil'; +import * as Util from '../core/Util'; + +/* + * @class VideoOverlay + * @aka L.VideoOverlay + * @inherits ImageOverlay + * + * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`. + * + * A video overlay uses the [`