├── public ├── CNAME └── favicon.ico ├── .htmlnanorc ├── src ├── exit.png ├── walk.png ├── stations.png ├── index.webmanifest ├── sw.js ├── index.html ├── index.css ├── stations.json ├── index.js └── sg-rail-walks.geo.json ├── .gitignore ├── assets ├── favicon.png ├── preview.gif ├── preview.jpg ├── icon-144.png ├── icon-192.png ├── icon-512.png ├── logo.svg └── icon.svg ├── design ├── v2.afdesign └── icon.afdesign ├── screenshots ├── screenshot-1.png ├── screenshot-2.png ├── screenshot-3.png ├── screenshot-4.png ├── screenshot-5.png ├── screenshot-6.png ├── screenshot-7.png ├── screenshot-8.png ├── screenshot-9.png ├── screenshot-10.png └── screenshot-11.png ├── .parcelrc ├── .proxyrc.js ├── scripts ├── gen-stations-sprite.js └── sprite.json ├── .github └── workflows │ └── main.yml ├── package.json ├── service-worker.js └── README.md /public/CNAME: -------------------------------------------------------------------------------- 1 | railrouter.sg 2 | -------------------------------------------------------------------------------- /.htmlnanorc: -------------------------------------------------------------------------------- 1 | { 2 | "minifySvg": false 3 | } -------------------------------------------------------------------------------- /src/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/src/exit.png -------------------------------------------------------------------------------- /src/walk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/src/walk.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | scripts/config.json 4 | .parcel-cache 5 | dist -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/assets/favicon.png -------------------------------------------------------------------------------- /assets/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/assets/preview.gif -------------------------------------------------------------------------------- /assets/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/assets/preview.jpg -------------------------------------------------------------------------------- /design/v2.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/design/v2.afdesign -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/stations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/src/stations.png -------------------------------------------------------------------------------- /assets/icon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/assets/icon-144.png -------------------------------------------------------------------------------- /assets/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/assets/icon-192.png -------------------------------------------------------------------------------- /assets/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/assets/icon-512.png -------------------------------------------------------------------------------- /design/icon.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/design/icon.afdesign -------------------------------------------------------------------------------- /screenshots/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-1.png -------------------------------------------------------------------------------- /screenshots/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-2.png -------------------------------------------------------------------------------- /screenshots/screenshot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-3.png -------------------------------------------------------------------------------- /screenshots/screenshot-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-4.png -------------------------------------------------------------------------------- /screenshots/screenshot-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-5.png -------------------------------------------------------------------------------- /screenshots/screenshot-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-6.png -------------------------------------------------------------------------------- /screenshots/screenshot-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-7.png -------------------------------------------------------------------------------- /screenshots/screenshot-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-8.png -------------------------------------------------------------------------------- /screenshots/screenshot-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-9.png -------------------------------------------------------------------------------- /screenshots/screenshot-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-10.png -------------------------------------------------------------------------------- /screenshots/screenshot-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheeaun/railrouter-sg/HEAD/screenshots/screenshot-11.png -------------------------------------------------------------------------------- /.parcelrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@parcel/config-default", 3 | "transformers": { 4 | "*.{jpg,png,svg,geo.json}": ["@parcel/transformer-raw"] 5 | } 6 | } -------------------------------------------------------------------------------- /.proxyrc.js: -------------------------------------------------------------------------------- 1 | // Bug: Cross Origin Resource Policy with Parcel 2 | // https://github.com/parcel-bundler/parcel/issues/6561#issuecomment-878344133 3 | module.exports = function (app) { 4 | app.use((req, res, next) => { 5 | res.removeHeader('Cross-Origin-Resource-Policy'); 6 | res.removeHeader('Cross-Origin-Embedder-Policy'); 7 | next(); 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /scripts/gen-stations-sprite.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const sprite = require('./sprite.json'); 3 | 4 | const { data } = sprite; 5 | 6 | const output = data.map((d) => { 7 | const { sprite, w, h, x, y } = d; 8 | return [sprite.replace(/\-svg$/i, ''), x, y, w, h]; 9 | }); 10 | 11 | fs.writeFileSync('src/stations.json', JSON.stringify(output, null, '\t')); 12 | -------------------------------------------------------------------------------- /src/index.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "RailRouter SG", 3 | "name": "RailRouter SG", 4 | "description": "Explore MRT and LRT rail routes in Singapore", 5 | "display": "standalone", 6 | "theme_color": "teal", 7 | "scope": "/", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "../assets/icon-192.png", 12 | "sizes": "192x192", 13 | "type": "image/png" 14 | }, 15 | { 16 | "src": "../assets/icon-512.png", 17 | "sizes": "512x512", 18 | "type": "image/png" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | build-and-deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout 🛎️ 11 | uses: actions/checkout@v2 12 | 13 | - name: Install and Build 🔧 14 | run: | 15 | npm ci 16 | npm run build 17 | - name: Deploy 🚀 18 | uses: JamesIves/github-pages-deploy-action@releases/v4 19 | with: 20 | branch: gh-pages # The branch the action should deploy to. 21 | folder: dist # The folder the action should deploy. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "railrouter-sg", 3 | "version": "3.0.0", 4 | "description": "Explore MRT and LRT rail routes in Singapore", 5 | "keywords": [ 6 | "singapore", 7 | "mrt", 8 | "lrt", 9 | "train", 10 | "metro", 11 | "subway", 12 | "map", 13 | "transport" 14 | ], 15 | "author": "Lim Chee Aun (http://cheeaun.com/)", 16 | "license": "MIT", 17 | "scripts": { 18 | "start": "parcel serve ./src/index.html --no-hmr", 19 | "start-https": "parcel serve ./src/index.html --no-hmr --https", 20 | "build": "parcel build ./src/index.html --no-cache", 21 | "postbuild": "cpy public/* dist" 22 | }, 23 | "dependencies": { 24 | "@mapbox/mapbox-gl-language": "~1.0.0", 25 | "fuse.js": "~6.6.2", 26 | "mapbox-gl": "~2.10.0", 27 | "regenerator-runtime": "~0.13.10", 28 | "workbox-cacheable-response": "~6.5.4", 29 | "workbox-expiration": "~6.5.4", 30 | "workbox-google-analytics": "~6.5.4", 31 | "workbox-routing": "~6.5.4", 32 | "workbox-strategies": "~6.5.4" 33 | }, 34 | "devDependencies": { 35 | "@parcel/packager-raw-url": "~2.8.0", 36 | "@parcel/transformer-webmanifest": "~2.8.0", 37 | "cpy-cli": "~4.2.0", 38 | "parcel": "~2.8.0" 39 | }, 40 | "browserslist": [ 41 | ">0.25%", 42 | "not dead", 43 | "not ie 11", 44 | "not chrome < 51", 45 | "not op_mini all", 46 | "not Android > 1", 47 | "not safari < 10" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /service-worker.js: -------------------------------------------------------------------------------- 1 | self.addEventListener('install', function(event){ 2 | console.log('Install'); 3 | }); 4 | 5 | self.addEventListener('activate', function(event){ 6 | console.log('Activate'); 7 | }); 8 | 9 | var cacheName = 'railroutersg-v2'; 10 | caches.delete('railroutersg-v1'); // Delete the old one 11 | var successResponses = /^0|([123]\d\d)|(40[14567])|410$/; 12 | 13 | function fetchAndCache(request){ 14 | return fetch(request.clone()).then(function(response){ 15 | if (request.method == 'GET' && response && successResponses.test(response.status) && (response.type == 'basic' || /\.(js|png|ttf|woff|woff2)/i.test(request.url) || /fonts\.googleapis\.com/i.test(request.url))){ 16 | console.log('Cache', request.url); 17 | caches.open(cacheName).then(function(cache){ 18 | cache.put(request, response); 19 | }); 20 | } 21 | return response.clone(); 22 | }); 23 | }; 24 | 25 | function cacheOnly(request){ 26 | return caches.open(cacheName).then(function(cache){ 27 | return cache.match(request); 28 | }); 29 | }; 30 | 31 | // Fastest strategy from https://github.com/GoogleChrome/sw-toolbox 32 | self.addEventListener('fetch', function(event){ 33 | var request = event.request; 34 | var url = request.url; 35 | event.respondWith(new Promise(function(resolve, reject){ 36 | var rejected = false; 37 | var reasons = []; 38 | 39 | var maybeReject = function(reason){ 40 | reasons.push(reason.toString()); 41 | if (rejected){ 42 | reject(new Error('Both cache and network failed: "' + reasons.join('", "') + '"')); 43 | } else { 44 | rejected = true; 45 | } 46 | }; 47 | 48 | var maybeResolve = function(result){ 49 | if (result instanceof Response){ 50 | resolve(result); 51 | } else { 52 | maybeReject('No result returned'); 53 | } 54 | }; 55 | 56 | fetchAndCache(request.clone()).then(maybeResolve, maybeReject); 57 | cacheOnly(request).then(maybeResolve, maybeReject); 58 | })); 59 | }); 60 | -------------------------------------------------------------------------------- /src/sw.js: -------------------------------------------------------------------------------- 1 | import { registerRoute } from 'workbox-routing'; 2 | import { 3 | NetworkFirst, 4 | StaleWhileRevalidate, 5 | CacheFirst, 6 | } from 'workbox-strategies'; 7 | import { ExpirationPlugin } from 'workbox-expiration'; 8 | import { CacheableResponsePlugin } from 'workbox-cacheable-response'; 9 | import * as googleAnalytics from 'workbox-google-analytics'; 10 | 11 | googleAnalytics.initialize(); 12 | 13 | registerRoute( 14 | ({ request }) => request.mode === 'navigate', 15 | new NetworkFirst({ 16 | cacheName: 'index', 17 | }), 18 | ); 19 | 20 | registerRoute( 21 | ({ request }) => 22 | request.destination === 'style' || request.destination === 'script', 23 | new StaleWhileRevalidate({ 24 | cacheName: 'static-resources', 25 | plugins: [ 26 | new ExpirationPlugin({ 27 | maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days 28 | purgeOnQuotaError: true, 29 | }), 30 | ], 31 | }), 32 | ); 33 | 34 | registerRoute( 35 | ({ request }) => request.destination === 'image', 36 | new CacheFirst({ 37 | cacheName: 'images', 38 | plugins: [ 39 | new ExpirationPlugin({ 40 | maxEntries: 60, 41 | maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days 42 | purgeOnQuotaError: true, 43 | }), 44 | new CacheableResponsePlugin({ 45 | statuses: [0, 200], 46 | }), 47 | ], 48 | }), 49 | ); 50 | 51 | registerRoute( 52 | /.*api\.mapbox\.com\/fonts/, 53 | new CacheFirst({ 54 | cacheName: 'mapbox-fonts', 55 | plugins: [ 56 | new ExpirationPlugin({ 57 | maxEntries: 10, 58 | purgeOnQuotaError: true, 59 | }), 60 | new CacheableResponsePlugin({ 61 | statuses: [0, 200], 62 | }), 63 | ], 64 | }), 65 | ); 66 | 67 | registerRoute( 68 | /.*(?:tiles\.mapbox|api\.mapbox)\.com.*$/, 69 | new StaleWhileRevalidate({ 70 | cacheName: 'mapbox', 71 | plugins: [ 72 | new ExpirationPlugin({ 73 | maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days 74 | purgeOnQuotaError: true, 75 | }), 76 | new CacheableResponsePlugin({ 77 | statuses: [0, 200], 78 | }), 79 | ], 80 | }), 81 | ); 82 | -------------------------------------------------------------------------------- /assets/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RailRouter SG 2 | 3 | ![Screenshot of RailRouter SG](screenshots/screenshot-10.png) 4 | 5 | ![Screenshot of RailRouter SG](screenshots/screenshot-11.png) 6 | 7 | **RailRouter SG** is a **progressive web app** that lets you explore MRT and LRT rail routes in Singapore. 8 | 9 | It was built to [scratch my curiosity itch](https://twitter.com/cheeaun/status/683495506031448064) for comparing the _real_ route lines VS the lines shown on Google Maps, which I personally find too _straight_ and skews the perception of how trains actually travel in the real world. 10 | 11 | Available features: 12 | 13 | - **Real** rail route lines, for all train routes. 14 | - Show station names in Chinese and Tamil, besides English. 15 | - Show station building structures, both underground and aboveground. 16 | - Show location of exits (a.k.a. entrances) for (almost) all stations. 17 | - ~~Show train arrival times for _some_ stations.~~ 18 | - Possibly, **works offline**. 19 | 20 | ## Previously 21 | 22 | ![Screenshot of RailRouter SG](screenshots/screenshot-2.png) 23 | 24 | This is the first version, using Google Maps. 25 | 26 | ## Technicalities 27 | 28 | ### For development 29 | 30 | - `npm i` - install dependencies 31 | - `npm start` - starts the server 32 | - `npm run build` - builds the production assets for deployment 33 | 34 | ### Data source 35 | 36 | From my other repo: **[cheeaun/sgraildata](https://github.com/cheeaun/sgraildata)**. 37 | 38 | ⚠️ NOTE: All feature `id`s are removed from `sg-rail.geo.json` in this repo, due to a strange bug in Mapbox GL JS. If the `id` number is too large, errors occur. 39 | 40 | ### Generating station code markers 41 | 42 | 1. Go to https://codepen.io/cheeaun/full/pogQjgV 43 | 2. Paste all the train codes. (`/data/raw/sg-stations-codes.txt` from `sgraildata` repo) 44 | 3. Click "Generate Images" button to download ZIP file of SVG images. 45 | 4. Extract files from the ZIP file. 46 | 5. Go to https://www.facetstudios.com/sprite-generator 47 | 6. Drag/Upload all SVG files to the site. 48 | 7. Uncheck "Export for retina". Check "Generate JSON". 49 | 8. Click "Download Files" button. 50 | 9. Extract files from ZIP file. 51 | 10. Move & rename sprite image to `src/stations.png`. Optimize the image with [TinyPNG](https://tinypng.com/). 52 | 11. Move & rename sprite JSON to `scripts/sprite.json`. 53 | 12. Run `node scripts/gen-stations-sprite.js` which will generate `src/stations.json`. 54 | 55 | ### Tamil characters rendering 56 | 57 | This is done with [maplibre-gl-complex-text](https://github.com/wipfli/maplibre-gl-complex-text). 58 | 59 | Related issue: [Tamil characters rendered wrongly](https://github.com/mapbox/mapbox-gl-js/issues/9894). 60 | 61 | ## License 62 | 63 | - Data: © [LTA](https://www.lta.gov.sg/content/ltagov/en/terms-of-use.html) © [Data.gov.sg](https://data.gov.sg/privacy-and-website-terms#site-terms) © [SMRT](https://www.smrt.com.sg/Terms-of-Use) © [SBS](https://www.sbstransit.com.sg/conditions-for-use) 64 | - Everything else: [MIT](http://cheeaun.mit-license.org/) 65 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | RailRouter SG – Explore MRT and LRT rail routes in Singapore – 6 | Singapore train map 7 | 8 | 9 | 13 | 19 | 20 | 21 | 22 | 23 | 28 | 33 | 34 | 40 | 41 | 42 | 43 | 44 |
45 | 46 |
47 | 104 |
105 | Legend 106 |
107 |
108 |
109 | High crowd density 110 |
111 |
112 |
113 | Moderate crowd density 114 |
115 |
116 | 117 | Station entrance/exit 118 |
119 |
120 | 142 | 158 |
159 | 160 | 162 | 163 | 167 | 176 | -------------------------------------------------------------------------------- /scripts/sprite.json: -------------------------------------------------------------------------------- 1 | {"image":{"image":"spriteness.png","width":840,"height":840},"data":[{"sprite":"EW16-NE3-TE17-svg","w":229,"h":40,"x":0,"y":0},{"sprite":"NS27-CE2-TE20-svg","w":223,"h":40,"x":229,"y":0},{"sprite":"NS24-NE6-CC1-svg","w":214,"h":40,"x":452,"y":0},{"sprite":"EW21-CC22-svg","w":168,"h":40,"x":666,"y":0},{"sprite":"NS26-EW14-svg","w":167,"h":40,"x":0,"y":40},{"sprite":"NS25-EW13-svg","w":167,"h":40,"x":167,"y":40},{"sprite":"EW12-DT14-svg","w":166,"h":40,"x":334,"y":40},{"sprite":"NS17-CC15-svg","w":163,"h":40,"x":500,"y":40},{"sprite":"NE12-CC13-svg","w":163,"h":40,"x":663,"y":40},{"sprite":"CC10-DT26-svg","w":162,"h":40,"x":0,"y":80},{"sprite":"NS22-TE14-svg","w":159,"h":40,"x":162,"y":80},{"sprite":"NS21-DT11-svg","w":159,"h":40,"x":321,"y":80},{"sprite":"DT10-TE11-svg","w":156,"h":40,"x":480,"y":80},{"sprite":"NS1-EW24-svg","w":154,"h":40,"x":636,"y":80},{"sprite":"EW2-DT32-svg","w":152,"h":40,"x":0,"y":120},{"sprite":"NE1-CC29-svg","w":150,"h":40,"x":0,"y":160},{"sprite":"DT35-CG1-svg","w":150,"h":40,"x":0,"y":200},{"sprite":"CC4-DT15-svg","w":148,"h":40,"x":0,"y":240},{"sprite":"CC19-DT9-svg","w":148,"h":40,"x":0,"y":280},{"sprite":"NE7-DT12-svg","w":147,"h":40,"x":0,"y":320},{"sprite":"NE4-DT19-svg","w":147,"h":40,"x":0,"y":360},{"sprite":"NE17-PTC-svg","w":147,"h":40,"x":0,"y":400},{"sprite":"NE16-STC-svg","w":147,"h":40,"x":0,"y":440},{"sprite":"DT16-CE1-svg","w":147,"h":40,"x":0,"y":480},{"sprite":"CC17-TE9-svg","w":147,"h":40,"x":0,"y":520},{"sprite":"EW8-CC9-svg","w":142,"h":40,"x":0,"y":560},{"sprite":"NS4-BP1-svg","w":135,"h":40,"x":0,"y":600},{"sprite":"DT1-BP6-svg","w":133,"h":40,"x":0,"y":640},{"sprite":"NS9-TE2-svg","w":132,"h":40,"x":0,"y":680},{"sprite":"EW4-CG-svg","w":127,"h":40,"x":0,"y":720},{"sprite":"EW33-svg","w":90,"h":40,"x":0,"y":760},{"sprite":"EW32-svg","w":90,"h":40,"x":0,"y":800},{"sprite":"EW31-svg","w":90,"h":40,"x":152,"y":120},{"sprite":"EW30-svg","w":90,"h":40,"x":242,"y":120},{"sprite":"EW29-svg","w":90,"h":40,"x":332,"y":120},{"sprite":"EW28-svg","w":90,"h":40,"x":422,"y":120},{"sprite":"EW27-svg","w":90,"h":40,"x":512,"y":120},{"sprite":"EW26-svg","w":90,"h":40,"x":602,"y":120},{"sprite":"EW25-svg","w":90,"h":40,"x":692,"y":120},{"sprite":"EW23-svg","w":90,"h":40,"x":152,"y":160},{"sprite":"EW22-svg","w":90,"h":40,"x":242,"y":160},{"sprite":"EW20-svg","w":90,"h":40,"x":332,"y":160},{"sprite":"EW19-svg","w":90,"h":40,"x":422,"y":160},{"sprite":"EW18-svg","w":90,"h":40,"x":512,"y":160},{"sprite":"EW17-svg","w":90,"h":40,"x":602,"y":160},{"sprite":"EW15-svg","w":90,"h":40,"x":692,"y":160},{"sprite":"EW10-svg","w":90,"h":40,"x":152,"y":200},{"sprite":"EW11-svg","w":88,"h":40,"x":242,"y":200},{"sprite":"CC28-svg","w":86,"h":40,"x":330,"y":200},{"sprite":"CC27-svg","w":86,"h":40,"x":416,"y":200},{"sprite":"CC26-svg","w":86,"h":40,"x":502,"y":200},{"sprite":"CC25-svg","w":86,"h":40,"x":588,"y":200},{"sprite":"CC24-svg","w":86,"h":40,"x":674,"y":200},{"sprite":"CC23-svg","w":86,"h":40,"x":152,"y":240},{"sprite":"CC21-svg","w":86,"h":40,"x":152,"y":280},{"sprite":"CC20-svg","w":86,"h":40,"x":152,"y":320},{"sprite":"CC16-svg","w":86,"h":40,"x":152,"y":360},{"sprite":"CC14-svg","w":86,"h":40,"x":152,"y":400},{"sprite":"CC12-svg","w":86,"h":40,"x":152,"y":440},{"sprite":"NS28-svg","w":84,"h":40,"x":152,"y":480},{"sprite":"NS23-svg","w":84,"h":40,"x":152,"y":520},{"sprite":"NS20-svg","w":84,"h":40,"x":152,"y":560},{"sprite":"NS19-svg","w":84,"h":40,"x":152,"y":600},{"sprite":"NS18-svg","w":84,"h":40,"x":152,"y":640},{"sprite":"NS16-svg","w":84,"h":40,"x":152,"y":680},{"sprite":"NS15-svg","w":84,"h":40,"x":152,"y":720},{"sprite":"NS14-svg","w":84,"h":40,"x":152,"y":760},{"sprite":"NS13-svg","w":84,"h":40,"x":152,"y":800},{"sprite":"NS12-svg","w":84,"h":40,"x":238,"y":240},{"sprite":"NS10-svg","w":84,"h":40,"x":322,"y":240},{"sprite":"NE18-svg","w":84,"h":40,"x":406,"y":240},{"sprite":"NE15-svg","w":84,"h":40,"x":490,"y":240},{"sprite":"NE14-svg","w":84,"h":40,"x":574,"y":240},{"sprite":"NE13-svg","w":84,"h":40,"x":658,"y":240},{"sprite":"NE10-svg","w":84,"h":40,"x":742,"y":240},{"sprite":"CC11-svg","w":84,"h":40,"x":238,"y":280},{"sprite":"BP13-svg","w":84,"h":40,"x":322,"y":280},{"sprite":"BP12-svg","w":84,"h":40,"x":406,"y":280},{"sprite":"BP10-svg","w":84,"h":40,"x":490,"y":280},{"sprite":"NS11-svg","w":83,"h":40,"x":574,"y":280},{"sprite":"NE11-svg","w":83,"h":40,"x":657,"y":280},{"sprite":"DT34-svg","w":83,"h":40,"x":740,"y":280},{"sprite":"DT33-svg","w":83,"h":40,"x":238,"y":320},{"sprite":"DT31-svg","w":83,"h":40,"x":238,"y":360},{"sprite":"DT30-svg","w":83,"h":40,"x":238,"y":400},{"sprite":"DT29-svg","w":83,"h":40,"x":238,"y":440},{"sprite":"DT28-svg","w":83,"h":40,"x":238,"y":480},{"sprite":"DT27-svg","w":83,"h":40,"x":238,"y":520},{"sprite":"DT25-svg","w":83,"h":40,"x":238,"y":560},{"sprite":"DT24-svg","w":83,"h":40,"x":238,"y":600},{"sprite":"DT23-svg","w":83,"h":40,"x":238,"y":640},{"sprite":"DT22-svg","w":83,"h":40,"x":238,"y":680},{"sprite":"DT21-svg","w":83,"h":40,"x":238,"y":720},{"sprite":"DT20-svg","w":83,"h":40,"x":238,"y":760},{"sprite":"DT18-svg","w":83,"h":40,"x":238,"y":800},{"sprite":"DT17-svg","w":83,"h":40,"x":321,"y":320},{"sprite":"DT13-svg","w":83,"h":40,"x":404,"y":320},{"sprite":"BP11-svg","w":83,"h":40,"x":487,"y":320},{"sprite":"TE29-svg","w":82,"h":40,"x":570,"y":320},{"sprite":"TE28-svg","w":82,"h":40,"x":652,"y":320},{"sprite":"TE27-svg","w":82,"h":40,"x":734,"y":320},{"sprite":"TE26-svg","w":82,"h":40,"x":321,"y":360},{"sprite":"TE25-svg","w":82,"h":40,"x":403,"y":360},{"sprite":"TE24-svg","w":82,"h":40,"x":485,"y":360},{"sprite":"TE23-svg","w":82,"h":40,"x":567,"y":360},{"sprite":"TE22-svg","w":82,"h":40,"x":649,"y":360},{"sprite":"TE19-svg","w":82,"h":40,"x":731,"y":360},{"sprite":"TE18-svg","w":82,"h":40,"x":321,"y":400},{"sprite":"TE16-svg","w":82,"h":40,"x":321,"y":440},{"sprite":"TE15-svg","w":82,"h":40,"x":321,"y":480},{"sprite":"TE13-svg","w":82,"h":40,"x":321,"y":520},{"sprite":"TE12-svg","w":82,"h":40,"x":321,"y":560},{"sprite":"SW8-svg","w":76,"h":40,"x":760,"y":200},{"sprite":"SW7-svg","w":76,"h":40,"x":321,"y":600},{"sprite":"SW6-svg","w":76,"h":40,"x":321,"y":640},{"sprite":"SW5-svg","w":76,"h":40,"x":321,"y":680},{"sprite":"SW4-svg","w":76,"h":40,"x":321,"y":720},{"sprite":"SW3-svg","w":76,"h":40,"x":321,"y":760},{"sprite":"SW2-svg","w":76,"h":40,"x":321,"y":800},{"sprite":"SW1-svg","w":76,"h":40,"x":403,"y":400},{"sprite":"PW7-svg","w":76,"h":40,"x":479,"y":400},{"sprite":"PW6-svg","w":76,"h":40,"x":555,"y":400},{"sprite":"PW5-svg","w":76,"h":40,"x":631,"y":400},{"sprite":"PW4-svg","w":76,"h":40,"x":707,"y":400},{"sprite":"PW3-svg","w":76,"h":40,"x":403,"y":440},{"sprite":"PW2-svg","w":76,"h":40,"x":403,"y":480},{"sprite":"PW1-svg","w":76,"h":40,"x":403,"y":520},{"sprite":"EW9-svg","w":76,"h":40,"x":403,"y":560},{"sprite":"EW7-svg","w":76,"h":40,"x":403,"y":600},{"sprite":"EW6-svg","w":76,"h":40,"x":403,"y":640},{"sprite":"EW5-svg","w":76,"h":40,"x":403,"y":680},{"sprite":"EW3-svg","w":76,"h":40,"x":403,"y":720},{"sprite":"EW1-svg","w":76,"h":40,"x":403,"y":760},{"sprite":"CG2-svg","w":74,"h":40,"x":403,"y":800},{"sprite":"CC8-svg","w":72,"h":40,"x":479,"y":440},{"sprite":"CC7-svg","w":72,"h":40,"x":551,"y":440},{"sprite":"CC6-svg","w":72,"h":40,"x":623,"y":440},{"sprite":"CC5-svg","w":72,"h":40,"x":695,"y":440},{"sprite":"CC3-svg","w":72,"h":40,"x":767,"y":440},{"sprite":"CC2-svg","w":72,"h":40,"x":479,"y":480},{"sprite":"NS8-svg","w":71,"h":40,"x":551,"y":480},{"sprite":"NS7-svg","w":71,"h":40,"x":622,"y":480},{"sprite":"NS5-svg","w":71,"h":40,"x":693,"y":480},{"sprite":"NS3-svg","w":71,"h":40,"x":764,"y":480},{"sprite":"NS2-svg","w":71,"h":40,"x":479,"y":520},{"sprite":"NE9-svg","w":71,"h":40,"x":479,"y":560},{"sprite":"NE8-svg","w":71,"h":40,"x":479,"y":600},{"sprite":"NE5-svg","w":71,"h":40,"x":479,"y":640},{"sprite":"BP9-svg","w":71,"h":40,"x":479,"y":680},{"sprite":"BP8-svg","w":71,"h":40,"x":479,"y":720},{"sprite":"BP7-svg","w":71,"h":40,"x":479,"y":760},{"sprite":"BP5-svg","w":71,"h":40,"x":479,"y":800},{"sprite":"BP4-svg","w":71,"h":40,"x":550,"y":520},{"sprite":"BP3-svg","w":71,"h":40,"x":621,"y":520},{"sprite":"BP2-svg","w":71,"h":40,"x":692,"y":520},{"sprite":"SE5-svg","w":70,"h":40,"x":763,"y":520},{"sprite":"SE4-svg","w":70,"h":40,"x":550,"y":560},{"sprite":"SE3-svg","w":70,"h":40,"x":620,"y":560},{"sprite":"SE2-svg","w":70,"h":40,"x":690,"y":560},{"sprite":"SE1-svg","w":70,"h":40,"x":760,"y":560},{"sprite":"PE7-svg","w":70,"h":40,"x":550,"y":600},{"sprite":"PE6-svg","w":70,"h":40,"x":550,"y":640},{"sprite":"PE5-svg","w":70,"h":40,"x":550,"y":680},{"sprite":"PE4-svg","w":70,"h":40,"x":550,"y":720},{"sprite":"PE3-svg","w":70,"h":40,"x":550,"y":760},{"sprite":"PE2-svg","w":70,"h":40,"x":550,"y":800},{"sprite":"PE1-svg","w":70,"h":40,"x":620,"y":600},{"sprite":"DT8-svg","w":70,"h":40,"x":690,"y":600},{"sprite":"DT7-svg","w":70,"h":40,"x":760,"y":600},{"sprite":"DT6-svg","w":70,"h":40,"x":620,"y":640},{"sprite":"DT5-svg","w":70,"h":40,"x":690,"y":640},{"sprite":"DT4-svg","w":70,"h":40,"x":760,"y":640},{"sprite":"DT3-svg","w":70,"h":40,"x":620,"y":680},{"sprite":"DT2-svg","w":70,"h":40,"x":620,"y":720},{"sprite":"TE8-svg","w":68,"h":40,"x":620,"y":760},{"sprite":"TE7-svg","w":68,"h":40,"x":620,"y":800},{"sprite":"TE6-svg","w":68,"h":40,"x":690,"y":680},{"sprite":"TE5-svg","w":68,"h":40,"x":758,"y":680},{"sprite":"TE4-svg","w":68,"h":40,"x":690,"y":720},{"sprite":"TE3-svg","w":68,"h":40,"x":690,"y":760},{"sprite":"TE1-svg","w":68,"h":40,"x":690,"y":800},{"sprite":"red-yellow-brown-svg","w":50,"h":16,"x":790,"y":80},{"sprite":"red-purple-yellow-svg","w":50,"h":16,"x":790,"y":96},{"sprite":"green-purple-brown-svg","w":50,"h":16,"x":90,"y":760},{"sprite":"yellow-brown-svg","w":36,"h":16,"x":90,"y":776},{"sprite":"yellow-blue-svg","w":36,"h":16,"x":90,"y":792},{"sprite":"red-yellow-svg","w":36,"h":16,"x":90,"y":808},{"sprite":"red-green-svg","w":36,"h":16,"x":90,"y":824},{"sprite":"red-gray-svg","w":36,"h":16,"x":782,"y":120},{"sprite":"red-brown-svg","w":36,"h":16,"x":782,"y":136},{"sprite":"red-blue-svg","w":36,"h":16,"x":782,"y":160},{"sprite":"purple-yellow-svg","w":36,"h":16,"x":782,"y":176},{"sprite":"purple-gray-svg","w":36,"h":16,"x":783,"y":400},{"sprite":"purple-blue-svg","w":36,"h":16,"x":783,"y":416},{"sprite":"green-yellow-svg","w":36,"h":16,"x":758,"y":720},{"sprite":"green-green-svg","w":36,"h":16,"x":794,"y":720},{"sprite":"green-blue-svg","w":36,"h":16,"x":758,"y":736},{"sprite":"blue-yellow-svg","w":36,"h":16,"x":794,"y":736},{"sprite":"blue-green-svg","w":36,"h":16,"x":758,"y":752},{"sprite":"blue-gray-svg","w":36,"h":16,"x":794,"y":752},{"sprite":"blue-brown-svg","w":36,"h":16,"x":758,"y":768},{"sprite":"yellow-svg","w":21,"h":16,"x":127,"y":720},{"sprite":"red-svg","w":21,"h":16,"x":127,"y":736},{"sprite":"purple-svg","w":21,"h":16,"x":126,"y":776},{"sprite":"green-svg","w":21,"h":16,"x":126,"y":792},{"sprite":"gray-svg","w":21,"h":16,"x":126,"y":808},{"sprite":"brown-svg","w":21,"h":16,"x":126,"y":824},{"sprite":"blue-svg","w":21,"h":16,"x":818,"y":120}]} -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import '../node_modules/mapbox-gl/dist/mapbox-gl.css'; 2 | 3 | html { 4 | position: fixed; 5 | top: 0; 6 | right: 0; 7 | bottom: 0; 8 | left: 0; 9 | } 10 | 11 | body { 12 | margin: 0; 13 | padding: 0; 14 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, 15 | sans-serif, Apple Color Emoji, Segoe UI Emoji; 16 | color: #333; 17 | font-size: 15px; 18 | overflow: hidden; 19 | } 20 | 21 | * { 22 | box-sizing: border-box; 23 | } 24 | 25 | a { 26 | color: teal; 27 | text-decoration: none; 28 | text-shadow: 0 0 5px #fff; 29 | background-image: linear-gradient( 30 | to bottom, 31 | rgba(255, 255, 255, 0), 32 | rgba(255, 255, 255, 0) 50%, 33 | powderblue 90%, 34 | rgba(255, 255, 255, 0) 35 | ); 36 | } 37 | 38 | abbr { 39 | color: teal; 40 | font-weight: bold; 41 | text-decoration: none; 42 | } 43 | 44 | .ib { 45 | display: inline-block; 46 | } 47 | 48 | #map { 49 | position: absolute; 50 | top: 0; 51 | bottom: 0; 52 | width: 100%; 53 | } 54 | 55 | .mapboxgl-ctrl-emoji { 56 | font-size: 18px; 57 | } 58 | .mapboxgl-map { 59 | user-select: none; 60 | -webkit-user-select: none; 61 | } 62 | .mapboxgl-ctrl-group { 63 | border-radius: 123123px; 64 | overflow: hidden; 65 | } 66 | .mapboxgl-ctrl-group button { 67 | width: 44px; 68 | height: 44px; 69 | } 70 | 71 | #logo { 72 | cursor: pointer; 73 | position: absolute; 74 | z-index: 100; 75 | top: 16px; 76 | left: 16px; 77 | filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.3)); 78 | transition: all 0.3s; 79 | outline: 0; 80 | } 81 | #logo:active { 82 | filter: brightness(0.8) drop-shadow(0 0px 2px rgba(0, 0, 0, 0.3)); 83 | } 84 | 85 | .sheet { 86 | position: absolute; 87 | z-index: 300; 88 | width: 100%; 89 | top: 100%; 90 | max-height: 100%; 91 | overflow: auto; 92 | background-color: #fff; 93 | padding: 16px; 94 | transition: transform 0.3s ease-out; 95 | pointer-events: none; 96 | user-select: none; 97 | -webkit-user-select: none; 98 | } 99 | .sheet.open { 100 | box-shadow: 0 -5px rgba(0, 0, 0, 0.1); 101 | transform: translateY(-100%); 102 | pointer-events: auto; 103 | user-select: auto; 104 | -webkit-user-select: auto; 105 | } 106 | .sheet.open.min { 107 | transform: translateY(-100px); 108 | cursor: pointer; 109 | } 110 | .sheet.modal.open { 111 | box-shadow: 0 0 50vh rgba(0, 0, 0, 0.5); 112 | } 113 | .sheet.open ~ #map .mapboxgl-control-container { 114 | display: none; 115 | } 116 | .sheet-cover { 117 | position: absolute; 118 | z-index: 200; 119 | left: 0; 120 | right: 0; 121 | top: 0; 122 | bottom: 0; 123 | background-color: rgba(0, 0, 0, 0.4); 124 | opacity: 0; 125 | pointer-events: none; 126 | transition: opacity 0.3s; 127 | } 128 | .sheet.modal.open ~ .sheet-cover { 129 | opacity: 1; 130 | pointer-events: auto; 131 | } 132 | .sheet.open:not(.modal) ~ #logo { 133 | transform: translateY(-100%); 134 | opacity: 0; 135 | pointer-events: none; 136 | } 137 | .sheet.open:not(.modal) ~ .sheet-close { 138 | pointer-events: auto; 139 | opacity: 1; 140 | transform: translateY(-50vh); 141 | } 142 | #station.open ~ .sheet-close { 143 | transform: translateY(-50vh); 144 | } 145 | #station.open.min ~ .sheet-close { 146 | transform: translateY(-100px) rotate(-90deg); 147 | opacity: 1; 148 | } 149 | .sheet h1 { 150 | color: teal; 151 | padding: 0; 152 | margin: 0; 153 | letter-spacing: -0.02em; 154 | } 155 | .sheet h2 { 156 | color: teal; 157 | padding: 0; 158 | margin: 0; 159 | } 160 | .sheet h3 { 161 | color: teal; 162 | padding: 0; 163 | margin: 0; 164 | font-size: 1em; 165 | } 166 | 167 | .sheet .btn { 168 | cursor: pointer; 169 | background-color: teal; 170 | color: #fff; 171 | border: 0; 172 | border-radius: 12px; 173 | padding: 16px; 174 | display: block; 175 | width: 100%; 176 | font-weight: bold; 177 | font-size: 1em; 178 | font-family: inherit; 179 | outline: 0; 180 | } 181 | .sheet .btn:active { 182 | filter: brightness(0.8); 183 | } 184 | 185 | .sheet-close { 186 | pointer-events: none; 187 | display: block; 188 | opacity: 0; 189 | position: absolute; 190 | z-index: 301; 191 | top: 100%; 192 | right: 16px; 193 | width: 44px; 194 | height: 44px; 195 | border-radius: 123123px; 196 | border: 0; 197 | padding: 0; 198 | background-color: gainsboro; 199 | transform: translateY(150%) rotate(-90deg); 200 | cursor: pointer; 201 | transition-property: transform, opacity; 202 | transition-duration: 0.3s; 203 | transition-timing-function: ease-out; 204 | outline: 0; 205 | } 206 | .sheet-close:after { 207 | content: ''; 208 | display: block; 209 | width: 2px; 210 | height: 20px; 211 | background-color: gray; 212 | position: absolute; 213 | left: calc(50% - 1px); 214 | top: calc((44px - 20px) / 2); 215 | transform: rotate(45deg); 216 | } 217 | .sheet-close:before { 218 | content: ''; 219 | display: block; 220 | width: 2px; 221 | height: 20px; 222 | background-color: gray; 223 | position: absolute; 224 | left: calc(50% - 1px); 225 | top: calc((44px - 20px) / 2); 226 | transform: rotate(-45deg); 227 | } 228 | .sheet-close:active { 229 | filter: brightness(0.8); 230 | } 231 | 232 | .sheet header h2 { 233 | vertical-align: middle; 234 | line-height: 1; 235 | margin-bottom: 8px; 236 | } 237 | 238 | #station .pill { 239 | margin-top: 2px; 240 | margin-bottom: 8px; 241 | cursor: default; 242 | } 243 | 244 | #station { 245 | display: flex; 246 | flex-direction: column; 247 | padding: 0; 248 | background-color: transparent; 249 | box-shadow: none; 250 | height: 50vh; 251 | } 252 | #station header { 253 | flex-shrink: 0; 254 | } 255 | #station header { 256 | position: relative; 257 | text-align: center; 258 | background-image: linear-gradient( 259 | to bottom, 260 | transparent, 261 | transparent 50%, 262 | #fff 50% 263 | ); 264 | overflow: hidden; 265 | box-shadow: 0 8px 8px #fff; 266 | } 267 | #station header:after { 268 | content: ''; 269 | position: absolute; 270 | width: 100%; 271 | height: 60%; 272 | background: #fff; 273 | top: 20%; 274 | left: 0; 275 | border-radius: 50%; 276 | z-index: -1; 277 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.25); 278 | } 279 | #station .scrollable { 280 | padding: 0 16px 16px; 281 | background-color: #fff; 282 | flex-grow: 1; 283 | overflow: auto; 284 | } 285 | 286 | .pill { 287 | display: inline-flex; 288 | font-weight: bold; 289 | font-size: 16px; 290 | border-radius: 5px/50%; 291 | overflow: hidden; 292 | word-spacing: -0.2em; 293 | box-shadow: 0 0 0 1px #fff, 0 2px 4px 1px rgba(0, 0, 0, 0.2); 294 | text-shadow: 0 -1px rgba(0, 0, 0, 0.25); 295 | } 296 | .pill.mini { 297 | font-size: 11px; 298 | } 299 | .pill span { 300 | padding: 0.4em; 301 | color: #fff; 302 | background-color: #748477; 303 | background-image: linear-gradient( 304 | to bottom, 305 | rgba(255, 255, 255, 0.2), 306 | rgba(0, 0, 0, 0), 307 | rgba(0, 0, 0, 0.1) 308 | ); 309 | } 310 | .pill span:first-child { 311 | padding-left: 0.5em; 312 | } 313 | .pill span:last-child { 314 | padding-right: 0.5em; 315 | } 316 | .pill span.red { 317 | background-color: #d42e12; 318 | } 319 | .pill span.green { 320 | background-color: #009645; 321 | } 322 | .pill span.yellow { 323 | background-color: #fa9e0d; 324 | color: #000; 325 | text-shadow: 0 -1px rgba(255, 255, 255, 0.5); 326 | background-image: linear-gradient( 327 | to bottom, 328 | rgba(255, 255, 255, 0.3), 329 | rgba(0, 0, 0, 0) 330 | ); 331 | } 332 | .pill span.brown { 333 | background-color: #9d5b25; 334 | } 335 | .pill span.purple { 336 | background-color: #9900aa; 337 | } 338 | .pill span.blue { 339 | background-color: #005ec4; 340 | } 341 | 342 | .arrivals { 343 | background-color: aliceblue; 344 | padding: 12px 16px; 345 | border-radius: 12px; 346 | margin-top: 12px; 347 | } 348 | .arrivals:empty { 349 | display: none; 350 | } 351 | .arrivals table { 352 | width: 100%; 353 | line-height: 1.5em; 354 | } 355 | .arrivals table tbody tr td:nth-last-child(2), 356 | .arrivals table tbody tr td:last-child { 357 | text-align: right; 358 | } 359 | 360 | .exits { 361 | margin-top: 12px; 362 | border-radius: 3px; 363 | background-color: #24201c; 364 | color: #feff65; 365 | padding: 12px; 366 | text-align: center; 367 | background-image: linear-gradient(180deg, #ffffff47, black); 368 | border: 2px solid black; 369 | } 370 | .sheet .exits h3 { 371 | color: #fffc; 372 | text-transform: uppercase; 373 | margin-top: -.5em; 374 | font-size: .85em; 375 | } 376 | .exit-btn { 377 | appearance: none; 378 | display: inline-block; 379 | margin: 3px; 380 | font-weight: bold; 381 | border: 0; 382 | border-radius: 3px; 383 | color: #000; 384 | background: #feff65 url(./exit.png) no-repeat; 385 | background-size: 100%; 386 | font-size: 16px; 387 | display: inline-block; 388 | width: 32px; 389 | height: 32px; 390 | line-height: 34px; 391 | cursor: pointer; 392 | padding: 0; 393 | } 394 | .exit-btn:hover { 395 | filter: saturate(2); 396 | transform: scale(1.1); 397 | } 398 | .exit-btn:active { 399 | filter: brightness(0.8); 400 | transform: scale(1); 401 | } 402 | .exits .note { 403 | color: #fffc; 404 | margin: .5em 0 0; 405 | padding: 0; 406 | } 407 | 408 | .wikipedia { 409 | margin-top: 12px; 410 | border-radius: 12px; 411 | overflow: hidden; 412 | background-color: aliceblue; 413 | } 414 | .wikipedia img { 415 | width: 100%; 416 | height: auto; 417 | } 418 | .wikipedia .extract { 419 | padding: 12px; 420 | line-height: 1.5em; 421 | } 422 | 423 | .wikipedia .extract p { 424 | margin-top: 0; 425 | padding-top: 0; 426 | } 427 | .wikipedia .extract p:last-child { 428 | margin-bottom: 0; 429 | padding-bottom: 0; 430 | } 431 | 432 | .wikipedia .more { 433 | padding: 0 16px 16px; 434 | text-align: right; 435 | } 436 | 437 | #search { 438 | position: fixed; 439 | z-index: 400; 440 | top: 0; 441 | width: 100%; 442 | height: 100%; 443 | background-color: rgba(225, 225, 225, 0.95); 444 | flex-direction: column; 445 | user-select: none; 446 | -webkit-user-select: none; 447 | } 448 | #search:not([hidden]) { 449 | display: flex; 450 | } 451 | @supports (backdrop-filter: blur(10px)) { 452 | #search { 453 | background-color: rgba(225, 225, 225, 0.5); 454 | backdrop-filter: blur(20px) saturate(3); 455 | -webkit-backdrop-filter: blur(20px) saturate(3); 456 | } 457 | } 458 | @supports (-webkit-backdrop-filter: blur(10px)) { 459 | #search { 460 | background-color: rgba(225, 225, 225, 0.5); 461 | -webkit-backdrop-filter: blur(20px) saturate(3); 462 | } 463 | } 464 | 465 | #search-field-container { 466 | display: flex; 467 | flex-shrink: 0; 468 | } 469 | #search-field { 470 | outline: 0; 471 | flex-grow: 1; 472 | border-radius: 9px; 473 | font-size: 18px; 474 | margin: 16px 0 16px 16px; 475 | padding: 8px; 476 | border: 0; 477 | background-color: rgba(0, 0, 0, 0.1); 478 | transition: background-color 0.3s; 479 | appearance: none; 480 | -webkit-appearance: none; 481 | } 482 | #search-field:focus { 483 | background-color: rgba(255, 255, 255, 0.5); 484 | /* blue outline */ 485 | outline: 3px solid #007bffcc; 486 | } 487 | #search-cancel { 488 | border: 0; 489 | padding: 16px; 490 | background-color: transparent; 491 | appearance: none; 492 | -webkit-appearance: none; 493 | font-size: 16px; 494 | color: slategray; 495 | outline: 0; 496 | cursor: pointer; 497 | } 498 | 499 | #search-results { 500 | margin: 0; 501 | padding: 0; 502 | list-style: none; 503 | overflow: auto; 504 | } 505 | 506 | #search-results li { 507 | padding: 0; 508 | margin: 0; 509 | } 510 | 511 | #search-results li a { 512 | color: inherit; 513 | display: block; 514 | padding: 16px; 515 | font-weight: bold; 516 | position: relative; 517 | background-image: none; 518 | transition: background-color 0.3s; 519 | outline: 0; 520 | } 521 | 522 | #search-results li a:first-child { 523 | background-color: rgba(255, 255, 255, 0.5); 524 | } 525 | #search-results li a * { 526 | pointer-events: none; 527 | } 528 | #search-results li a:hover { 529 | background-color: #fff; 530 | } 531 | #search-results li a:after { 532 | content: ''; 533 | display: block; 534 | width: calc(100% - 32px); 535 | position: absolute; 536 | left: 16px; 537 | bottom: 0; 538 | border-bottom: 1px solid rgba(255, 255, 255, 0.75); 539 | } 540 | #search-results .pill { 541 | float: right; 542 | margin-top: -2px; 543 | margin-left: 0.5em; 544 | margin-right: -1px; 545 | } 546 | 547 | /* @media (min-width: 600px) and (max-width: 799px) { 548 | .wikipedia img { 549 | float: right; 550 | width: 50%; 551 | border-radius: 12px; 552 | margin: 16px; 553 | } 554 | } */ 555 | 556 | .crowd-marker { 557 | pointer-events: none; 558 | } 559 | .crowd-marker:after { 560 | content: ''; 561 | display: block; 562 | position: absolute; 563 | top: 0; 564 | right: 0; 565 | bottom: 0; 566 | left: 0; 567 | background-color: orangered; 568 | border-radius: 50%; 569 | animation: pulsing-h 2s infinite ease-out backwards; 570 | will-change: transform, opacity, width, height, margin; 571 | } 572 | .crowd-marker.large:after { 573 | width: 200%; 574 | height: 200%; 575 | margin: -50%; 576 | } 577 | .crowd-marker.larger:after { 578 | width: 400%; 579 | height: 400%; 580 | margin: -150%; 581 | } 582 | .crowd-marker-m:after { 583 | transform: scale(0.5); 584 | background-color: orange; 585 | animation-name: pulsing-m; 586 | animation-duration: 5s; 587 | } 588 | @keyframes pulsing-m { 589 | 0% { 590 | transform: scale(0); 591 | opacity: 0.75; 592 | } 593 | 100% { 594 | transform: scale(0.8); 595 | opacity: 0; 596 | } 597 | } 598 | @keyframes pulsing-h { 599 | 0% { 600 | transform: scale(0); 601 | opacity: 0.75; 602 | } 603 | 100% { 604 | transform: scale(1); 605 | opacity: 0; 606 | } 607 | } 608 | .crowd-marker:nth-child(even):after { 609 | animation-delay: 0.5s; 610 | } 611 | 612 | #legend { 613 | position: fixed; 614 | z-index: 1; 615 | bottom: 40px; 616 | left: 10px; 617 | background-color: rgba(255, 255, 255, 0.5); 618 | padding: 0.6em; 619 | border-radius: 12px; 620 | max-width: calc(100% - 100px); 621 | backdrop-filter: blur(20px) saturate(3); 622 | -webkit-backdrop-filter: blur(20px) saturate(3); 623 | border: 1px solid rgba(255, 255, 255, 0.25); 624 | } 625 | 626 | #legend summary { 627 | font-weight: bold; 628 | outline: 0; 629 | cursor: pointer; 630 | } 631 | #legend summary ~ div { 632 | vertical-align: middle; 633 | margin-top: 0.25em; 634 | } 635 | 636 | #legend img { 637 | vertical-align: middle; 638 | } 639 | #legend .crowd-marker { 640 | width: 16px; 641 | height: 16px; 642 | position: relative; 643 | display: inline-block; 644 | vertical-align: middle; 645 | background-color: #fff; 646 | border-radius: 50%; 647 | } 648 | 649 | #crowded-timing { 650 | font-size: 11px; 651 | text-transform: uppercase; 652 | margin: 3px; 653 | color: #666; 654 | } 655 | #crowded-timing b { 656 | display: inline-block; 657 | } 658 | 659 | @media (min-width: 640px) { 660 | .sheet { 661 | width: 320px; 662 | top: 0; 663 | right: 100%; 664 | bottom: 0; 665 | } 666 | .sheet.open, 667 | .sheet.open.min { 668 | transform: translateX(100%); 669 | box-shadow: 5px 0 rgba(0, 0, 0, 0.1) !important; 670 | } 671 | .sheet.modal.open { 672 | box-shadow: 0 0 50vh rgba(0, 0, 0, 0.5) !important; 673 | } 674 | #station { 675 | height: auto; 676 | } 677 | #station header { 678 | background: #fff none; 679 | padding-top: 16px; 680 | } 681 | .sheet-close { 682 | top: 16px; 683 | left: 0; 684 | } 685 | .sheet.open ~ .sheet-close { 686 | transform: translateX(320px) translateX(-50%) !important; 687 | } 688 | 689 | #search { 690 | align-items: center; 691 | } 692 | #search-field-container, 693 | #search-results { 694 | width: 480px; 695 | } 696 | } 697 | -------------------------------------------------------------------------------- /src/stations.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | "EW16-NE3-TE17", 4 | 0, 5 | 0, 6 | 229, 7 | 40 8 | ], 9 | [ 10 | "NS27-CE2-TE20", 11 | 229, 12 | 0, 13 | 223, 14 | 40 15 | ], 16 | [ 17 | "NS24-NE6-CC1", 18 | 452, 19 | 0, 20 | 214, 21 | 40 22 | ], 23 | [ 24 | "EW21-CC22", 25 | 666, 26 | 0, 27 | 168, 28 | 40 29 | ], 30 | [ 31 | "NS26-EW14", 32 | 0, 33 | 40, 34 | 167, 35 | 40 36 | ], 37 | [ 38 | "NS25-EW13", 39 | 167, 40 | 40, 41 | 167, 42 | 40 43 | ], 44 | [ 45 | "EW12-DT14", 46 | 334, 47 | 40, 48 | 166, 49 | 40 50 | ], 51 | [ 52 | "NS17-CC15", 53 | 500, 54 | 40, 55 | 163, 56 | 40 57 | ], 58 | [ 59 | "NE12-CC13", 60 | 663, 61 | 40, 62 | 163, 63 | 40 64 | ], 65 | [ 66 | "CC10-DT26", 67 | 0, 68 | 80, 69 | 162, 70 | 40 71 | ], 72 | [ 73 | "NS22-TE14", 74 | 162, 75 | 80, 76 | 159, 77 | 40 78 | ], 79 | [ 80 | "NS21-DT11", 81 | 321, 82 | 80, 83 | 159, 84 | 40 85 | ], 86 | [ 87 | "DT10-TE11", 88 | 480, 89 | 80, 90 | 156, 91 | 40 92 | ], 93 | [ 94 | "NS1-EW24", 95 | 636, 96 | 80, 97 | 154, 98 | 40 99 | ], 100 | [ 101 | "EW2-DT32", 102 | 0, 103 | 120, 104 | 152, 105 | 40 106 | ], 107 | [ 108 | "NE1-CC29", 109 | 0, 110 | 160, 111 | 150, 112 | 40 113 | ], 114 | [ 115 | "DT35-CG1", 116 | 0, 117 | 200, 118 | 150, 119 | 40 120 | ], 121 | [ 122 | "CC4-DT15", 123 | 0, 124 | 240, 125 | 148, 126 | 40 127 | ], 128 | [ 129 | "CC19-DT9", 130 | 0, 131 | 280, 132 | 148, 133 | 40 134 | ], 135 | [ 136 | "NE7-DT12", 137 | 0, 138 | 320, 139 | 147, 140 | 40 141 | ], 142 | [ 143 | "NE4-DT19", 144 | 0, 145 | 360, 146 | 147, 147 | 40 148 | ], 149 | [ 150 | "NE17-PTC", 151 | 0, 152 | 400, 153 | 147, 154 | 40 155 | ], 156 | [ 157 | "NE16-STC", 158 | 0, 159 | 440, 160 | 147, 161 | 40 162 | ], 163 | [ 164 | "DT16-CE1", 165 | 0, 166 | 480, 167 | 147, 168 | 40 169 | ], 170 | [ 171 | "CC17-TE9", 172 | 0, 173 | 520, 174 | 147, 175 | 40 176 | ], 177 | [ 178 | "EW8-CC9", 179 | 0, 180 | 560, 181 | 142, 182 | 40 183 | ], 184 | [ 185 | "NS4-BP1", 186 | 0, 187 | 600, 188 | 135, 189 | 40 190 | ], 191 | [ 192 | "DT1-BP6", 193 | 0, 194 | 640, 195 | 133, 196 | 40 197 | ], 198 | [ 199 | "NS9-TE2", 200 | 0, 201 | 680, 202 | 132, 203 | 40 204 | ], 205 | [ 206 | "EW4-CG", 207 | 0, 208 | 720, 209 | 127, 210 | 40 211 | ], 212 | [ 213 | "EW33", 214 | 0, 215 | 760, 216 | 90, 217 | 40 218 | ], 219 | [ 220 | "EW32", 221 | 0, 222 | 800, 223 | 90, 224 | 40 225 | ], 226 | [ 227 | "EW31", 228 | 152, 229 | 120, 230 | 90, 231 | 40 232 | ], 233 | [ 234 | "EW30", 235 | 242, 236 | 120, 237 | 90, 238 | 40 239 | ], 240 | [ 241 | "EW29", 242 | 332, 243 | 120, 244 | 90, 245 | 40 246 | ], 247 | [ 248 | "EW28", 249 | 422, 250 | 120, 251 | 90, 252 | 40 253 | ], 254 | [ 255 | "EW27", 256 | 512, 257 | 120, 258 | 90, 259 | 40 260 | ], 261 | [ 262 | "EW26", 263 | 602, 264 | 120, 265 | 90, 266 | 40 267 | ], 268 | [ 269 | "EW25", 270 | 692, 271 | 120, 272 | 90, 273 | 40 274 | ], 275 | [ 276 | "EW23", 277 | 152, 278 | 160, 279 | 90, 280 | 40 281 | ], 282 | [ 283 | "EW22", 284 | 242, 285 | 160, 286 | 90, 287 | 40 288 | ], 289 | [ 290 | "EW20", 291 | 332, 292 | 160, 293 | 90, 294 | 40 295 | ], 296 | [ 297 | "EW19", 298 | 422, 299 | 160, 300 | 90, 301 | 40 302 | ], 303 | [ 304 | "EW18", 305 | 512, 306 | 160, 307 | 90, 308 | 40 309 | ], 310 | [ 311 | "EW17", 312 | 602, 313 | 160, 314 | 90, 315 | 40 316 | ], 317 | [ 318 | "EW15", 319 | 692, 320 | 160, 321 | 90, 322 | 40 323 | ], 324 | [ 325 | "EW10", 326 | 152, 327 | 200, 328 | 90, 329 | 40 330 | ], 331 | [ 332 | "EW11", 333 | 242, 334 | 200, 335 | 88, 336 | 40 337 | ], 338 | [ 339 | "CC28", 340 | 330, 341 | 200, 342 | 86, 343 | 40 344 | ], 345 | [ 346 | "CC27", 347 | 416, 348 | 200, 349 | 86, 350 | 40 351 | ], 352 | [ 353 | "CC26", 354 | 502, 355 | 200, 356 | 86, 357 | 40 358 | ], 359 | [ 360 | "CC25", 361 | 588, 362 | 200, 363 | 86, 364 | 40 365 | ], 366 | [ 367 | "CC24", 368 | 674, 369 | 200, 370 | 86, 371 | 40 372 | ], 373 | [ 374 | "CC23", 375 | 152, 376 | 240, 377 | 86, 378 | 40 379 | ], 380 | [ 381 | "CC21", 382 | 152, 383 | 280, 384 | 86, 385 | 40 386 | ], 387 | [ 388 | "CC20", 389 | 152, 390 | 320, 391 | 86, 392 | 40 393 | ], 394 | [ 395 | "CC16", 396 | 152, 397 | 360, 398 | 86, 399 | 40 400 | ], 401 | [ 402 | "CC14", 403 | 152, 404 | 400, 405 | 86, 406 | 40 407 | ], 408 | [ 409 | "CC12", 410 | 152, 411 | 440, 412 | 86, 413 | 40 414 | ], 415 | [ 416 | "NS28", 417 | 152, 418 | 480, 419 | 84, 420 | 40 421 | ], 422 | [ 423 | "NS23", 424 | 152, 425 | 520, 426 | 84, 427 | 40 428 | ], 429 | [ 430 | "NS20", 431 | 152, 432 | 560, 433 | 84, 434 | 40 435 | ], 436 | [ 437 | "NS19", 438 | 152, 439 | 600, 440 | 84, 441 | 40 442 | ], 443 | [ 444 | "NS18", 445 | 152, 446 | 640, 447 | 84, 448 | 40 449 | ], 450 | [ 451 | "NS16", 452 | 152, 453 | 680, 454 | 84, 455 | 40 456 | ], 457 | [ 458 | "NS15", 459 | 152, 460 | 720, 461 | 84, 462 | 40 463 | ], 464 | [ 465 | "NS14", 466 | 152, 467 | 760, 468 | 84, 469 | 40 470 | ], 471 | [ 472 | "NS13", 473 | 152, 474 | 800, 475 | 84, 476 | 40 477 | ], 478 | [ 479 | "NS12", 480 | 238, 481 | 240, 482 | 84, 483 | 40 484 | ], 485 | [ 486 | "NS10", 487 | 322, 488 | 240, 489 | 84, 490 | 40 491 | ], 492 | [ 493 | "NE18", 494 | 406, 495 | 240, 496 | 84, 497 | 40 498 | ], 499 | [ 500 | "NE15", 501 | 490, 502 | 240, 503 | 84, 504 | 40 505 | ], 506 | [ 507 | "NE14", 508 | 574, 509 | 240, 510 | 84, 511 | 40 512 | ], 513 | [ 514 | "NE13", 515 | 658, 516 | 240, 517 | 84, 518 | 40 519 | ], 520 | [ 521 | "NE10", 522 | 742, 523 | 240, 524 | 84, 525 | 40 526 | ], 527 | [ 528 | "CC11", 529 | 238, 530 | 280, 531 | 84, 532 | 40 533 | ], 534 | [ 535 | "BP13", 536 | 322, 537 | 280, 538 | 84, 539 | 40 540 | ], 541 | [ 542 | "BP12", 543 | 406, 544 | 280, 545 | 84, 546 | 40 547 | ], 548 | [ 549 | "BP10", 550 | 490, 551 | 280, 552 | 84, 553 | 40 554 | ], 555 | [ 556 | "NS11", 557 | 574, 558 | 280, 559 | 83, 560 | 40 561 | ], 562 | [ 563 | "NE11", 564 | 657, 565 | 280, 566 | 83, 567 | 40 568 | ], 569 | [ 570 | "DT34", 571 | 740, 572 | 280, 573 | 83, 574 | 40 575 | ], 576 | [ 577 | "DT33", 578 | 238, 579 | 320, 580 | 83, 581 | 40 582 | ], 583 | [ 584 | "DT31", 585 | 238, 586 | 360, 587 | 83, 588 | 40 589 | ], 590 | [ 591 | "DT30", 592 | 238, 593 | 400, 594 | 83, 595 | 40 596 | ], 597 | [ 598 | "DT29", 599 | 238, 600 | 440, 601 | 83, 602 | 40 603 | ], 604 | [ 605 | "DT28", 606 | 238, 607 | 480, 608 | 83, 609 | 40 610 | ], 611 | [ 612 | "DT27", 613 | 238, 614 | 520, 615 | 83, 616 | 40 617 | ], 618 | [ 619 | "DT25", 620 | 238, 621 | 560, 622 | 83, 623 | 40 624 | ], 625 | [ 626 | "DT24", 627 | 238, 628 | 600, 629 | 83, 630 | 40 631 | ], 632 | [ 633 | "DT23", 634 | 238, 635 | 640, 636 | 83, 637 | 40 638 | ], 639 | [ 640 | "DT22", 641 | 238, 642 | 680, 643 | 83, 644 | 40 645 | ], 646 | [ 647 | "DT21", 648 | 238, 649 | 720, 650 | 83, 651 | 40 652 | ], 653 | [ 654 | "DT20", 655 | 238, 656 | 760, 657 | 83, 658 | 40 659 | ], 660 | [ 661 | "DT18", 662 | 238, 663 | 800, 664 | 83, 665 | 40 666 | ], 667 | [ 668 | "DT17", 669 | 321, 670 | 320, 671 | 83, 672 | 40 673 | ], 674 | [ 675 | "DT13", 676 | 404, 677 | 320, 678 | 83, 679 | 40 680 | ], 681 | [ 682 | "BP11", 683 | 487, 684 | 320, 685 | 83, 686 | 40 687 | ], 688 | [ 689 | "TE29", 690 | 570, 691 | 320, 692 | 82, 693 | 40 694 | ], 695 | [ 696 | "TE28", 697 | 652, 698 | 320, 699 | 82, 700 | 40 701 | ], 702 | [ 703 | "TE27", 704 | 734, 705 | 320, 706 | 82, 707 | 40 708 | ], 709 | [ 710 | "TE26", 711 | 321, 712 | 360, 713 | 82, 714 | 40 715 | ], 716 | [ 717 | "TE25", 718 | 403, 719 | 360, 720 | 82, 721 | 40 722 | ], 723 | [ 724 | "TE24", 725 | 485, 726 | 360, 727 | 82, 728 | 40 729 | ], 730 | [ 731 | "TE23", 732 | 567, 733 | 360, 734 | 82, 735 | 40 736 | ], 737 | [ 738 | "TE22", 739 | 649, 740 | 360, 741 | 82, 742 | 40 743 | ], 744 | [ 745 | "TE19", 746 | 731, 747 | 360, 748 | 82, 749 | 40 750 | ], 751 | [ 752 | "TE18", 753 | 321, 754 | 400, 755 | 82, 756 | 40 757 | ], 758 | [ 759 | "TE16", 760 | 321, 761 | 440, 762 | 82, 763 | 40 764 | ], 765 | [ 766 | "TE15", 767 | 321, 768 | 480, 769 | 82, 770 | 40 771 | ], 772 | [ 773 | "TE13", 774 | 321, 775 | 520, 776 | 82, 777 | 40 778 | ], 779 | [ 780 | "TE12", 781 | 321, 782 | 560, 783 | 82, 784 | 40 785 | ], 786 | [ 787 | "SW8", 788 | 760, 789 | 200, 790 | 76, 791 | 40 792 | ], 793 | [ 794 | "SW7", 795 | 321, 796 | 600, 797 | 76, 798 | 40 799 | ], 800 | [ 801 | "SW6", 802 | 321, 803 | 640, 804 | 76, 805 | 40 806 | ], 807 | [ 808 | "SW5", 809 | 321, 810 | 680, 811 | 76, 812 | 40 813 | ], 814 | [ 815 | "SW4", 816 | 321, 817 | 720, 818 | 76, 819 | 40 820 | ], 821 | [ 822 | "SW3", 823 | 321, 824 | 760, 825 | 76, 826 | 40 827 | ], 828 | [ 829 | "SW2", 830 | 321, 831 | 800, 832 | 76, 833 | 40 834 | ], 835 | [ 836 | "SW1", 837 | 403, 838 | 400, 839 | 76, 840 | 40 841 | ], 842 | [ 843 | "PW7", 844 | 479, 845 | 400, 846 | 76, 847 | 40 848 | ], 849 | [ 850 | "PW6", 851 | 555, 852 | 400, 853 | 76, 854 | 40 855 | ], 856 | [ 857 | "PW5", 858 | 631, 859 | 400, 860 | 76, 861 | 40 862 | ], 863 | [ 864 | "PW4", 865 | 707, 866 | 400, 867 | 76, 868 | 40 869 | ], 870 | [ 871 | "PW3", 872 | 403, 873 | 440, 874 | 76, 875 | 40 876 | ], 877 | [ 878 | "PW2", 879 | 403, 880 | 480, 881 | 76, 882 | 40 883 | ], 884 | [ 885 | "PW1", 886 | 403, 887 | 520, 888 | 76, 889 | 40 890 | ], 891 | [ 892 | "EW9", 893 | 403, 894 | 560, 895 | 76, 896 | 40 897 | ], 898 | [ 899 | "EW7", 900 | 403, 901 | 600, 902 | 76, 903 | 40 904 | ], 905 | [ 906 | "EW6", 907 | 403, 908 | 640, 909 | 76, 910 | 40 911 | ], 912 | [ 913 | "EW5", 914 | 403, 915 | 680, 916 | 76, 917 | 40 918 | ], 919 | [ 920 | "EW3", 921 | 403, 922 | 720, 923 | 76, 924 | 40 925 | ], 926 | [ 927 | "EW1", 928 | 403, 929 | 760, 930 | 76, 931 | 40 932 | ], 933 | [ 934 | "CG2", 935 | 403, 936 | 800, 937 | 74, 938 | 40 939 | ], 940 | [ 941 | "CC8", 942 | 479, 943 | 440, 944 | 72, 945 | 40 946 | ], 947 | [ 948 | "CC7", 949 | 551, 950 | 440, 951 | 72, 952 | 40 953 | ], 954 | [ 955 | "CC6", 956 | 623, 957 | 440, 958 | 72, 959 | 40 960 | ], 961 | [ 962 | "CC5", 963 | 695, 964 | 440, 965 | 72, 966 | 40 967 | ], 968 | [ 969 | "CC3", 970 | 767, 971 | 440, 972 | 72, 973 | 40 974 | ], 975 | [ 976 | "CC2", 977 | 479, 978 | 480, 979 | 72, 980 | 40 981 | ], 982 | [ 983 | "NS8", 984 | 551, 985 | 480, 986 | 71, 987 | 40 988 | ], 989 | [ 990 | "NS7", 991 | 622, 992 | 480, 993 | 71, 994 | 40 995 | ], 996 | [ 997 | "NS5", 998 | 693, 999 | 480, 1000 | 71, 1001 | 40 1002 | ], 1003 | [ 1004 | "NS3", 1005 | 764, 1006 | 480, 1007 | 71, 1008 | 40 1009 | ], 1010 | [ 1011 | "NS2", 1012 | 479, 1013 | 520, 1014 | 71, 1015 | 40 1016 | ], 1017 | [ 1018 | "NE9", 1019 | 479, 1020 | 560, 1021 | 71, 1022 | 40 1023 | ], 1024 | [ 1025 | "NE8", 1026 | 479, 1027 | 600, 1028 | 71, 1029 | 40 1030 | ], 1031 | [ 1032 | "NE5", 1033 | 479, 1034 | 640, 1035 | 71, 1036 | 40 1037 | ], 1038 | [ 1039 | "BP9", 1040 | 479, 1041 | 680, 1042 | 71, 1043 | 40 1044 | ], 1045 | [ 1046 | "BP8", 1047 | 479, 1048 | 720, 1049 | 71, 1050 | 40 1051 | ], 1052 | [ 1053 | "BP7", 1054 | 479, 1055 | 760, 1056 | 71, 1057 | 40 1058 | ], 1059 | [ 1060 | "BP5", 1061 | 479, 1062 | 800, 1063 | 71, 1064 | 40 1065 | ], 1066 | [ 1067 | "BP4", 1068 | 550, 1069 | 520, 1070 | 71, 1071 | 40 1072 | ], 1073 | [ 1074 | "BP3", 1075 | 621, 1076 | 520, 1077 | 71, 1078 | 40 1079 | ], 1080 | [ 1081 | "BP2", 1082 | 692, 1083 | 520, 1084 | 71, 1085 | 40 1086 | ], 1087 | [ 1088 | "SE5", 1089 | 763, 1090 | 520, 1091 | 70, 1092 | 40 1093 | ], 1094 | [ 1095 | "SE4", 1096 | 550, 1097 | 560, 1098 | 70, 1099 | 40 1100 | ], 1101 | [ 1102 | "SE3", 1103 | 620, 1104 | 560, 1105 | 70, 1106 | 40 1107 | ], 1108 | [ 1109 | "SE2", 1110 | 690, 1111 | 560, 1112 | 70, 1113 | 40 1114 | ], 1115 | [ 1116 | "SE1", 1117 | 760, 1118 | 560, 1119 | 70, 1120 | 40 1121 | ], 1122 | [ 1123 | "PE7", 1124 | 550, 1125 | 600, 1126 | 70, 1127 | 40 1128 | ], 1129 | [ 1130 | "PE6", 1131 | 550, 1132 | 640, 1133 | 70, 1134 | 40 1135 | ], 1136 | [ 1137 | "PE5", 1138 | 550, 1139 | 680, 1140 | 70, 1141 | 40 1142 | ], 1143 | [ 1144 | "PE4", 1145 | 550, 1146 | 720, 1147 | 70, 1148 | 40 1149 | ], 1150 | [ 1151 | "PE3", 1152 | 550, 1153 | 760, 1154 | 70, 1155 | 40 1156 | ], 1157 | [ 1158 | "PE2", 1159 | 550, 1160 | 800, 1161 | 70, 1162 | 40 1163 | ], 1164 | [ 1165 | "PE1", 1166 | 620, 1167 | 600, 1168 | 70, 1169 | 40 1170 | ], 1171 | [ 1172 | "DT8", 1173 | 690, 1174 | 600, 1175 | 70, 1176 | 40 1177 | ], 1178 | [ 1179 | "DT7", 1180 | 760, 1181 | 600, 1182 | 70, 1183 | 40 1184 | ], 1185 | [ 1186 | "DT6", 1187 | 620, 1188 | 640, 1189 | 70, 1190 | 40 1191 | ], 1192 | [ 1193 | "DT5", 1194 | 690, 1195 | 640, 1196 | 70, 1197 | 40 1198 | ], 1199 | [ 1200 | "DT4", 1201 | 760, 1202 | 640, 1203 | 70, 1204 | 40 1205 | ], 1206 | [ 1207 | "DT3", 1208 | 620, 1209 | 680, 1210 | 70, 1211 | 40 1212 | ], 1213 | [ 1214 | "DT2", 1215 | 620, 1216 | 720, 1217 | 70, 1218 | 40 1219 | ], 1220 | [ 1221 | "TE8", 1222 | 620, 1223 | 760, 1224 | 68, 1225 | 40 1226 | ], 1227 | [ 1228 | "TE7", 1229 | 620, 1230 | 800, 1231 | 68, 1232 | 40 1233 | ], 1234 | [ 1235 | "TE6", 1236 | 690, 1237 | 680, 1238 | 68, 1239 | 40 1240 | ], 1241 | [ 1242 | "TE5", 1243 | 758, 1244 | 680, 1245 | 68, 1246 | 40 1247 | ], 1248 | [ 1249 | "TE4", 1250 | 690, 1251 | 720, 1252 | 68, 1253 | 40 1254 | ], 1255 | [ 1256 | "TE3", 1257 | 690, 1258 | 760, 1259 | 68, 1260 | 40 1261 | ], 1262 | [ 1263 | "TE1", 1264 | 690, 1265 | 800, 1266 | 68, 1267 | 40 1268 | ], 1269 | [ 1270 | "red-yellow-brown", 1271 | 790, 1272 | 80, 1273 | 50, 1274 | 16 1275 | ], 1276 | [ 1277 | "red-purple-yellow", 1278 | 790, 1279 | 96, 1280 | 50, 1281 | 16 1282 | ], 1283 | [ 1284 | "green-purple-brown", 1285 | 90, 1286 | 760, 1287 | 50, 1288 | 16 1289 | ], 1290 | [ 1291 | "yellow-brown", 1292 | 90, 1293 | 776, 1294 | 36, 1295 | 16 1296 | ], 1297 | [ 1298 | "yellow-blue", 1299 | 90, 1300 | 792, 1301 | 36, 1302 | 16 1303 | ], 1304 | [ 1305 | "red-yellow", 1306 | 90, 1307 | 808, 1308 | 36, 1309 | 16 1310 | ], 1311 | [ 1312 | "red-green", 1313 | 90, 1314 | 824, 1315 | 36, 1316 | 16 1317 | ], 1318 | [ 1319 | "red-gray", 1320 | 782, 1321 | 120, 1322 | 36, 1323 | 16 1324 | ], 1325 | [ 1326 | "red-brown", 1327 | 782, 1328 | 136, 1329 | 36, 1330 | 16 1331 | ], 1332 | [ 1333 | "red-blue", 1334 | 782, 1335 | 160, 1336 | 36, 1337 | 16 1338 | ], 1339 | [ 1340 | "purple-yellow", 1341 | 782, 1342 | 176, 1343 | 36, 1344 | 16 1345 | ], 1346 | [ 1347 | "purple-gray", 1348 | 783, 1349 | 400, 1350 | 36, 1351 | 16 1352 | ], 1353 | [ 1354 | "purple-blue", 1355 | 783, 1356 | 416, 1357 | 36, 1358 | 16 1359 | ], 1360 | [ 1361 | "green-yellow", 1362 | 758, 1363 | 720, 1364 | 36, 1365 | 16 1366 | ], 1367 | [ 1368 | "green-green", 1369 | 794, 1370 | 720, 1371 | 36, 1372 | 16 1373 | ], 1374 | [ 1375 | "green-blue", 1376 | 758, 1377 | 736, 1378 | 36, 1379 | 16 1380 | ], 1381 | [ 1382 | "blue-yellow", 1383 | 794, 1384 | 736, 1385 | 36, 1386 | 16 1387 | ], 1388 | [ 1389 | "blue-green", 1390 | 758, 1391 | 752, 1392 | 36, 1393 | 16 1394 | ], 1395 | [ 1396 | "blue-gray", 1397 | 794, 1398 | 752, 1399 | 36, 1400 | 16 1401 | ], 1402 | [ 1403 | "blue-brown", 1404 | 758, 1405 | 768, 1406 | 36, 1407 | 16 1408 | ], 1409 | [ 1410 | "yellow", 1411 | 127, 1412 | 720, 1413 | 21, 1414 | 16 1415 | ], 1416 | [ 1417 | "red", 1418 | 127, 1419 | 736, 1420 | 21, 1421 | 16 1422 | ], 1423 | [ 1424 | "purple", 1425 | 126, 1426 | 776, 1427 | 21, 1428 | 16 1429 | ], 1430 | [ 1431 | "green", 1432 | 126, 1433 | 792, 1434 | 21, 1435 | 16 1436 | ], 1437 | [ 1438 | "gray", 1439 | 126, 1440 | 808, 1441 | 21, 1442 | 16 1443 | ], 1444 | [ 1445 | "brown", 1446 | 126, 1447 | 824, 1448 | 21, 1449 | 16 1450 | ], 1451 | [ 1452 | "blue", 1453 | 818, 1454 | 120, 1455 | 21, 1456 | 16 1457 | ] 1458 | ] -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // https://github.com/parcel-bundler/parcel/issues/3375#issuecomment-599160200 2 | import 'regenerator-runtime/runtime'; 3 | 4 | const $ = (id) => document.getElementById(id); 5 | const $home = $('home'); 6 | const $btnCloseHome = $('btn-close-home'); 7 | const $station = $('station'); 8 | const $search = $('search'); 9 | const $searchField = $('search-field'); 10 | const $searchCancel = $('search-cancel'); 11 | const $searchResults = $('search-results'); 12 | const $crowdedTiming = $('crowded-timing'); 13 | 14 | $btnCloseHome.onclick = (e) => { 15 | e.preventDefault(); 16 | localStorage['railrouter-sg:about'] = 1; 17 | $home.classList.remove('open'); 18 | }; 19 | if (!localStorage['railrouter-sg:about']) { 20 | $home.classList.add('open'); 21 | } 22 | $('logo').onclick = () => { 23 | $home.classList.toggle('open'); 24 | }; 25 | 26 | import Fuse from 'fuse.js'; 27 | let fuse; 28 | 29 | let stationsData; 30 | const exitsData = {}; 31 | 32 | const geojsonFetch = fetch(require('./sg-rail.geo.json')); 33 | 34 | import mapboxgl from 'mapbox-gl'; 35 | import MapboxLanguage from '@mapbox/mapbox-gl-language'; 36 | import stationsSprite from './stations.json'; 37 | mapboxgl.accessToken = 38 | 'pk.eyJ1IjoiY2hlZWF1biIsImEiOiJja2NydG83cWMwaGJsMnBqdjR5aHc3MzdlIn0.YGTZpi7JQMquEOv9E8K_bg'; 39 | 40 | const center = [103.8475, 1.3011]; 41 | const lowerLat = 1.23, 42 | upperLat = 1.475, 43 | lowerLong = 103.59, 44 | upperLong = 104.05; 45 | const bounds = [lowerLong, lowerLat, upperLong, upperLat]; 46 | 47 | mapboxgl.setRTLTextPlugin( 48 | "https://wipfli.github.io/maplibre-gl-complex-text/dist/maplibre-gl-complex-text.js", 49 | false 50 | ); 51 | 52 | const map = (window.$map = new mapboxgl.Map({ 53 | container: 'map', 54 | // style: 'mapbox://styles/cheeaun/clagddy23000y14saafbh02a8/draft', 55 | style: 'mapbox://styles/cheeaun/clagddy23000y14saafbh02a8', 56 | center, 57 | bounds, 58 | renderWorldCopies: false, 59 | boxZoom: false, 60 | bearingSnap: 15, 61 | // localIdeographFontFamily: 62 | // '"InaiMathi", "Tamil Sangam MN", "Nirmala UI", Latha, Bamini ,Roboto, Noto, "Noto Sans Tamil", sans-serif', 63 | transformRequest: (url, resourceType) => { 64 | if (resourceType === "Glyphs") { 65 | const match = url.match(/(\d+)-(\d+)\.pbf/); 66 | if (match) { 67 | const start = parseInt(match[1], 10); 68 | const end = parseInt(match[2], 10); 69 | const encodedRangeStarts = [63488, 63232, 62976, 62720, 62464, 62208, 61952, 61696, 61440, 61184, 60928, 60672, 60416, 60160, 59904, 59648, 59392, 59136, 58880, 58624, 58368, 58112, 57856, 57600, 3072, 2816, 2560, 2304, 10240, 10752]; 70 | if (encodedRangeStarts.includes(start)) { 71 | return { url: `https://wipfli.github.io/pgf-glyph-ranges/font/NotoSansMultiscript-Regular-v1/${start}-${end}.pbf` }; 72 | } 73 | } 74 | } 75 | return undefined; 76 | } 77 | })); 78 | const mapCanvas = map.getCanvas(); 79 | 80 | const supportedLanguages = [ 81 | 'ar', 82 | 'de', 83 | 'en', 84 | 'es', 85 | 'fr', 86 | 'it', 87 | 'ja', 88 | 'ko', 89 | 'mul', 90 | 'pt', 91 | 'ru', 92 | 'vi', 93 | 'zh-Hans', 94 | 'zh-Hant', 95 | ]; 96 | function browserLanguage() { 97 | const language = navigator.languages 98 | ? navigator.languages[0] 99 | : navigator.language || navigator.userLanguage; 100 | const parts = language && language.split('-'); 101 | let languageCode = language; 102 | if (parts.length > 1) { 103 | languageCode = parts[0]; 104 | } 105 | if (supportedLanguages.indexOf(languageCode) > -1) { 106 | return languageCode; 107 | } 108 | const closestLanguageCode = supportedLanguages.find((l) => { 109 | return l.startsWith(languageCode); 110 | }); 111 | if (closestLanguageCode) return closestLanguageCode; 112 | return null; 113 | } 114 | 115 | map.addControl( 116 | new MapboxLanguage({ 117 | defaultLanguage: browserLanguage(), 118 | }), 119 | ); 120 | 121 | map.addControl( 122 | new mapboxgl.GeolocateControl({ 123 | positionOptions: { 124 | enableHighAccuracy: true, 125 | }, 126 | trackUserLocation: true, 127 | }), 128 | 'bottom-right', 129 | ); 130 | 131 | const mapLoaded = new Promise((res) => { 132 | map.once('load', () => { 133 | console.timeStamp('Map load'); 134 | res(); 135 | }); 136 | }); 137 | 138 | const lineColors = { 139 | orangered: '#d42e12', 140 | mediumseagreen: '#009645', 141 | orange: '#fa9e0d', 142 | saddlebrown: '#9D5B25', 143 | darkmagenta: '#9900aa', 144 | darkslateblue: '#005ec4', 145 | gray: '#748477', 146 | }; 147 | const lineColorsExpression = [ 148 | 'match', 149 | ['get', 'line_color'], 150 | ...Object.keys(lineColors) 151 | .map((c) => [c, lineColors[c]]) 152 | .flat(), 153 | '#748477', 154 | ]; 155 | 156 | function formatArriveTime(str) { 157 | if (/\d/.test(str)) { 158 | return str + ' min' + (str == '1' ? '' : 's'); 159 | } 160 | return str; 161 | } 162 | 163 | const origTitle = document.title; 164 | let currentStation; 165 | const stationView = { 166 | mount: (feature) => { 167 | // set title 168 | const { properties, geometry } = feature; 169 | const { 170 | name, 171 | 'name_zh-Hans': name_zh_Hans, 172 | name_ta, 173 | station_codes, 174 | station_colors, 175 | wikipedia_slug, 176 | } = properties; 177 | 178 | document.title = `${name} / ${name_zh_Hans} / ${name_ta} (${station_codes}) – RailRouter SG`; 179 | 180 | $station.classList.remove('min'); 181 | 182 | const zoom = map.getZoom(); 183 | const isScreenLarge = window.innerWidth >= 640; 184 | const padding = isScreenLarge 185 | ? { left: 320 } 186 | : { bottom: window.innerHeight / 2 }; 187 | if (zoom <= 13) { 188 | map.jumpTo({ 189 | center: geometry.coordinates, 190 | zoom: 16.5, 191 | pitch: 70, 192 | padding, 193 | }); 194 | } else { 195 | map.easeTo({ 196 | center: geometry.coordinates, 197 | zoom: 16.5, 198 | pitch: 70, 199 | padding, 200 | duration: 500, 201 | }); 202 | } 203 | 204 | if (station_codes === currentStation) return; 205 | 206 | currentStation = station_codes; 207 | $station.innerHTML = ` 208 |
209 | 210 | ${station_codes 211 | .split('-') 212 | .map( 213 | (c, i) => 214 | `${c.replace( 215 | /^([a-z]+)/i, 216 | '$1 ', 217 | )}`, 218 | ) 219 | .join('')} 220 | 221 |

222 | ${name}
223 | ${name_zh_Hans}    224 | ${name_ta} 225 |

226 |
227 |
228 | ${ 229 | /*

Arrival times

Loading…

*/ '' 230 | } 231 |
232 |
233 |
234 | `; 235 | $station.classList.add('open'); 236 | // arrivalTimes.mount(name); 237 | stationsExits.mount(exitsData[station_codes], feature); 238 | wikipedia.mount(wikipedia_slug); 239 | }, 240 | unmount: () => { 241 | document.title = origTitle; 242 | currentStation = null; 243 | $station.classList.remove('open'); 244 | $station.classList.remove('min'); 245 | 246 | const zoom = map.getZoom(); 247 | const isScreenLarge = window.innerWidth >= 800; 248 | map.easeTo({ 249 | zoom: zoom - 1, 250 | pitch: 0, 251 | bearing: 0, 252 | padding: isScreenLarge ? { left: 0 } : { bottom: 0 }, 253 | duration: 500, 254 | }); 255 | }, 256 | }; 257 | 258 | let arrivalTimeout; 259 | const arrivalTimes = { 260 | render: (name) => { 261 | const $arrivals = $station.querySelector('.arrivals'); 262 | fetch( 263 | `https://connectv3.smrt.wwprojects.com/smrt/api/train_arrival_time_by_id/?station=${encodeURIComponent( 264 | name, 265 | )}`, 266 | ) 267 | .then((res) => res.json()) 268 | .then(({ results }) => { 269 | if (!results.length) { 270 | throw new Error('No results'); 271 | } 272 | const html = results 273 | .filter((result, pos, arr) => { 274 | // Filter weird destination names 275 | if (/do not board/i.test(result.next_train_destination)) 276 | return false; 277 | return ( 278 | arr.findIndex( 279 | (r) => 280 | r.next_train_destination == result.next_train_destination, 281 | ) == pos 282 | ); 283 | }) 284 | .map((result) => { 285 | let arrow = '⇢'; 286 | const isWeirdName = /do not board/i.test( 287 | result.next_train_destination, 288 | ); 289 | if (result.next_train_destination == result.mrt) { 290 | arrow = '⇠'; 291 | } 292 | let dest = result.next_train_destination; 293 | if (isWeirdName) { 294 | if (/do not board/i.test(result.subseq_train_destination)) { 295 | // Weird name again 296 | dest = result.mrt; 297 | arrow = '⇠'; 298 | } else { 299 | dest = result.subseq_train_destination; 300 | } 301 | } 302 | return ` 303 | ${arrow} ${dest} 304 | ${result.next_train_arr} 305 | ${formatArriveTime(result.subseq_train_arr)} 306 | `; 307 | }) 308 | .join(''); 309 | 310 | $arrivals.innerHTML = `

Arrival times

311 | 312 | 313 | ${html} 314 | 315 | 316 | 317 | 320 | 321 | 322 |
318 | Arrival times powered by SMRT Trains Ltd. 319 |
`; 323 | }) 324 | .catch((e) => { 325 | $arrivals.innerHTML = `

Arrival times

326 |

No arrival times available

`; 327 | }); 328 | }, 329 | mount: (name) => { 330 | clearTimeout(arrivalTimeout); 331 | arrivalTimes.render(name); 332 | arrivalTimeout = setTimeout(() => { 333 | requestAnimationFrame(() => { 334 | arrivalTimes.render(name); 335 | }); 336 | }, 30 * 1000); // every 30 seconds 337 | }, 338 | unmount: () => { 339 | clearTimeout(arrivalTimeout); 340 | }, 341 | }; 342 | 343 | const wikipedia = { 344 | mount: (slug) => { 345 | const $wikipedia = $station.querySelector('.wikipedia'); 346 | fetch( 347 | `https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent( 348 | slug, 349 | )}`, 350 | ) 351 | .then((res) => res.json()) 352 | .then((res) => { 353 | const { 354 | content_urls: { 355 | desktop: { page }, 356 | }, 357 | extract_html, 358 | thumbnail: { source, width, height }, 359 | } = res; 360 | const html = `
361 | 365 |
${extract_html}
366 | 367 |
`; 368 | $wikipedia.innerHTML = html; 369 | }); 370 | }, 371 | }; 372 | 373 | const stationsExits = { 374 | onExitClick: (e) => { 375 | const $exit = e.target.closest('.exit-btn'); 376 | if (!$exit) return; 377 | const coords = $exit.dataset.coords.split(',').map(parseFloat); 378 | const angle = $exit.dataset.angle; 379 | map.flyTo({ 380 | center: coords, 381 | zoom: 20, 382 | bearing: angle, 383 | }); 384 | }, 385 | mount: (exits, feature) => { 386 | const $exits = $station.querySelector('.exits'); 387 | const sortedExits = exits.sort((a, b) => { 388 | if (isNaN(a.properties.name)) { 389 | if (a.properties.name < b.properties.name) return -1; 390 | if (a.properties.name > b.properties.name) return 1; 391 | return 0; 392 | } 393 | return a.properties.name - b.properties.name; 394 | }); 395 | const { coordinates: stationCoords } = feature.geometry; 396 | const hasDups = sortedExits.some( 397 | (exit, i) => exit.properties.name == sortedExits[i + 1]?.properties.name, 398 | ); 399 | 400 | // check missing exits by comparing total exits to last exit number, only for numbered exits 401 | const hasMissingExits = 402 | !isNaN(sortedExits[0].properties.name) && 403 | sortedExits.length < sortedExits[sortedExits.length - 1].properties.name; 404 | 405 | const html = sortedExits 406 | .map(({ properties: { name }, geometry: { coordinates } }) => { 407 | // angle between stationCoords and coordinates, relative to north, in degrees 408 | const angle = Math.atan2( 409 | stationCoords[0] - coordinates[0], 410 | stationCoords[1] - coordinates[1], 411 | ); 412 | const angleDeg = (angle * 180) / Math.PI; 413 | return ` 414 | 417 | `; 418 | }) 419 | .join(''); 420 | $exits.innerHTML = `

${exits.length} Exit${ 421 | exits.length === 1 ? '' : 's' 422 | }

423 |
424 | ${html} 425 |
426 | ${ 427 | hasDups 428 | ? '

Note: The data unfortunately contains duplicated exits. Please check your surroundings before proceeding.

' 429 | : '' 430 | } 431 | ${ 432 | hasMissingExits 433 | ? '

Note: The data unfortunately contains missing exits. They could also be under construction or not opened yet.

' 434 | : '' 435 | } 436 | `; 437 | $station.addEventListener('click', stationsExits.onExitClick); 438 | }, 439 | unmount: () => { 440 | $station.removeEventListener('click', stationsExits.onExitClick); 441 | }, 442 | }; 443 | 444 | // format HH:MM for startTime and endTime 445 | const formatTime = (datetime, showAMPM = false) => { 446 | const date = new Date(datetime); 447 | let hours = date.getHours(); 448 | let minutes = date.getMinutes(); 449 | const ampm = hours >= 12 ? 'pm' : 'am'; 450 | hours = hours % 12; 451 | hours = hours ? hours : 12; // the hour '0' should be '12' 452 | minutes = minutes < 10 ? `0${minutes}` : minutes; 453 | const strTime = `${hours}:${minutes}${showAMPM ? ampm : ''}`; 454 | return strTime; 455 | }; 456 | 457 | (async () => { 458 | await mapLoaded; 459 | const layers = map.getStyle().layers; 460 | // console.log(layers); 461 | 462 | const labelLayerId = layers.find( 463 | (l) => l.type === 'symbol' && l.layout['text-field'], 464 | ).id; 465 | 466 | const data = await geojsonFetch.then((res) => res.json()); 467 | const exitsFeatures = data.features.filter((f) => { 468 | return f.properties.stop_type === 'entrance'; 469 | }); 470 | // Group entrances by station_codes 471 | exitsFeatures.forEach((f) => { 472 | const { 473 | properties: { station_codes }, 474 | } = f; 475 | if (!exitsData[station_codes]) exitsData[station_codes] = []; 476 | exitsData[station_codes].push(f); 477 | }); 478 | 479 | map.addSource('rail', { 480 | type: 'geojson', 481 | data, 482 | buffer: 0, 483 | }); 484 | 485 | // LINES 486 | map.addLayer( 487 | { 488 | id: 'lines-case', 489 | source: 'rail', 490 | filter: ['==', ['geometry-type'], 'LineString'], 491 | type: 'line', 492 | minzoom: 11, 493 | layout: { 494 | 'line-cap': 'round', 495 | 'line-join': 'round', 496 | }, 497 | paint: { 498 | 'line-width': ['interpolate', ['linear'], ['zoom'], 10, 1, 22, 30], 499 | 'line-color': lineColorsExpression, 500 | 'line-opacity': 0.25, 501 | 'line-blur': ['interpolate', ['linear'], ['zoom'], 10, 0, 22, 14], 502 | }, 503 | }, 504 | 'building-extrusion', 505 | ); 506 | map.addLayer( 507 | { 508 | id: 'lines', 509 | source: 'rail', 510 | filter: ['==', ['geometry-type'], 'LineString'], 511 | type: 'line', 512 | layout: { 513 | 'line-cap': 'round', 514 | 'line-join': 'round', 515 | }, 516 | paint: { 517 | 'line-width': ['interpolate', ['linear'], ['zoom'], 0, 1, 22, 2], 518 | 'line-color': lineColorsExpression, 519 | }, 520 | }, 521 | labelLayerId, 522 | ); 523 | map.addLayer({ 524 | id: 'lines-label', 525 | source: 'rail', 526 | filter: ['==', ['geometry-type'], 'LineString'], 527 | type: 'symbol', 528 | minzoom: 13, 529 | layout: { 530 | 'symbol-placement': 'line', 531 | 'text-field': ['get', 'name'], 532 | 'text-font': ['DIN Pro Medium', 'Arial Unicode MS Regular'], 533 | 'text-letter-spacing': 0.1, 534 | 'text-size': ['interpolate', ['linear'], ['zoom'], 13, 12, 22, 16], 535 | 'text-pitch-alignment': 'viewport', 536 | 'text-rotation-alignment': 'map', 537 | 'text-max-angle': 30, 538 | 'text-padding': 1, 539 | }, 540 | paint: { 541 | 'text-color': lineColorsExpression, 542 | 'text-halo-blur': 1, 543 | 'text-halo-color': '#fff', 544 | 'text-halo-width': 2, 545 | }, 546 | }); 547 | 548 | // EXITS 549 | map.addLayer({ 550 | id: 'exits', 551 | source: 'rail', 552 | filter: ['==', ['get', 'stop_type'], 'entrance'], 553 | type: 'symbol', 554 | minzoom: 14, 555 | layout: { 556 | 'icon-image': 'exit', 557 | 'icon-size': ['interpolate', ['linear'], ['zoom'], 14, 0.25, 17, 0.6], 558 | 'icon-allow-overlap': true, 559 | }, 560 | }); 561 | map.addLayer({ 562 | id: 'exits-label', 563 | source: 'rail', 564 | filter: ['==', ['get', 'stop_type'], 'entrance'], 565 | type: 'symbol', 566 | minzoom: 14, 567 | layout: { 568 | 'text-field': ['get', 'name'], 569 | 'text-font': ['DIN Pro Medium', 'Arial Unicode MS Regular'], 570 | 'text-size': ['interpolate', ['linear'], ['zoom'], 14, 5, 17, 13], 571 | 'text-ignore-placement': true, 572 | 'text-allow-overlap': true, 573 | }, 574 | paint: { 575 | 'text-color': '#000', 576 | 'text-translate-anchor': 'viewport', 577 | 'text-translate': [ 578 | 'interpolate', 579 | ['linear'], 580 | ['zoom'], 581 | 14, 582 | ['literal', [0, 1]], 583 | 16, 584 | ['literal', [0, 2]], 585 | ], 586 | }, 587 | }); 588 | 589 | // STATIONS 590 | map.addLayer({ 591 | id: 'stations-point', 592 | source: 'rail', 593 | filter: ['==', ['get', 'stop_type'], 'station'], 594 | type: 'symbol', 595 | minzoom: 10, 596 | maxzoom: 14, 597 | layout: { 598 | 'icon-image': ['get', 'station_colors'], 599 | 'icon-size': [ 600 | 'interpolate', 601 | ['exponential', 2], 602 | ['zoom'], 603 | 10, 604 | 0.2, 605 | 14, 606 | 1, 607 | ], 608 | 'icon-allow-overlap': true, 609 | }, 610 | }); 611 | map.addLayer({ 612 | id: 'stations-point-label', 613 | source: 'rail', 614 | filter: [ 615 | 'all', 616 | ['==', ['get', 'stop_type'], 'station'], 617 | ['in', '-', ['get', 'station_codes']], 618 | ], 619 | type: 'symbol', 620 | minzoom: 10, 621 | maxzoom: 13, 622 | layout: { 623 | 'symbol-avoid-edges': true, 624 | 'text-field': ['get', 'name'], 625 | 'text-size': ['interpolate', ['linear'], ['zoom'], 10, 10, 13, 12], 626 | 'text-font': ['DIN Pro Medium', 'Arial Unicode MS Regular'], 627 | 'text-variable-anchor': ['left', 'right'], 628 | 'text-radial-offset': [ 629 | 'interpolate', 630 | ['linear'], 631 | ['zoom'], 632 | 10, 633 | ['*', 0.25, ['get', 'network_count']], 634 | 13, 635 | ['*', 0.5, ['get', 'network_count']], 636 | ], 637 | 'text-max-width': 20, 638 | 'text-optional': true, 639 | }, 640 | paint: { 641 | 'text-color': 'rgba(0,0,0,.5)', 642 | 'text-halo-color': 'rgba(255,255,255,.5)', 643 | 'text-halo-width': 1, 644 | 'text-halo-blur': 1, 645 | }, 646 | }); 647 | map.addLayer({ 648 | id: 'stations-label-non-en', 649 | source: 'rail', 650 | filter: ['==', ['get', 'stop_type'], 'station'], 651 | type: 'symbol', 652 | minzoom: 13, 653 | layout: { 654 | 'text-field': [ 655 | 'format', 656 | ['get', 'name_zh-Hans'], 657 | {}, 658 | '\n', 659 | {}, 660 | ['get', 'name_ta'], 661 | { 662 | // 'text-font': ['literal', ['Noto Sans Tamil Medium']], 663 | // 'font-scale': 1.1, // Slightly larger text size for Tamil 664 | }, 665 | ], 666 | 'text-size': ['interpolate', ['linear'], ['zoom'], 13, 12, 16, 16], 667 | 'text-font': ['DIN Pro Medium', 'Arial Unicode MS Regular'], 668 | 'text-anchor': 'top', 669 | 'text-offset': [0, 0.8], 670 | 'text-max-width': 20, 671 | 'text-optional': true, 672 | }, 673 | paint: { 674 | 'text-halo-color': '#fff', 675 | 'text-halo-width': 2, 676 | 'text-halo-blur': 1, 677 | }, 678 | }); 679 | map.addLayer({ 680 | id: 'stations-label', 681 | source: 'rail', 682 | filter: ['==', ['get', 'stop_type'], 'station'], 683 | type: 'symbol', 684 | minzoom: 13, 685 | layout: { 686 | 'text-field': ['get', 'name'], 687 | 'text-size': ['interpolate', ['linear'], ['zoom'], 13, 12, 16, 16], 688 | 'text-font': ['DIN Pro Medium', 'Arial Unicode MS Regular'], 689 | 'text-anchor': 'bottom', 690 | 'text-offset': [0, -0.8], 691 | 'text-max-width': 20, 692 | // 'text-allow-overlap': true, 693 | 'icon-image': ['get', 'station_codes'], 694 | 'icon-size': ['interpolate', ['linear'], ['zoom'], 13, 0.3, 15, 0.5], 695 | 'icon-ignore-placement': true, 696 | 'icon-allow-overlap': true, 697 | }, 698 | paint: { 699 | 'text-halo-color': '#fff', 700 | 'text-halo-width': 2, 701 | 'text-halo-blur': 1, 702 | }, 703 | }); 704 | 705 | // STATION BUILDINGS 706 | map.addLayer( 707 | { 708 | id: 'buildings-underground', 709 | source: 'rail', 710 | filter: [ 711 | 'all', 712 | ['==', ['get', 'type'], 'subway'], 713 | ['==', ['get', 'underground'], true], 714 | ], 715 | type: 'fill', 716 | minzoom: 14, 717 | paint: { 718 | 'fill-antialias': false, 719 | 'fill-color': 'hsla(6, 63%, 60%, 0.3)', 720 | 'fill-outline-color': '#d96659', 721 | }, 722 | }, 723 | 'building-extrusion', 724 | ); 725 | map.addLayer( 726 | { 727 | id: 'buildings-aboveground', 728 | source: 'rail', 729 | filter: [ 730 | 'all', 731 | ['==', ['get', 'type'], 'subway'], 732 | ['==', ['get', 'underground'], false], 733 | ], 734 | type: 'fill-extrusion', 735 | minzoom: 14, 736 | paint: { 737 | 'fill-extrusion-color': '#d96659', 738 | 'fill-extrusion-height': 20, 739 | 'fill-extrusion-opacity': 0.3, 740 | }, 741 | }, 742 | 'building-extrusion', 743 | ); 744 | 745 | // const handleSource = (e) => { 746 | // if (e.sourceId !== 'rail' || e.sourceDataType === 'metadata') return; 747 | // map.off('sourcedata', handleSource); 748 | 749 | // const lineFeatures = map.querySourceFeatures('rail', { 750 | // filter: ['==', ['geometry-type'], 'LineString'], 751 | // }); 752 | 753 | // const linesBounds = {}; 754 | // lineFeatures.forEach((l) => { 755 | // const { 756 | // properties: { name }, 757 | // geometry: { type, coordinates }, 758 | // } = l; 759 | // if (!linesBounds[name]) linesBounds[name] = new mapboxgl.LngLatBounds(); 760 | // coordinates.flat(type === 'LineString' ? 0 : 1).forEach((c) => { 761 | // linesBounds[name].extend(c); 762 | // }); 763 | // }); 764 | // console.log(lineFeatures, linesBounds); 765 | // }; 766 | // map.on('sourcedata', handleSource); 767 | 768 | map.on('click', 'stations-label', (e) => { 769 | location.hash = `stations/${e.features[0].properties.name}`; 770 | // stationView.mount(e.features[0]); 771 | }); 772 | 773 | // Handle onhashchange 774 | const onHashChange = () => { 775 | // hash looks like this "stations/[NAME]", get the NAME, find it in the geojson and show it 776 | const name = decodeURIComponent(location.hash.split('/')[1] || ''); 777 | const stationData = 778 | name && 779 | data.features.find((f) => { 780 | const { name: fName, station_codes } = f.properties; 781 | const hasName = (fName || '').toLowerCase() === name.toLowerCase(); 782 | if (hasName) return true; 783 | // Also works if "stations/[CODE]" e.g. "stations/NS1" 784 | const codes = station_codes.split('-'); 785 | // Array.includes but case-insensitive 786 | return codes.some((c) => c.toLowerCase() === name.toLowerCase()); 787 | }); 788 | if (stationData) { 789 | stationView.mount(stationData); 790 | } else { 791 | stationView.unmount(); 792 | } 793 | }; 794 | window.addEventListener('hashchange', onHashChange); 795 | requestAnimationFrame(onHashChange); 796 | 797 | document.querySelector('.sheet-close').onclick = (e) => { 798 | e.preventDefault(); 799 | location.hash = ''; 800 | // stationView.unmount(); 801 | }; 802 | 803 | map.on('movestart', (e) => { 804 | if (!e.originalEvent) return; // Not initiated by humans 805 | if (!currentStation) return; 806 | $station.classList.add('min'); 807 | }); 808 | 809 | $station.onclick = (e) => { 810 | if ($station.classList.contains('min')) { 811 | e.preventDefault(); 812 | e.stopPropagation(); 813 | $station.classList.remove('min'); 814 | } 815 | }; 816 | 817 | map.on('mouseenter', 'stations-label', () => { 818 | mapCanvas.style.cursor = 'pointer'; 819 | }); 820 | map.on('mouseleave', 'stations-label', () => { 821 | mapCanvas.style.cursor = ''; 822 | }); 823 | 824 | setTimeout(() => { 825 | map.loadImage(require('./exit.png'), (e, img) => { 826 | map.addImage('exit', img); 827 | }); 828 | 829 | const canvas = document.createElement('canvas'); 830 | const ctx = canvas.getContext('2d', { 831 | willReadFrequently: true, 832 | }); 833 | map.loadImage(require('./stations.png'), (e, img) => { 834 | if (!img) return; 835 | canvas.width = img.width; 836 | canvas.height = img.height; 837 | ctx.drawImage(img, 0, 0); 838 | stationsSprite.forEach((s) => { 839 | const [code, ...args] = s; 840 | const imageData = ctx.getImageData(...args); 841 | map.addImage(code, imageData); 842 | }); 843 | }); 844 | 845 | stationsData = data.features.filter((f) => { 846 | return f.properties.stop_type === 'station'; 847 | }); 848 | fuse = new Fuse(stationsData, { 849 | distance: 5, 850 | includeMatches: true, 851 | keys: [ 852 | 'properties.name', 853 | 'properties.name_zh-Hans', 854 | 'properties.name_ta', 855 | { 856 | name: 'station_codes', 857 | getFn: (obj) => { 858 | return obj.properties.station_codes.split('-'); 859 | }, 860 | weight: 0.5, 861 | }, 862 | ], 863 | }); 864 | 865 | map.addSource('walks', { 866 | type: 'geojson', 867 | data: require('./sg-rail-walks.geo.json'), 868 | buffer: 0, 869 | }); 870 | map.addLayer( 871 | { 872 | id: 'walks-case', 873 | source: 'walks', 874 | filter: ['==', ['geometry-type'], 'LineString'], 875 | type: 'line', 876 | minzoom: 14, 877 | layout: { 878 | 'line-cap': 'round', 879 | 'line-join': 'round', 880 | }, 881 | paint: { 882 | 'line-width': ['interpolate', ['linear'], ['zoom'], 15, 3, 22, 15], 883 | 'line-color': 'rgba(255, 255, 255, .75)', 884 | }, 885 | }, 886 | 'building-extrusion', 887 | ); 888 | map.addLayer( 889 | { 890 | id: 'walks', 891 | source: 'walks', 892 | filter: ['==', ['geometry-type'], 'LineString'], 893 | type: 'line', 894 | minzoom: 14, 895 | layout: { 896 | 'line-cap': 'round', 897 | 'line-join': 'round', 898 | }, 899 | paint: { 900 | 'line-width': ['interpolate', ['linear'], ['zoom'], 15, 1, 22, 5], 901 | 'line-color': 'skyblue', 902 | 'line-dasharray': [0.5, 2], 903 | }, 904 | }, 905 | 'building-extrusion', 906 | ); 907 | map.addLayer( 908 | { 909 | id: 'walks-label', 910 | source: 'walks', 911 | filter: ['==', ['geometry-type'], 'Point'], 912 | type: 'symbol', 913 | minzoom: 15.5, 914 | layout: { 915 | 'text-field': ['concat', ['get', 'duration_min'], ' mins'], 916 | 'text-font': ['DIN Pro Medium', 'Arial Unicode MS Regular'], 917 | 'text-size': ['interpolate', ['linear'], ['zoom'], 15, 12, 22, 16], 918 | 'text-anchor': 'top', 919 | 'text-offset': [0, 0.8], 920 | 'icon-image': 'walk', 921 | 'icon-size': 0.5, 922 | }, 923 | paint: { 924 | 'text-color': 'dodgerblue', 925 | 'text-halo-color': 'rgba(255,255,255,.75)', 926 | 'text-halo-width': 2, 927 | 'icon-halo-color': 'rgba(255,255,255,.75)', 928 | 'icon-halo-width': 2, 929 | }, 930 | }, 931 | 'exits-label', 932 | ); 933 | map.on('mouseenter', 'walks-label', () => { 934 | mapCanvas.style.cursor = 'pointer'; 935 | }); 936 | map.on('mouseleave', 'walks-label', () => { 937 | mapCanvas.style.cursor = ''; 938 | }); 939 | map.on('click', 'walks-label', (e) => { 940 | const f = e.features[0]; 941 | const { 942 | duration_min, 943 | station_codes_1, 944 | station_codes_2, 945 | exit_name_1, 946 | exit_name_2, 947 | } = f.properties; 948 | const station1 = stationsData.find( 949 | (d) => d.properties.station_codes === station_codes_1, 950 | ); 951 | const station2 = stationsData.find( 952 | (d) => d.properties.station_codes === station_codes_2, 953 | ); 954 | alert( 955 | `${duration_min}-min walk between ${station1.properties.name} (Exit ${exit_name_1}) and ${station2.properties.name} (Exit ${exit_name_2})`, 956 | ); 957 | }); 958 | map.loadImage(require('./walk.png'), (e, img) => { 959 | map.addImage('walk', img); 960 | }); 961 | }, 300); 962 | 963 | let markers = []; 964 | map.on('zoomend', () => { 965 | const zoom = map.getZoom(); 966 | const large = zoom >= 12; 967 | const larger = zoom >= 15; 968 | markers.forEach((m) => { 969 | m.getElement().classList.toggle('large', large); 970 | m.getElement().classList.toggle('larger', larger); 971 | m.getElement().style.cursor = zoom >= 13 ? 'pointer' : ''; 972 | }); 973 | }); 974 | const renderCrowd = () => { 975 | markers.forEach((m) => { 976 | m.remove(); 977 | }); 978 | 979 | fetch('https://sg-rail-crowd.cheeaun.workers.dev/') 980 | .then((res) => res.json()) 981 | .then((results) => { 982 | const zoom = map.getZoom(); 983 | const large = zoom >= 12; 984 | const larger = zoom >= 15; 985 | const crowdedData = []; 986 | results.data.forEach((r) => { 987 | const { station, crowdLevel } = r; 988 | if (!crowdLevel || (crowdLevel !== 'h' && crowdLevel !== 'm')) return; 989 | const f = data.features.find((f) => 990 | f.properties.station_codes.split('-').includes(station), 991 | ); 992 | 993 | if (!f) return; 994 | 995 | crowdedData.push(r); 996 | 997 | // const markerCrowdLabel = Math.random() < 0.5 ? 'h' : 'm'; 998 | const markerCrowdLabel = crowdLevel; 999 | 1000 | const el = document.createElement('div'); 1001 | const width = 50; 1002 | const height = 50; 1003 | el.className = `crowd-marker crowd-marker-${markerCrowdLabel} ${ 1004 | large ? 'large' : '' 1005 | } ${larger ? 'larger' : ''}`; 1006 | el.style.width = `${width}px`; 1007 | el.style.height = `${height}px`; 1008 | 1009 | // Add markers to the map. 1010 | const marker = new mapboxgl.Marker(el) 1011 | .setLngLat(f.geometry.coordinates) 1012 | .addTo(map); 1013 | markers.push(marker); 1014 | }); 1015 | 1016 | if (crowdedData.length) { 1017 | const startTime = formatTime(crowdedData[0].startTime); 1018 | const endTime = formatTime(crowdedData[0].endTime); 1019 | 1020 | console.log({ 1021 | startTime, 1022 | endTime, 1023 | }); 1024 | console.table( 1025 | crowdedData.map((d) => ({ 1026 | station: d.station, 1027 | crowdLevel: d.crowdLevel, 1028 | })), 1029 | ); 1030 | } 1031 | 1032 | if (results.data.length) { 1033 | $crowdedTiming.innerHTML = `Crowded time interval: ${formatTime( 1034 | results.data[0].startTime, 1035 | )} - ${formatTime(results.data[0].endTime, true)}`; 1036 | } else { 1037 | $crowdedTiming.innerHTML = 'Crowded time interval: N/A'; 1038 | } 1039 | }) 1040 | .catch((e) => { 1041 | $crowdedTiming.innerHTML = 'Crowded time interval: N/A'; 1042 | }) 1043 | .finally(() => { 1044 | setTimeout(() => { 1045 | requestAnimationFrame(renderCrowd); 1046 | }, 1000 * 60); // 1 minute 1047 | }); 1048 | }; 1049 | renderCrowd(); 1050 | })(); 1051 | 1052 | class SearchControl { 1053 | options = { 1054 | onClick: () => {}, 1055 | }; 1056 | 1057 | constructor(options) { 1058 | Object.assign(this.options, options); 1059 | } 1060 | 1061 | onAdd(map) { 1062 | this._map = map; 1063 | const container = document.createElement('div'); 1064 | container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group'; 1065 | container.innerHTML = ` 1066 | 1069 | `; 1070 | container.querySelector('button').onclick = this.options.onClick; 1071 | this._container = container; 1072 | return this._container; 1073 | } 1074 | onRemove() { 1075 | this._container.parentNode.removeChild(this._container); 1076 | this._map = undefined; 1077 | } 1078 | } 1079 | function focusSearchField() { 1080 | $search.hidden = false; 1081 | $searchField.focus(); 1082 | setTimeout(() => { 1083 | $searchField.focus(); 1084 | }, 1500); 1085 | } 1086 | map.addControl( 1087 | new SearchControl({ 1088 | onClick: focusSearchField, 1089 | }), 1090 | 'bottom-right', 1091 | ); 1092 | document.onkeydown = (e) => { 1093 | if (/(input|textarea|select)/i.test(e.target.tagName)) return; 1094 | if ( 1095 | e.code.toLowerCase() === 'slash' || 1096 | e.key === '/' || 1097 | e.keyCode === 191 || 1098 | e.which === 191 1099 | ) { 1100 | e.preventDefault(); 1101 | focusSearchField(); 1102 | } 1103 | }; 1104 | 1105 | $searchField.oninput = () => { 1106 | if (!fuse) return; 1107 | const value = $searchField.value.trim(); 1108 | const results = fuse.search(value); 1109 | $searchResults.innerHTML = results 1110 | .slice(0, 10) 1111 | .map((r) => { 1112 | const { 1113 | item: { properties }, 1114 | matches, 1115 | } = r; 1116 | const firstNameMatch = matches.find((m) => /name/i.test(m.key)); 1117 | const { name: stationName, station_codes, station_colors } = properties; 1118 | const name = 1119 | properties[ 1120 | firstNameMatch ? firstNameMatch.key.replace(/.+\./, '') : 'name' 1121 | ]; 1122 | const html = `
  • 1123 | 1124 | 1125 | ${station_codes 1126 | .split('-') 1127 | .map( 1128 | (c, i) => 1129 | `${c.replace( 1130 | /^([a-z]+)/i, 1131 | '$1 ', 1132 | )}`, 1133 | ) 1134 | .join('')} 1135 | 1136 | ${name} 1137 | 1138 |
  • `; 1139 | return html; 1140 | }) 1141 | .join(''); 1142 | }; 1143 | 1144 | $searchField.onkeydown = (e) => { 1145 | // Enter 1146 | if (e.code.toLowerCase() === 'enter' || e.keyCode === 13 || e.which === 13) { 1147 | $searchField.blur(); 1148 | $searchResults.querySelector('a')?.click(); 1149 | } 1150 | }; 1151 | 1152 | $searchCancel.onclick = () => { 1153 | $search.hidden = true; 1154 | $searchField.value = ''; 1155 | }; 1156 | 1157 | $searchResults.onclick = (e) => { 1158 | // const { target } = e; 1159 | // if (target.tagName.toLowerCase() !== 'li') return; 1160 | // const { codes } = target.dataset; 1161 | // const feature = stationsData.find( 1162 | // (d) => d.properties.station_codes === codes, 1163 | // ); 1164 | // stationView.mount(feature); 1165 | $search.hidden = true; 1166 | $searchField.value = ''; 1167 | document.body.scrollTo(0, 0); 1168 | }; 1169 | 1170 | if ('serviceWorker' in navigator) { 1171 | window.addEventListener('load', function () { 1172 | navigator.serviceWorker.register(new URL('./sw.js', import.meta.url), { 1173 | type: 'module', 1174 | }); 1175 | }); 1176 | } 1177 | 1178 | map.addControl( 1179 | new mapboxgl.NavigationControl({ 1180 | showZoom: false, 1181 | visualizePitch: true, 1182 | }), 1183 | 'bottom-right', 1184 | ); 1185 | -------------------------------------------------------------------------------- /src/sg-rail-walks.geo.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": {}, 7 | "geometry": { 8 | "type": "LineString", 9 | "coordinates": [ 10 | [ 11 | 103.84956, 12 | 1.298199 13 | ], 14 | [ 15 | 103.84957, 16 | 1.29819 17 | ], 18 | [ 19 | 103.84953, 20 | 1.29815 21 | ], 22 | [ 23 | 103.8495, 24 | 1.29815 25 | ], 26 | [ 27 | 103.84951, 28 | 1.29811 29 | ], 30 | [ 31 | 103.84958, 32 | 1.29806 33 | ], 34 | [ 35 | 103.84963, 36 | 1.29802 37 | ], 38 | [ 39 | 103.84967, 40 | 1.29801 41 | ], 42 | [ 43 | 103.8497, 44 | 1.29801 45 | ], 46 | [ 47 | 103.84977, 48 | 1.29799 49 | ], 50 | [ 51 | 103.84977, 52 | 1.29792 53 | ], 54 | [ 55 | 103.84978, 56 | 1.29789 57 | ], 58 | [ 59 | 103.84989, 60 | 1.29781 61 | ], 62 | [ 63 | 103.84995, 64 | 1.29776 65 | ], 66 | [ 67 | 103.85012, 68 | 1.29762 69 | ], 70 | [ 71 | 103.85012, 72 | 1.29759 73 | ], 74 | [ 75 | 103.85014, 76 | 1.29757 77 | ], 78 | [ 79 | 103.85016, 80 | 1.29755 81 | ], 82 | [ 83 | 103.850158, 84 | 1.297551 85 | ] 86 | ] 87 | } 88 | }, 89 | { 90 | "type": "Feature", 91 | "properties": { 92 | "duration_min": 2, 93 | "station_codes_1": "DT21", 94 | "station_codes_2": "CC2", 95 | "exit_name_1": "B", 96 | "exit_name_2": "D" 97 | }, 98 | "geometry": { 99 | "type": "Point", 100 | "coordinates": [ 101 | 103.84977516823972, 102 | 1.2979044952809418 103 | ] 104 | } 105 | }, 106 | { 107 | "type": "Feature", 108 | "properties": {}, 109 | "geometry": { 110 | "type": "LineString", 111 | "coordinates": [ 112 | [ 113 | 103.850843, 114 | 1.299195 115 | ], 116 | [ 117 | 103.8508, 118 | 1.29923 119 | ], 120 | [ 121 | 103.85084, 122 | 1.29928 123 | ], 124 | [ 125 | 103.85087, 126 | 1.29932 127 | ], 128 | [ 129 | 103.85096, 130 | 1.29943 131 | ], 132 | [ 133 | 103.85097, 134 | 1.29944 135 | ], 136 | [ 137 | 103.85103, 138 | 1.29951 139 | ], 140 | [ 141 | 103.85139, 142 | 1.29995 143 | ], 144 | [ 145 | 103.85147, 146 | 1.30005 147 | ], 148 | [ 149 | 103.85166, 150 | 1.30027 151 | ], 152 | [ 153 | 103.85201, 154 | 1.29999 155 | ], 156 | [ 157 | 103.85209, 158 | 1.29992 159 | ], 160 | [ 161 | 103.85225, 162 | 1.29979 163 | ], 164 | [ 165 | 103.85225, 166 | 1.29977 167 | ], 168 | [ 169 | 103.85224, 170 | 1.29976 171 | ], 172 | [ 173 | 103.85238, 174 | 1.29965 175 | ], 176 | [ 177 | 103.85241, 178 | 1.29963 179 | ], 180 | [ 181 | 103.85241, 182 | 1.29962 183 | ], 184 | [ 185 | 103.85245, 186 | 1.29963 187 | ], 188 | [ 189 | 103.85267, 190 | 1.29944 191 | ], 192 | [ 193 | 103.85303, 194 | 1.29914 195 | ], 196 | [ 197 | 103.85304, 198 | 1.29913 199 | ], 200 | [ 201 | 103.85305, 202 | 1.29912 203 | ], 204 | [ 205 | 103.85315, 206 | 1.29904 207 | ], 208 | [ 209 | 103.85317, 210 | 1.29903 211 | ], 212 | [ 213 | 103.85319, 214 | 1.29905 215 | ], 216 | [ 217 | 103.85323, 218 | 1.29902 219 | ], 220 | [ 221 | 103.85324, 222 | 1.29903 223 | ], 224 | [ 225 | 103.85336, 226 | 1.29918 227 | ], 228 | [ 229 | 103.85338, 230 | 1.2992 231 | ], 232 | [ 233 | 103.85394, 234 | 1.29874 235 | ], 236 | [ 237 | 103.85395, 238 | 1.29873 239 | ], 240 | [ 241 | 103.85399, 242 | 1.29871 243 | ], 244 | [ 245 | 103.85401, 246 | 1.29869 247 | ], 248 | [ 249 | 103.85424, 250 | 1.2985 251 | ], 252 | [ 253 | 103.85427, 254 | 1.29849 255 | ], 256 | [ 257 | 103.85429, 258 | 1.29853 259 | ], 260 | [ 261 | 103.8543, 262 | 1.29854 263 | ], 264 | [ 265 | 103.85474, 266 | 1.29904 267 | ], 268 | [ 269 | 103.85478, 270 | 1.29908 271 | ], 272 | [ 273 | 103.8548, 274 | 1.29906 275 | ], 276 | [ 277 | 103.85481, 278 | 1.29908 279 | ], 280 | [ 281 | 103.85493, 282 | 1.29922 283 | ], 284 | [ 285 | 103.85507, 286 | 1.29938 287 | ], 288 | [ 289 | 103.85502, 290 | 1.2994 291 | ], 292 | [ 293 | 103.85502, 294 | 1.29941 295 | ], 296 | [ 297 | 103.855, 298 | 1.29942 299 | ], 300 | [ 301 | 103.85506, 302 | 1.29949 303 | ], 304 | [ 305 | 103.85508, 306 | 1.29947 307 | ], 308 | [ 309 | 103.85515, 310 | 1.29955 311 | ], 312 | [ 313 | 103.85537, 314 | 1.29978 315 | ], 316 | [ 317 | 103.85542, 318 | 1.29984 319 | ], 320 | [ 321 | 103.85543, 322 | 1.29985 323 | ], 324 | [ 325 | 103.85548, 326 | 1.29991 327 | ], 328 | [ 329 | 103.8555, 330 | 1.29993 331 | ], 332 | [ 333 | 103.85554, 334 | 1.29991 335 | ], 336 | [ 337 | 103.85559, 338 | 1.29998 339 | ], 340 | [ 341 | 103.85564, 342 | 1.30004 343 | ], 344 | [ 345 | 103.855686, 346 | 1.300007 347 | ] 348 | ] 349 | } 350 | }, 351 | { 352 | "type": "Feature", 353 | "properties": { 354 | "duration_min": 10, 355 | "station_codes_1": "DT21", 356 | "station_codes_2": "EW12-DT14", 357 | "exit_name_1": "A", 358 | "exit_name_2": "C" 359 | }, 360 | "geometry": { 361 | "type": "Point", 362 | "coordinates": [ 363 | 103.8532587562409, 364 | 1.2990534453026883 365 | ] 366 | } 367 | }, 368 | { 369 | "type": "Feature", 370 | "properties": {}, 371 | "geometry": { 372 | "type": "LineString", 373 | "coordinates": [ 374 | [ 375 | 103.849272, 376 | 1.297699 377 | ], 378 | [ 379 | 103.84923, 380 | 1.29773 381 | ], 382 | [ 383 | 103.84922, 384 | 1.29772 385 | ], 386 | [ 387 | 103.84911, 388 | 1.29759 389 | ], 390 | [ 391 | 103.84897, 392 | 1.29745 393 | ], 394 | [ 395 | 103.84892, 396 | 1.29743 397 | ], 398 | [ 399 | 103.84895, 400 | 1.2974 401 | ], 402 | [ 403 | 103.84896, 404 | 1.29739 405 | ], 406 | [ 407 | 103.84905, 408 | 1.2973 409 | ], 410 | [ 411 | 103.84903, 412 | 1.29727 413 | ], 414 | [ 415 | 103.84904, 416 | 1.29725 417 | ], 418 | [ 419 | 103.84903, 420 | 1.29724 421 | ], 422 | [ 423 | 103.8489, 424 | 1.29714 425 | ], 426 | [ 427 | 103.84886, 428 | 1.29711 429 | ], 430 | [ 431 | 103.84892, 432 | 1.29706 433 | ], 434 | [ 435 | 103.84894, 436 | 1.29705 437 | ], 438 | [ 439 | 103.849, 440 | 1.29697 441 | ], 442 | [ 443 | 103.84911, 444 | 1.29684 445 | ], 446 | [ 447 | 103.84916, 448 | 1.29677 449 | ], 450 | [ 451 | 103.84921, 452 | 1.29671 453 | ], 454 | [ 455 | 103.8493, 456 | 1.2966 457 | ], 458 | [ 459 | 103.84932, 460 | 1.29657 461 | ], 462 | [ 463 | 103.84934, 464 | 1.29654 465 | ], 466 | [ 467 | 103.84937, 468 | 1.29649 469 | ], 470 | [ 471 | 103.84941, 472 | 1.29643 473 | ], 474 | [ 475 | 103.84943, 476 | 1.2963 477 | ], 478 | [ 479 | 103.84943, 480 | 1.29628 481 | ], 482 | [ 483 | 103.84945, 484 | 1.29614 485 | ], 486 | [ 487 | 103.84946, 488 | 1.29612 489 | ], 490 | [ 491 | 103.84945, 492 | 1.29606 493 | ], 494 | [ 495 | 103.84946, 496 | 1.29599 497 | ], 498 | [ 499 | 103.84951, 500 | 1.29575 501 | ], 502 | [ 503 | 103.84959, 504 | 1.29549 505 | ], 506 | [ 507 | 103.84967, 508 | 1.29535 509 | ], 510 | [ 511 | 103.84977, 512 | 1.29514 513 | ], 514 | [ 515 | 103.84979, 516 | 1.29512 517 | ], 518 | [ 519 | 103.84981, 520 | 1.29511 521 | ], 522 | [ 523 | 103.8499, 524 | 1.29505 525 | ], 526 | [ 527 | 103.84999, 528 | 1.29503 529 | ], 530 | [ 531 | 103.85027, 532 | 1.29486 533 | ], 534 | [ 535 | 103.85051, 536 | 1.29471 537 | ], 538 | [ 539 | 103.85054, 540 | 1.29468 541 | ], 542 | [ 543 | 103.85056, 544 | 1.29467 545 | ], 546 | [ 547 | 103.85079, 548 | 1.29451 549 | ], 550 | [ 551 | 103.85069, 552 | 1.29436 553 | ], 554 | [ 555 | 103.85069, 556 | 1.29435 557 | ], 558 | [ 559 | 103.85122, 560 | 1.29402 561 | ], 562 | [ 563 | 103.85128, 564 | 1.29398 565 | ], 566 | [ 567 | 103.85133, 568 | 1.29395 569 | ], 570 | [ 571 | 103.85141, 572 | 1.2939 573 | ], 574 | [ 575 | 103.85179, 576 | 1.29365 577 | ], 578 | [ 579 | 103.85181, 580 | 1.29364 581 | ], 582 | [ 583 | 103.85187, 584 | 1.29356 585 | ], 586 | [ 587 | 103.85187, 588 | 1.29354 589 | ], 590 | [ 591 | 103.85186, 592 | 1.2935 593 | ], 594 | [ 595 | 103.85184, 596 | 1.29345 597 | ], 598 | [ 599 | 103.85183, 600 | 1.29344 601 | ], 602 | [ 603 | 103.85181, 604 | 1.29345 605 | ], 606 | [ 607 | 103.8518, 608 | 1.29346 609 | ], 610 | [ 611 | 103.851802, 612 | 1.293455 613 | ] 614 | ] 615 | } 616 | }, 617 | { 618 | "type": "Feature", 619 | "properties": { 620 | "duration_min": 9, 621 | "station_codes_1": "DT21", 622 | "station_codes_2": "NS25-EW13", 623 | "exit_name_1": "C", 624 | "exit_name_2": "D" 625 | }, 626 | "geometry": { 627 | "type": "Point", 628 | "coordinates": [ 629 | 103.8497124414109, 630 | 1.2952608730419028 631 | ] 632 | } 633 | }, 634 | { 635 | "type": "Feature", 636 | "properties": {}, 637 | "geometry": { 638 | "type": "LineString", 639 | "coordinates": [ 640 | [ 641 | 103.849272, 642 | 1.297699 643 | ], 644 | [ 645 | 103.84923, 646 | 1.29773 647 | ], 648 | [ 649 | 103.84922, 650 | 1.29772 651 | ], 652 | [ 653 | 103.84911, 654 | 1.29759 655 | ], 656 | [ 657 | 103.84897, 658 | 1.29745 659 | ], 660 | [ 661 | 103.84892, 662 | 1.29743 663 | ], 664 | [ 665 | 103.84889, 666 | 1.29746 667 | ], 668 | [ 669 | 103.84885, 670 | 1.29742 671 | ], 672 | [ 673 | 103.84876, 674 | 1.29733 675 | ], 676 | [ 677 | 103.84873, 678 | 1.29729 679 | ], 680 | [ 681 | 103.84871, 682 | 1.29731 683 | ], 684 | [ 685 | 103.84867, 686 | 1.29734 687 | ], 688 | [ 689 | 103.84866, 690 | 1.29735 691 | ], 692 | [ 693 | 103.84867, 694 | 1.29736 695 | ], 696 | [ 697 | 103.84867, 698 | 1.29739 699 | ], 700 | [ 701 | 103.84866, 702 | 1.2974 703 | ], 704 | [ 705 | 103.84859, 706 | 1.29746 707 | ], 708 | [ 709 | 103.84847, 710 | 1.29756 711 | ], 712 | [ 713 | 103.84823, 714 | 1.29775 715 | ], 716 | [ 717 | 103.84821, 718 | 1.29777 719 | ], 720 | [ 721 | 103.84804, 722 | 1.2979 723 | ], 724 | [ 725 | 103.84803, 726 | 1.29791 727 | ], 728 | [ 729 | 103.84788, 730 | 1.29803 731 | ], 732 | [ 733 | 103.84785, 734 | 1.29807 735 | ], 736 | [ 737 | 103.84783, 738 | 1.29808 739 | ], 740 | [ 741 | 103.84781, 742 | 1.29809 743 | ], 744 | [ 745 | 103.84766, 746 | 1.29818 747 | ], 748 | [ 749 | 103.84757, 750 | 1.29824 751 | ], 752 | [ 753 | 103.84755, 754 | 1.29824 755 | ], 756 | [ 757 | 103.84755, 758 | 1.29827 759 | ], 760 | [ 761 | 103.84756, 762 | 1.29837 763 | ], 764 | [ 765 | 103.84756, 766 | 1.29839 767 | ], 768 | [ 769 | 103.84754, 770 | 1.29838 771 | ], 772 | [ 773 | 103.84739, 774 | 1.29838 775 | ], 776 | [ 777 | 103.84735, 778 | 1.29837 779 | ], 780 | [ 781 | 103.84732, 782 | 1.29837 783 | ], 784 | [ 785 | 103.84728, 786 | 1.29835 787 | ], 788 | [ 789 | 103.84724, 790 | 1.29833 791 | ], 792 | [ 793 | 103.84721, 794 | 1.29831 795 | ], 796 | [ 797 | 103.84717, 798 | 1.29829 799 | ], 800 | [ 801 | 103.84715, 802 | 1.29827 803 | ], 804 | [ 805 | 103.84712, 806 | 1.29826 807 | ], 808 | [ 809 | 103.84694, 810 | 1.29827 811 | ], 812 | [ 813 | 103.84688, 814 | 1.29824 815 | ], 816 | [ 817 | 103.84683, 818 | 1.29824 819 | ], 820 | [ 821 | 103.84668, 822 | 1.29828 823 | ], 824 | [ 825 | 103.84646, 826 | 1.29836 827 | ], 828 | [ 829 | 103.84641, 830 | 1.29838 831 | ], 832 | [ 833 | 103.84637, 834 | 1.29839 835 | ], 836 | [ 837 | 103.84638, 838 | 1.2984 839 | ], 840 | [ 841 | 103.84621, 842 | 1.29846 843 | ], 844 | [ 845 | 103.84625, 846 | 1.29861 847 | ], 848 | [ 849 | 103.84676, 850 | 1.29844 851 | ], 852 | [ 853 | 103.846788, 854 | 1.298445 855 | ] 856 | ] 857 | } 858 | }, 859 | { 860 | "type": "Feature", 861 | "properties": { 862 | "duration_min": 7, 863 | "station_codes_1": "DT21", 864 | "station_codes_2": "NS24-NE6-CC1", 865 | "exit_name_1": "C", 866 | "exit_name_2": "A" 867 | }, 868 | "geometry": { 869 | "type": "Point", 870 | "coordinates": [ 871 | 103.84759096506014, 872 | 1.2982260232937965 873 | ] 874 | } 875 | }, 876 | { 877 | "type": "Feature", 878 | "properties": {}, 879 | "geometry": { 880 | "type": "LineString", 881 | "coordinates": [ 882 | [ 883 | 103.850843, 884 | 1.299195 885 | ], 886 | [ 887 | 103.8508, 888 | 1.29923 889 | ], 890 | [ 891 | 103.85084, 892 | 1.29928 893 | ], 894 | [ 895 | 103.85087, 896 | 1.29932 897 | ], 898 | [ 899 | 103.85096, 900 | 1.29943 901 | ], 902 | [ 903 | 103.85097, 904 | 1.29944 905 | ], 906 | [ 907 | 103.85103, 908 | 1.29951 909 | ], 910 | [ 911 | 103.85139, 912 | 1.29995 913 | ], 914 | [ 915 | 103.85147, 916 | 1.30005 917 | ], 918 | [ 919 | 103.85166, 920 | 1.30027 921 | ], 922 | [ 923 | 103.85163, 924 | 1.3003 925 | ], 926 | [ 927 | 103.85156, 928 | 1.30031 929 | ], 930 | [ 931 | 103.8515, 932 | 1.30036 933 | ], 934 | [ 935 | 103.85145, 936 | 1.30041 937 | ], 938 | [ 939 | 103.85144, 940 | 1.30043 941 | ], 942 | [ 943 | 103.85143, 944 | 1.30044 945 | ], 946 | [ 947 | 103.8513, 948 | 1.30051 949 | ], 950 | [ 951 | 103.85113, 952 | 1.30063 953 | ], 954 | [ 955 | 103.85102, 956 | 1.30069 957 | ], 958 | [ 959 | 103.8508, 960 | 1.30085 961 | ], 962 | [ 963 | 103.85079, 964 | 1.30088 965 | ], 966 | [ 967 | 103.8508, 968 | 1.3009 969 | ], 970 | [ 971 | 103.85093, 972 | 1.30106 973 | ], 974 | [ 975 | 103.85096, 976 | 1.30109 977 | ], 978 | [ 979 | 103.85094, 980 | 1.30111 981 | ], 982 | [ 983 | 103.85094, 984 | 1.30112 985 | ], 986 | [ 987 | 103.85083, 988 | 1.30121 989 | ], 990 | [ 991 | 103.85082, 992 | 1.30122 993 | ], 994 | [ 995 | 103.85085, 996 | 1.30125 997 | ], 998 | [ 999 | 103.85111, 1000 | 1.30155 1001 | ], 1002 | [ 1003 | 103.85115, 1004 | 1.30161 1005 | ], 1006 | [ 1007 | 103.85124, 1008 | 1.30171 1009 | ], 1010 | [ 1011 | 103.85128, 1012 | 1.30177 1013 | ], 1014 | [ 1015 | 103.8515, 1016 | 1.30205 1017 | ], 1018 | [ 1019 | 103.85149, 1020 | 1.30212 1021 | ], 1022 | [ 1023 | 103.85091, 1024 | 1.30261 1025 | ], 1026 | [ 1027 | 103.85085, 1028 | 1.3026 1029 | ], 1030 | [ 1031 | 103.85089, 1032 | 1.30264 1033 | ], 1034 | [ 1035 | 103.85095, 1036 | 1.30271 1037 | ], 1038 | [ 1039 | 103.85119, 1040 | 1.30301 1041 | ], 1042 | [ 1043 | 103.85122, 1044 | 1.30303 1045 | ], 1046 | [ 1047 | 103.85125, 1048 | 1.30308 1049 | ], 1050 | [ 1051 | 103.85136, 1052 | 1.30321 1053 | ], 1054 | [ 1055 | 103.85154, 1056 | 1.30342 1057 | ], 1058 | [ 1059 | 103.85157, 1060 | 1.30343 1061 | ], 1062 | [ 1063 | 103.85158, 1064 | 1.30341 1065 | ], 1066 | [ 1067 | 103.85197, 1068 | 1.30312 1069 | ], 1070 | [ 1071 | 103.85222, 1072 | 1.30294 1073 | ], 1074 | [ 1075 | 103.85256, 1076 | 1.30337 1077 | ], 1078 | [ 1079 | 103.85249, 1080 | 1.30343 1081 | ], 1082 | [ 1083 | 103.852375, 1084 | 1.303404 1085 | ] 1086 | ] 1087 | } 1088 | }, 1089 | { 1090 | "type": "Feature", 1091 | "properties": { 1092 | "duration_min": 10, 1093 | "station_codes_1": "DT21", 1094 | "station_codes_2": "DT13", 1095 | "exit_name_1": "A", 1096 | "exit_name_2": "A" 1097 | }, 1098 | "geometry": { 1099 | "type": "Point", 1100 | "coordinates": [ 1101 | 103.8512980191138, 1102 | 1.3017929334206095 1103 | ] 1104 | } 1105 | }, 1106 | { 1107 | "type": "Feature", 1108 | "properties": {}, 1109 | "geometry": { 1110 | "type": "LineString", 1111 | "coordinates": [ 1112 | [ 1113 | 103.863074, 1114 | 1.313853 1115 | ], 1116 | [ 1117 | 103.86308, 1118 | 1.31385 1119 | ], 1120 | [ 1121 | 103.86338, 1122 | 1.31422 1123 | ], 1124 | [ 1125 | 103.86345, 1126 | 1.3143 1127 | ], 1128 | [ 1129 | 103.86348, 1130 | 1.31435 1131 | ], 1132 | [ 1133 | 103.8635, 1134 | 1.31437 1135 | ], 1136 | [ 1137 | 103.8635, 1138 | 1.3144 1139 | ], 1140 | [ 1141 | 103.86349, 1142 | 1.31442 1143 | ], 1144 | [ 1145 | 103.8636, 1146 | 1.31453 1147 | ], 1148 | [ 1149 | 103.86363, 1150 | 1.31454 1151 | ], 1152 | [ 1153 | 103.86366, 1154 | 1.31457 1155 | ], 1156 | [ 1157 | 103.86377, 1158 | 1.31472 1159 | ], 1160 | [ 1161 | 103.86381, 1162 | 1.31477 1163 | ], 1164 | [ 1165 | 103.86387, 1166 | 1.31485 1167 | ], 1168 | [ 1169 | 103.86424, 1170 | 1.31532 1171 | ], 1172 | [ 1173 | 103.86423, 1174 | 1.31537 1175 | ], 1176 | [ 1177 | 103.8642, 1178 | 1.31545 1179 | ], 1180 | [ 1181 | 103.86391, 1182 | 1.31569 1183 | ], 1184 | [ 1185 | 103.86387, 1186 | 1.31571 1187 | ], 1188 | [ 1189 | 103.86381, 1190 | 1.31576 1191 | ], 1192 | [ 1193 | 103.86374, 1194 | 1.31582 1195 | ], 1196 | [ 1197 | 103.86343, 1198 | 1.31606 1199 | ], 1200 | [ 1201 | 103.86337, 1202 | 1.3161 1203 | ], 1204 | [ 1205 | 103.86326, 1206 | 1.31619 1207 | ], 1208 | [ 1209 | 103.8632, 1210 | 1.31625 1211 | ], 1212 | [ 1213 | 103.86318, 1214 | 1.31627 1215 | ], 1216 | [ 1217 | 103.86312, 1218 | 1.31631 1219 | ], 1220 | [ 1221 | 103.86303, 1222 | 1.31638 1223 | ], 1224 | [ 1225 | 103.863, 1226 | 1.31638 1227 | ], 1228 | [ 1229 | 103.8627, 1230 | 1.31662 1231 | ], 1232 | [ 1233 | 103.86267, 1234 | 1.31664 1235 | ], 1236 | [ 1237 | 103.86264, 1238 | 1.31665 1239 | ], 1240 | [ 1241 | 103.86258, 1242 | 1.31665 1243 | ], 1244 | [ 1245 | 103.86258, 1246 | 1.31671 1247 | ], 1248 | [ 1249 | 103.86253, 1250 | 1.31673 1251 | ], 1252 | [ 1253 | 103.86242, 1254 | 1.31681 1255 | ], 1256 | [ 1257 | 103.86234, 1258 | 1.31687 1259 | ], 1260 | [ 1261 | 103.86233, 1262 | 1.31686 1263 | ], 1264 | [ 1265 | 103.8623, 1266 | 1.31689 1267 | ], 1268 | [ 1269 | 103.86227, 1270 | 1.31692 1271 | ], 1272 | [ 1273 | 103.86202, 1274 | 1.31712 1275 | ], 1276 | [ 1277 | 103.862, 1278 | 1.31713 1279 | ], 1280 | [ 1281 | 103.86195, 1282 | 1.31717 1283 | ], 1284 | [ 1285 | 103.86186, 1286 | 1.31723 1287 | ], 1288 | [ 1289 | 103.86178, 1290 | 1.3173 1291 | ], 1292 | [ 1293 | 103.86163, 1294 | 1.31742 1295 | ], 1296 | [ 1297 | 103.86158, 1298 | 1.31746 1299 | ], 1300 | [ 1301 | 103.86153, 1302 | 1.3175 1303 | ], 1304 | [ 1305 | 103.86143, 1306 | 1.31755 1307 | ], 1308 | [ 1309 | 103.86142, 1310 | 1.31756 1311 | ], 1312 | [ 1313 | 103.8613, 1314 | 1.31765 1315 | ], 1316 | [ 1317 | 103.86125, 1318 | 1.3177 1319 | ], 1320 | [ 1321 | 103.86117, 1322 | 1.31776 1323 | ], 1324 | [ 1325 | 103.86112, 1326 | 1.3178 1327 | ], 1328 | [ 1329 | 103.86106, 1330 | 1.31785 1331 | ], 1332 | [ 1333 | 103.86089, 1334 | 1.31798 1335 | ], 1336 | [ 1337 | 103.86083, 1338 | 1.31803 1339 | ], 1340 | [ 1341 | 103.86081, 1342 | 1.318 1343 | ], 1344 | [ 1345 | 103.86072, 1346 | 1.3179 1347 | ], 1348 | [ 1349 | 103.86071, 1350 | 1.31791 1351 | ], 1352 | [ 1353 | 103.860707, 1354 | 1.317915 1355 | ] 1356 | ] 1357 | } 1358 | }, 1359 | { 1360 | "type": "Feature", 1361 | "properties": { 1362 | "duration_min": 9, 1363 | "station_codes_1": "DT23", 1364 | "station_codes_2": "NE9", 1365 | "exit_name_1": "A", 1366 | "exit_name_2": "C" 1367 | }, 1368 | "geometry": { 1369 | "type": "Point", 1370 | "coordinates": [ 1371 | 103.86324257212416, 1372 | 1.3162074278762554 1373 | ] 1374 | } 1375 | }, 1376 | { 1377 | "type": "Feature", 1378 | "properties": {}, 1379 | "geometry": { 1380 | "type": "LineString", 1381 | "coordinates": [ 1382 | [ 1383 | 103.851327, 1384 | 1.296859 1385 | ], 1386 | [ 1387 | 103.85137, 1388 | 1.29683 1389 | ], 1390 | [ 1391 | 103.85142, 1392 | 1.2969 1393 | ], 1394 | [ 1395 | 103.85144, 1396 | 1.29692 1397 | ], 1398 | [ 1399 | 103.85144, 1400 | 1.29693 1401 | ], 1402 | [ 1403 | 103.85132, 1404 | 1.29703 1405 | ], 1406 | [ 1407 | 103.85135, 1408 | 1.29707 1409 | ], 1410 | [ 1411 | 103.85136, 1412 | 1.29709 1413 | ], 1414 | [ 1415 | 103.8514, 1416 | 1.29715 1417 | ], 1418 | [ 1419 | 103.85143, 1420 | 1.29717 1421 | ], 1422 | [ 1423 | 103.85148, 1424 | 1.29723 1425 | ], 1426 | [ 1427 | 103.85152, 1428 | 1.29728 1429 | ], 1430 | [ 1431 | 103.85161, 1432 | 1.29739 1433 | ], 1434 | [ 1435 | 103.85166, 1436 | 1.29745 1437 | ], 1438 | [ 1439 | 103.85168, 1440 | 1.29748 1441 | ], 1442 | [ 1443 | 103.85181, 1444 | 1.29763 1445 | ], 1446 | [ 1447 | 103.85183, 1448 | 1.29766 1449 | ], 1450 | [ 1451 | 103.85192, 1452 | 1.29776 1453 | ], 1454 | [ 1455 | 103.85196, 1456 | 1.2978 1457 | ], 1458 | [ 1459 | 103.85206, 1460 | 1.29793 1461 | ], 1462 | [ 1463 | 103.85208, 1464 | 1.29796 1465 | ], 1466 | [ 1467 | 103.85222, 1468 | 1.29812 1469 | ], 1470 | [ 1471 | 103.85226, 1472 | 1.29818 1473 | ], 1474 | [ 1475 | 103.85242, 1476 | 1.29836 1477 | ], 1478 | [ 1479 | 103.85248, 1480 | 1.29843 1481 | ], 1482 | [ 1483 | 103.8526, 1484 | 1.29858 1485 | ], 1486 | [ 1487 | 103.85272, 1488 | 1.29873 1489 | ], 1490 | [ 1491 | 103.85283, 1492 | 1.29887 1493 | ], 1494 | [ 1495 | 103.85303, 1496 | 1.29909 1497 | ], 1498 | [ 1499 | 103.85303, 1500 | 1.29912 1501 | ], 1502 | [ 1503 | 103.85304, 1504 | 1.29913 1505 | ], 1506 | [ 1507 | 103.85305, 1508 | 1.29912 1509 | ], 1510 | [ 1511 | 103.85315, 1512 | 1.29904 1513 | ], 1514 | [ 1515 | 103.85317, 1516 | 1.29903 1517 | ], 1518 | [ 1519 | 103.85319, 1520 | 1.29905 1521 | ], 1522 | [ 1523 | 103.85323, 1524 | 1.29902 1525 | ], 1526 | [ 1527 | 103.85324, 1528 | 1.29903 1529 | ], 1530 | [ 1531 | 103.85336, 1532 | 1.29918 1533 | ], 1534 | [ 1535 | 103.85338, 1536 | 1.2992 1537 | ], 1538 | [ 1539 | 103.85394, 1540 | 1.29874 1541 | ], 1542 | [ 1543 | 103.85395, 1544 | 1.29873 1545 | ], 1546 | [ 1547 | 103.85399, 1548 | 1.29871 1549 | ], 1550 | [ 1551 | 103.85401, 1552 | 1.29869 1553 | ], 1554 | [ 1555 | 103.85424, 1556 | 1.2985 1557 | ], 1558 | [ 1559 | 103.85427, 1560 | 1.29849 1561 | ], 1562 | [ 1563 | 103.85429, 1564 | 1.29853 1565 | ], 1566 | [ 1567 | 103.8543, 1568 | 1.29854 1569 | ], 1570 | [ 1571 | 103.85474, 1572 | 1.29904 1573 | ], 1574 | [ 1575 | 103.85478, 1576 | 1.29908 1577 | ], 1578 | [ 1579 | 103.8548, 1580 | 1.29906 1581 | ], 1582 | [ 1583 | 103.85481, 1584 | 1.29908 1585 | ], 1586 | [ 1587 | 103.85493, 1588 | 1.29922 1589 | ], 1590 | [ 1591 | 103.85507, 1592 | 1.29938 1593 | ], 1594 | [ 1595 | 103.85502, 1596 | 1.2994 1597 | ], 1598 | [ 1599 | 103.85502, 1600 | 1.29941 1601 | ], 1602 | [ 1603 | 103.855, 1604 | 1.29942 1605 | ], 1606 | [ 1607 | 103.85506, 1608 | 1.29949 1609 | ], 1610 | [ 1611 | 103.85508, 1612 | 1.29947 1613 | ], 1614 | [ 1615 | 103.85515, 1616 | 1.29955 1617 | ], 1618 | [ 1619 | 103.85537, 1620 | 1.29978 1621 | ], 1622 | [ 1623 | 103.85542, 1624 | 1.29984 1625 | ], 1626 | [ 1627 | 103.85543, 1628 | 1.29985 1629 | ], 1630 | [ 1631 | 103.85548, 1632 | 1.29991 1633 | ], 1634 | [ 1635 | 103.8555, 1636 | 1.29993 1637 | ], 1638 | [ 1639 | 103.85554, 1640 | 1.29991 1641 | ], 1642 | [ 1643 | 103.85559, 1644 | 1.29998 1645 | ], 1646 | [ 1647 | 103.85564, 1648 | 1.30004 1649 | ], 1650 | [ 1651 | 103.855686, 1652 | 1.300007 1653 | ] 1654 | ] 1655 | } 1656 | }, 1657 | { 1658 | "type": "Feature", 1659 | "properties": { 1660 | "duration_min": 10, 1661 | "station_codes_1": "CC2", 1662 | "station_codes_2": "EW12-DT14", 1663 | "exit_name_1": "A", 1664 | "exit_name_2": "C" 1665 | }, 1666 | "geometry": { 1667 | "type": "Point", 1668 | "coordinates": [ 1669 | 103.8533207744962, 1670 | 1.2991309681228072 1671 | ] 1672 | } 1673 | }, 1674 | { 1675 | "type": "Feature", 1676 | "properties": {}, 1677 | "geometry": { 1678 | "type": "LineString", 1679 | "coordinates": [ 1680 | [ 1681 | 103.850474, 1682 | 1.296046 1683 | ], 1684 | [ 1685 | 103.85044, 1686 | 1.29608 1687 | ], 1688 | [ 1689 | 103.8503, 1690 | 1.29592 1691 | ], 1692 | [ 1693 | 103.85029, 1694 | 1.29591 1695 | ], 1696 | [ 1697 | 103.85026, 1698 | 1.29587 1699 | ], 1700 | [ 1701 | 103.85028, 1702 | 1.2958 1703 | ], 1704 | [ 1705 | 103.85028, 1706 | 1.29575 1707 | ], 1708 | [ 1709 | 103.85029, 1710 | 1.29575 1711 | ], 1712 | [ 1713 | 103.85034, 1714 | 1.29571 1715 | ], 1716 | [ 1717 | 103.8504, 1718 | 1.29567 1719 | ], 1720 | [ 1721 | 103.85039, 1722 | 1.29566 1723 | ], 1724 | [ 1725 | 103.85014, 1726 | 1.29531 1727 | ], 1728 | [ 1729 | 103.85002, 1730 | 1.29514 1731 | ], 1732 | [ 1733 | 103.84997, 1734 | 1.29508 1735 | ], 1736 | [ 1737 | 103.84999, 1738 | 1.29503 1739 | ], 1740 | [ 1741 | 103.85027, 1742 | 1.29486 1743 | ], 1744 | [ 1745 | 103.85051, 1746 | 1.29471 1747 | ], 1748 | [ 1749 | 103.85054, 1750 | 1.29468 1751 | ], 1752 | [ 1753 | 103.85056, 1754 | 1.29467 1755 | ], 1756 | [ 1757 | 103.85079, 1758 | 1.29451 1759 | ], 1760 | [ 1761 | 103.85069, 1762 | 1.29436 1763 | ], 1764 | [ 1765 | 103.85069, 1766 | 1.29435 1767 | ], 1768 | [ 1769 | 103.85122, 1770 | 1.29402 1771 | ], 1772 | [ 1773 | 103.85128, 1774 | 1.29398 1775 | ], 1776 | [ 1777 | 103.85133, 1778 | 1.29395 1779 | ], 1780 | [ 1781 | 103.85141, 1782 | 1.2939 1783 | ], 1784 | [ 1785 | 103.85179, 1786 | 1.29365 1787 | ], 1788 | [ 1789 | 103.85181, 1790 | 1.29364 1791 | ], 1792 | [ 1793 | 103.85187, 1794 | 1.29356 1795 | ], 1796 | [ 1797 | 103.85187, 1798 | 1.29354 1799 | ], 1800 | [ 1801 | 103.85186, 1802 | 1.2935 1803 | ], 1804 | [ 1805 | 103.85184, 1806 | 1.29345 1807 | ], 1808 | [ 1809 | 103.85183, 1810 | 1.29344 1811 | ], 1812 | [ 1813 | 103.85181, 1814 | 1.29345 1815 | ], 1816 | [ 1817 | 103.8518, 1818 | 1.29346 1819 | ], 1820 | [ 1821 | 103.851802, 1822 | 1.293455 1823 | ] 1824 | ] 1825 | } 1826 | }, 1827 | { 1828 | "type": "Feature", 1829 | "properties": { 1830 | "duration_min": 6, 1831 | "station_codes_1": "CC2", 1832 | "station_codes_2": "NS25-EW13", 1833 | "exit_name_1": "B", 1834 | "exit_name_2": "D" 1835 | }, 1836 | "geometry": { 1837 | "type": "Point", 1838 | "coordinates": [ 1839 | 103.85054145705546, 1840 | 1.294679271472282 1841 | ] 1842 | } 1843 | }, 1844 | { 1845 | "type": "Feature", 1846 | "properties": {}, 1847 | "geometry": { 1848 | "type": "LineString", 1849 | "coordinates": [ 1850 | [ 1851 | 103.855924, 1852 | 1.301204 1853 | ], 1854 | [ 1855 | 103.85603, 1856 | 1.30111 1857 | ], 1858 | [ 1859 | 103.8561, 1860 | 1.30119 1861 | ], 1862 | [ 1863 | 103.85618, 1864 | 1.30129 1865 | ], 1866 | [ 1867 | 103.85617, 1868 | 1.30132 1869 | ], 1870 | [ 1871 | 103.85614, 1872 | 1.30135 1873 | ], 1874 | [ 1875 | 103.85612, 1876 | 1.30137 1877 | ], 1878 | [ 1879 | 103.85606, 1880 | 1.30143 1881 | ], 1882 | [ 1883 | 103.85595, 1884 | 1.30154 1885 | ], 1886 | [ 1887 | 103.85591, 1888 | 1.30158 1889 | ], 1890 | [ 1891 | 103.85585, 1892 | 1.30163 1893 | ], 1894 | [ 1895 | 103.85575, 1896 | 1.30173 1897 | ], 1898 | [ 1899 | 103.85568, 1900 | 1.30181 1901 | ], 1902 | [ 1903 | 103.85558, 1904 | 1.30191 1905 | ], 1906 | [ 1907 | 103.85565, 1908 | 1.30198 1909 | ], 1910 | [ 1911 | 103.8557, 1912 | 1.30204 1913 | ], 1914 | [ 1915 | 103.85606, 1916 | 1.30246 1917 | ], 1918 | [ 1919 | 103.85607, 1920 | 1.30248 1921 | ], 1922 | [ 1923 | 103.85608, 1924 | 1.30249 1925 | ], 1926 | [ 1927 | 103.85619, 1928 | 1.30262 1929 | ], 1930 | [ 1931 | 103.8562, 1932 | 1.30264 1933 | ], 1934 | [ 1935 | 103.85618, 1936 | 1.30264 1937 | ], 1938 | [ 1939 | 103.85607, 1940 | 1.30273 1941 | ], 1942 | [ 1943 | 103.85594, 1944 | 1.30284 1945 | ], 1946 | [ 1947 | 103.85591, 1948 | 1.30286 1949 | ], 1950 | [ 1951 | 103.85577, 1952 | 1.30299 1953 | ], 1954 | [ 1955 | 103.85572, 1956 | 1.30302 1957 | ], 1958 | [ 1959 | 103.85568, 1960 | 1.30305 1961 | ], 1962 | [ 1963 | 103.85558, 1964 | 1.30312 1965 | ], 1966 | [ 1967 | 103.85549, 1968 | 1.30319 1969 | ], 1970 | [ 1971 | 103.85545, 1972 | 1.30322 1973 | ], 1974 | [ 1975 | 103.85542, 1976 | 1.30323 1977 | ], 1978 | [ 1979 | 103.85539, 1980 | 1.30325 1981 | ], 1982 | [ 1983 | 103.85534, 1984 | 1.30326 1985 | ], 1986 | [ 1987 | 103.8553, 1988 | 1.30327 1989 | ], 1990 | [ 1991 | 103.85526, 1992 | 1.30328 1993 | ], 1994 | [ 1995 | 103.85522, 1996 | 1.30328 1997 | ], 1998 | [ 1999 | 103.85522, 2000 | 1.30329 2001 | ], 2002 | [ 2003 | 103.8552, 2004 | 1.30335 2005 | ], 2006 | [ 2007 | 103.85519, 2008 | 1.30335 2009 | ], 2010 | [ 2011 | 103.85516, 2012 | 1.30334 2013 | ], 2014 | [ 2015 | 103.855, 2016 | 1.30328 2017 | ], 2018 | [ 2019 | 103.85496, 2020 | 1.30327 2021 | ], 2022 | [ 2023 | 103.85488, 2024 | 1.3035 2025 | ], 2026 | [ 2027 | 103.85487, 2028 | 1.30353 2029 | ], 2030 | [ 2031 | 103.85486, 2032 | 1.30358 2033 | ], 2034 | [ 2035 | 103.85485, 2036 | 1.30359 2037 | ], 2038 | [ 2039 | 103.85497, 2040 | 1.30364 2041 | ], 2042 | [ 2043 | 103.85506, 2044 | 1.30367 2045 | ], 2046 | [ 2047 | 103.85478, 2048 | 1.30429 2049 | ], 2050 | [ 2051 | 103.85475, 2052 | 1.30437 2053 | ], 2054 | [ 2055 | 103.85481, 2056 | 1.30447 2057 | ], 2058 | [ 2059 | 103.85486, 2060 | 1.3045 2061 | ], 2062 | [ 2063 | 103.8549, 2064 | 1.30447 2065 | ], 2066 | [ 2067 | 103.8552, 2068 | 1.30495 2069 | ], 2070 | [ 2071 | 103.855296, 2072 | 1.30489 2073 | ] 2074 | ] 2075 | } 2076 | }, 2077 | { 2078 | "type": "Feature", 2079 | "properties": { 2080 | "duration_min": 8, 2081 | "station_codes_1": "EW12-DT14", 2082 | "station_codes_2": "DT22", 2083 | "exit_name_1": "A", 2084 | "exit_name_2": "A" 2085 | }, 2086 | "geometry": { 2087 | "type": "Point", 2088 | "coordinates": [ 2089 | 103.8557057232213, 2090 | 1.3030307075841723 2091 | ] 2092 | } 2093 | }, 2094 | { 2095 | "type": "Feature", 2096 | "properties": {}, 2097 | "geometry": { 2098 | "type": "LineString", 2099 | "coordinates": [ 2100 | [ 2101 | 103.843798, 2102 | 1.283713 2103 | ], 2104 | [ 2105 | 103.8438, 2106 | 1.28371 2107 | ], 2108 | [ 2109 | 103.8444, 2110 | 1.28336 2111 | ], 2112 | [ 2113 | 103.84437, 2114 | 1.28331 2115 | ], 2116 | [ 2117 | 103.84441, 2118 | 1.28329 2119 | ], 2120 | [ 2121 | 103.84441, 2122 | 1.28328 2123 | ], 2124 | [ 2125 | 103.8444, 2126 | 1.28327 2127 | ], 2128 | [ 2129 | 103.84431, 2130 | 1.2831 2131 | ], 2132 | [ 2133 | 103.84424, 2134 | 1.28298 2135 | ], 2136 | [ 2137 | 103.84421, 2138 | 1.28293 2139 | ], 2140 | [ 2141 | 103.84421, 2142 | 1.28291 2143 | ], 2144 | [ 2145 | 103.84422, 2146 | 1.2829 2147 | ], 2148 | [ 2149 | 103.84414, 2150 | 1.28281 2151 | ], 2152 | [ 2153 | 103.84414, 2154 | 1.2828 2155 | ], 2156 | [ 2157 | 103.84398, 2158 | 1.28251 2159 | ], 2160 | [ 2161 | 103.84397, 2162 | 1.28249 2163 | ], 2164 | [ 2165 | 103.84397, 2166 | 1.28248 2167 | ], 2168 | [ 2169 | 103.84402, 2170 | 1.28245 2171 | ], 2172 | [ 2173 | 103.84403, 2174 | 1.28245 2175 | ], 2176 | [ 2177 | 103.84413, 2178 | 1.28239 2179 | ], 2180 | [ 2181 | 103.8442, 2182 | 1.28235 2183 | ], 2184 | [ 2185 | 103.84422, 2186 | 1.28234 2187 | ], 2188 | [ 2189 | 103.84424, 2190 | 1.28233 2191 | ], 2192 | [ 2193 | 103.84425, 2194 | 1.28233 2195 | ], 2196 | [ 2197 | 103.84427, 2198 | 1.28232 2199 | ], 2200 | [ 2201 | 103.84439, 2202 | 1.28224 2203 | ], 2204 | [ 2205 | 103.84457, 2206 | 1.28214 2207 | ], 2208 | [ 2209 | 103.84462, 2210 | 1.28211 2211 | ], 2212 | [ 2213 | 103.84475, 2214 | 1.28204 2215 | ], 2216 | [ 2217 | 103.84477, 2218 | 1.28203 2219 | ], 2220 | [ 2221 | 103.84474, 2222 | 1.28198 2223 | ], 2224 | [ 2225 | 103.84472, 2226 | 1.28193 2227 | ], 2228 | [ 2229 | 103.8447, 2230 | 1.28191 2231 | ], 2232 | [ 2233 | 103.84462, 2234 | 1.28178 2235 | ], 2236 | [ 2237 | 103.84452, 2238 | 1.28161 2239 | ], 2240 | [ 2241 | 103.84454, 2242 | 1.2816 2243 | ], 2244 | [ 2245 | 103.84457, 2246 | 1.28159 2247 | ], 2248 | [ 2249 | 103.84472, 2250 | 1.28151 2251 | ], 2252 | [ 2253 | 103.8447, 2254 | 1.28147 2255 | ], 2256 | [ 2257 | 103.84467, 2258 | 1.28142 2259 | ], 2260 | [ 2261 | 103.84467, 2262 | 1.2814 2263 | ], 2264 | [ 2265 | 103.84479, 2266 | 1.28132 2267 | ], 2268 | [ 2269 | 103.84478, 2270 | 1.28131 2271 | ], 2272 | [ 2273 | 103.84482, 2274 | 1.28117 2275 | ], 2276 | [ 2277 | 103.84473, 2278 | 1.28103 2279 | ], 2280 | [ 2281 | 103.844895, 2282 | 1.280919 2283 | ] 2284 | ] 2285 | } 2286 | }, 2287 | { 2288 | "type": "Feature", 2289 | "properties": { 2290 | "duration_min": 6, 2291 | "station_codes_1": "NE4-DT19", 2292 | "station_codes_2": "TE18", 2293 | "exit_name_1": "A", 2294 | "exit_name_2": "2" 2295 | }, 2296 | "geometry": { 2297 | "type": "Point", 2298 | "coordinates": [ 2299 | 103.84416621632215, 2300 | 1.2823693049591678 2301 | ] 2302 | } 2303 | }, 2304 | { 2305 | "type": "Feature", 2306 | "properties": {}, 2307 | "geometry": { 2308 | "type": "LineString", 2309 | "coordinates": [ 2310 | [ 2311 | 103.85298, 2312 | 1.293042 2313 | ], 2314 | [ 2315 | 103.85301, 2316 | 1.29309 2317 | ], 2318 | [ 2319 | 103.85332, 2320 | 1.29288 2321 | ], 2322 | [ 2323 | 103.85339, 2324 | 1.29286 2325 | ], 2326 | [ 2327 | 103.85342, 2328 | 1.29287 2329 | ], 2330 | [ 2331 | 103.85344, 2332 | 1.29288 2333 | ], 2334 | [ 2335 | 103.85346, 2336 | 1.29291 2337 | ], 2338 | [ 2339 | 103.85349, 2340 | 1.2929 2341 | ], 2342 | [ 2343 | 103.85357, 2344 | 1.29285 2345 | ], 2346 | [ 2347 | 103.85367, 2348 | 1.29279 2349 | ], 2350 | [ 2351 | 103.85376, 2352 | 1.29273 2353 | ], 2354 | [ 2355 | 103.85379, 2356 | 1.29271 2357 | ], 2358 | [ 2359 | 103.85384, 2360 | 1.29259 2361 | ], 2362 | [ 2363 | 103.85385, 2364 | 1.29257 2365 | ], 2366 | [ 2367 | 103.85395, 2368 | 1.29257 2369 | ], 2370 | [ 2371 | 103.85398, 2372 | 1.29259 2373 | ], 2374 | [ 2375 | 103.85408, 2376 | 1.29269 2377 | ], 2378 | [ 2379 | 103.85411, 2380 | 1.29271 2381 | ], 2382 | [ 2383 | 103.8542, 2384 | 1.29285 2385 | ], 2386 | [ 2387 | 103.85428, 2388 | 1.293 2389 | ], 2390 | [ 2391 | 103.85435, 2392 | 1.29311 2393 | ], 2394 | [ 2395 | 103.85443, 2396 | 1.29323 2397 | ], 2398 | [ 2399 | 103.85457, 2400 | 1.29346 2401 | ], 2402 | [ 2403 | 103.85466, 2404 | 1.29361 2405 | ], 2406 | [ 2407 | 103.85468, 2408 | 1.29363 2409 | ], 2410 | [ 2411 | 103.8547, 2412 | 1.29364 2413 | ], 2414 | [ 2415 | 103.85476, 2416 | 1.29364 2417 | ], 2418 | [ 2419 | 103.85477, 2420 | 1.29363 2421 | ], 2422 | [ 2423 | 103.8549, 2424 | 1.29355 2425 | ], 2426 | [ 2427 | 103.85492, 2428 | 1.293586 2429 | ] 2430 | ] 2431 | } 2432 | }, 2433 | { 2434 | "type": "Feature", 2435 | "properties": { 2436 | "duration_min": 4, 2437 | "station_codes_1": "NS25-EW13", 2438 | "station_codes_2": "CC3", 2439 | "exit_name_1": "C", 2440 | "exit_name_2": "G" 2441 | }, 2442 | "geometry": { 2443 | "type": "Point", 2444 | "coordinates": [ 2445 | 103.85404300257265, 2446 | 1.292653002574012 2447 | ] 2448 | } 2449 | }, 2450 | { 2451 | "type": "Feature", 2452 | "properties": {}, 2453 | "geometry": { 2454 | "type": "LineString", 2455 | "coordinates": [ 2456 | [ 2457 | 103.846666, 2458 | 1.289384 2459 | ], 2460 | [ 2461 | 103.84667, 2462 | 1.28939 2463 | ], 2464 | [ 2465 | 103.84666, 2466 | 1.28941 2467 | ], 2468 | [ 2469 | 103.84666, 2470 | 1.28942 2471 | ], 2472 | [ 2473 | 103.84659, 2474 | 1.28938 2475 | ], 2476 | [ 2477 | 103.84654, 2478 | 1.28936 2479 | ], 2480 | [ 2481 | 103.84623, 2482 | 1.28921 2483 | ], 2484 | [ 2485 | 103.84608, 2486 | 1.28914 2487 | ], 2488 | [ 2489 | 103.84583, 2490 | 1.28903 2491 | ], 2492 | [ 2493 | 103.84582, 2494 | 1.28905 2495 | ], 2496 | [ 2497 | 103.8458, 2498 | 1.28904 2499 | ], 2500 | [ 2501 | 103.8457, 2502 | 1.28909 2503 | ], 2504 | [ 2505 | 103.84558, 2506 | 1.28908 2507 | ], 2508 | [ 2509 | 103.84543, 2510 | 1.28905 2511 | ], 2512 | [ 2513 | 103.84532, 2514 | 1.289 2515 | ], 2516 | [ 2517 | 103.84524, 2518 | 1.28894 2519 | ], 2520 | [ 2521 | 103.84522, 2522 | 1.28892 2523 | ], 2524 | [ 2525 | 103.84518, 2526 | 1.2889 2527 | ], 2528 | [ 2529 | 103.84513, 2530 | 1.28885 2531 | ], 2532 | [ 2533 | 103.84505, 2534 | 1.2889 2535 | ], 2536 | [ 2537 | 103.84512, 2538 | 1.28943 2539 | ], 2540 | [ 2541 | 103.84508, 2542 | 1.28947 2543 | ], 2544 | [ 2545 | 103.84513, 2546 | 1.2895 2547 | ], 2548 | [ 2549 | 103.84503, 2550 | 1.28954 2551 | ], 2552 | [ 2553 | 103.84492, 2554 | 1.28963 2555 | ], 2556 | [ 2557 | 103.84482, 2558 | 1.28994 2559 | ], 2560 | [ 2561 | 103.84479, 2562 | 1.29015 2563 | ], 2564 | [ 2565 | 103.84477, 2566 | 1.29032 2567 | ], 2568 | [ 2569 | 103.84476, 2570 | 1.29054 2571 | ], 2572 | [ 2573 | 103.84469, 2574 | 1.29059 2575 | ], 2576 | [ 2577 | 103.8447, 2578 | 1.29067 2579 | ], 2580 | [ 2581 | 103.84435, 2582 | 1.29096 2583 | ], 2584 | [ 2585 | 103.8442, 2586 | 1.29108 2587 | ], 2588 | [ 2589 | 103.84421, 2590 | 1.29109 2591 | ], 2592 | [ 2593 | 103.84416, 2594 | 1.29113 2595 | ], 2596 | [ 2597 | 103.8441, 2598 | 1.29117 2599 | ], 2600 | [ 2601 | 103.84409, 2602 | 1.29116 2603 | ], 2604 | [ 2605 | 103.84391, 2606 | 1.29129 2607 | ], 2608 | [ 2609 | 103.84382, 2610 | 1.29134 2611 | ], 2612 | [ 2613 | 103.84415, 2614 | 1.2919 2615 | ], 2616 | [ 2617 | 103.844, 2618 | 1.29199 2619 | ], 2620 | [ 2621 | 103.84404, 2622 | 1.29206 2623 | ], 2624 | [ 2625 | 103.84414, 2626 | 1.29222 2627 | ], 2628 | [ 2629 | 103.84413, 2630 | 1.29223 2631 | ], 2632 | [ 2633 | 103.84406, 2634 | 1.29212 2635 | ], 2636 | [ 2637 | 103.844, 2638 | 1.29216 2639 | ], 2640 | [ 2641 | 103.84414, 2642 | 1.29239 2643 | ], 2644 | [ 2645 | 103.84415, 2646 | 1.2924 2647 | ], 2648 | [ 2649 | 103.84417, 2650 | 1.292406 2651 | ] 2652 | ] 2653 | } 2654 | }, 2655 | { 2656 | "type": "Feature", 2657 | "properties": { 2658 | "duration_min": 9, 2659 | "station_codes_1": "NE5", 2660 | "station_codes_2": "DT20", 2661 | "exit_name_1": "C", 2662 | "exit_name_2": "A" 2663 | }, 2664 | "geometry": { 2665 | "type": "Point", 2666 | "coordinates": [ 2667 | 103.84479192162907, 2668 | 1.2901365485976124 2669 | ] 2670 | } 2671 | }, 2672 | { 2673 | "type": "Feature", 2674 | "properties": {}, 2675 | "geometry": { 2676 | "type": "LineString", 2677 | "coordinates": [ 2678 | [ 2679 | 103.846065, 2680 | 1.286899 2681 | ], 2682 | [ 2683 | 103.84612, 2684 | 1.28687 2685 | ], 2686 | [ 2687 | 103.8461, 2688 | 1.28685 2689 | ], 2690 | [ 2691 | 103.84618, 2692 | 1.28679 2693 | ], 2694 | [ 2695 | 103.84619, 2696 | 1.28678 2697 | ], 2698 | [ 2699 | 103.8462, 2700 | 1.28677 2701 | ], 2702 | [ 2703 | 103.84624, 2704 | 1.2868 2705 | ], 2706 | [ 2707 | 103.84637, 2708 | 1.28684 2709 | ], 2710 | [ 2711 | 103.84645, 2712 | 1.28684 2713 | ], 2714 | [ 2715 | 103.84647, 2716 | 1.28683 2717 | ], 2718 | [ 2719 | 103.84651, 2720 | 1.28682 2721 | ], 2722 | [ 2723 | 103.84657, 2724 | 1.28679 2725 | ], 2726 | [ 2727 | 103.84667, 2728 | 1.28675 2729 | ], 2730 | [ 2731 | 103.84672, 2732 | 1.28673 2733 | ], 2734 | [ 2735 | 103.84686, 2736 | 1.28666 2737 | ], 2738 | [ 2739 | 103.84687, 2740 | 1.28665 2741 | ], 2742 | [ 2743 | 103.84695, 2744 | 1.28665 2745 | ], 2746 | [ 2747 | 103.847, 2748 | 1.28671 2749 | ], 2750 | [ 2751 | 103.84703, 2752 | 1.28669 2753 | ], 2754 | [ 2755 | 103.84726, 2756 | 1.28658 2757 | ], 2758 | [ 2759 | 103.84734, 2760 | 1.28655 2761 | ], 2762 | [ 2763 | 103.84745, 2764 | 1.28649 2765 | ], 2766 | [ 2767 | 103.84758, 2768 | 1.28643 2769 | ], 2770 | [ 2771 | 103.8476, 2772 | 1.28642 2773 | ], 2774 | [ 2775 | 103.84761, 2776 | 1.2864 2777 | ], 2778 | [ 2779 | 103.84761, 2780 | 1.28639 2781 | ], 2782 | [ 2783 | 103.84764, 2784 | 1.28636 2785 | ], 2786 | [ 2787 | 103.84778, 2788 | 1.2863 2789 | ], 2790 | [ 2791 | 103.84779, 2792 | 1.28626 2793 | ], 2794 | [ 2795 | 103.84783, 2796 | 1.28626 2797 | ], 2798 | [ 2799 | 103.84793, 2800 | 1.28622 2801 | ], 2802 | [ 2803 | 103.84821, 2804 | 1.2861 2805 | ], 2806 | [ 2807 | 103.84823, 2808 | 1.28607 2809 | ], 2810 | [ 2811 | 103.84824, 2812 | 1.28606 2813 | ], 2814 | [ 2815 | 103.84821, 2816 | 1.286 2817 | ], 2818 | [ 2819 | 103.8482, 2820 | 1.28599 2821 | ], 2822 | [ 2823 | 103.84823, 2824 | 1.28598 2825 | ], 2826 | [ 2827 | 103.84829, 2828 | 1.28595 2829 | ], 2830 | [ 2831 | 103.84831, 2832 | 1.28594 2833 | ], 2834 | [ 2835 | 103.84831, 2836 | 1.28595 2837 | ], 2838 | [ 2839 | 103.84832, 2840 | 1.28595 2841 | ], 2842 | [ 2843 | 103.84861, 2844 | 1.28581 2845 | ], 2846 | [ 2847 | 103.84868, 2848 | 1.28578 2849 | ], 2850 | [ 2851 | 103.8487, 2852 | 1.28578 2853 | ], 2854 | [ 2855 | 103.8487, 2856 | 1.28577 2857 | ], 2858 | [ 2859 | 103.84871, 2860 | 1.28577 2861 | ], 2862 | [ 2863 | 103.84871, 2864 | 1.28576 2865 | ], 2866 | [ 2867 | 103.84872, 2868 | 1.28576 2869 | ], 2870 | [ 2871 | 103.84872, 2872 | 1.28574 2873 | ], 2874 | [ 2875 | 103.84873, 2876 | 1.28574 2877 | ], 2878 | [ 2879 | 103.84873, 2880 | 1.28572 2881 | ], 2882 | [ 2883 | 103.84872, 2884 | 1.28571 2885 | ], 2886 | [ 2887 | 103.84872, 2888 | 1.2857 2889 | ], 2890 | [ 2891 | 103.84879, 2892 | 1.2857 2893 | ], 2894 | [ 2895 | 103.84886, 2896 | 1.28569 2897 | ], 2898 | [ 2899 | 103.84889, 2900 | 1.28567 2901 | ], 2902 | [ 2903 | 103.8489, 2904 | 1.2857 2905 | ], 2906 | [ 2907 | 103.84892, 2908 | 1.28569 2909 | ], 2910 | [ 2911 | 103.84919, 2912 | 1.28551 2913 | ], 2914 | [ 2915 | 103.84922, 2916 | 1.2855 2917 | ], 2918 | [ 2919 | 103.84937, 2920 | 1.28542 2921 | ], 2922 | [ 2923 | 103.84952, 2924 | 1.28535 2925 | ], 2926 | [ 2927 | 103.84959, 2928 | 1.28534 2929 | ], 2930 | [ 2931 | 103.84985, 2932 | 1.28519 2933 | ], 2934 | [ 2935 | 103.84992, 2936 | 1.28516 2937 | ], 2938 | [ 2939 | 103.84997, 2940 | 1.28513 2941 | ], 2942 | [ 2943 | 103.85001, 2944 | 1.28506 2945 | ], 2946 | [ 2947 | 103.85004, 2948 | 1.28508 2949 | ], 2950 | [ 2951 | 103.85008, 2952 | 1.28507 2953 | ], 2954 | [ 2955 | 103.85012, 2956 | 1.28508 2957 | ], 2958 | [ 2959 | 103.85022, 2960 | 1.28505 2961 | ], 2962 | [ 2963 | 103.85026, 2964 | 1.28502 2965 | ], 2966 | [ 2967 | 103.85032, 2968 | 1.28497 2969 | ], 2970 | [ 2971 | 103.85038, 2972 | 1.285 2973 | ], 2974 | [ 2975 | 103.85049, 2976 | 1.28499 2977 | ], 2978 | [ 2979 | 103.8505, 2980 | 1.28511 2981 | ], 2982 | [ 2983 | 103.8507, 2984 | 1.28509 2985 | ], 2986 | [ 2987 | 103.8508, 2988 | 1.28508 2989 | ], 2990 | [ 2991 | 103.85117, 2992 | 1.28504 2993 | ], 2994 | [ 2995 | 103.85131, 2996 | 1.28503 2997 | ], 2998 | [ 2999 | 103.85135, 3000 | 1.28505 3001 | ], 3002 | [ 3003 | 103.85143, 3004 | 1.28504 3005 | ], 3006 | [ 3007 | 103.85145, 3008 | 1.28508 3009 | ], 3010 | [ 3011 | 103.85148, 3012 | 1.28512 3013 | ], 3014 | [ 3015 | 103.85151, 3016 | 1.28512 3017 | ], 3018 | [ 3019 | 103.85156, 3020 | 1.28515 3021 | ], 3022 | [ 3023 | 103.85161, 3024 | 1.28516 3025 | ], 3026 | [ 3027 | 103.85163, 3028 | 1.28518 3029 | ], 3030 | [ 3031 | 103.85167, 3032 | 1.28528 3033 | ], 3034 | [ 3035 | 103.85164, 3036 | 1.28529 3037 | ], 3038 | [ 3039 | 103.851622, 3040 | 1.285258 3041 | ] 3042 | ] 3043 | } 3044 | }, 3045 | { 3046 | "type": "Feature", 3047 | "properties": { 3048 | "duration_min": 9, 3049 | "station_codes_1": "NE5", 3050 | "station_codes_2": "NS26-EW14", 3051 | "exit_name_1": "A", 3052 | "exit_name_2": "H" 3053 | }, 3054 | "geometry": { 3055 | "type": "Point", 3056 | "coordinates": [ 3057 | 103.8487585921979, 3058 | 1.2857000000002372 3059 | ] 3060 | } 3061 | }, 3062 | { 3063 | "type": "Feature", 3064 | "properties": {}, 3065 | "geometry": { 3066 | "type": "LineString", 3067 | "coordinates": [ 3068 | [ 3069 | 103.846065, 3070 | 1.286899 3071 | ], 3072 | [ 3073 | 103.84612, 3074 | 1.28687 3075 | ], 3076 | [ 3077 | 103.8461, 3078 | 1.28685 3079 | ], 3080 | [ 3081 | 103.84618, 3082 | 1.28679 3083 | ], 3084 | [ 3085 | 103.84619, 3086 | 1.28678 3087 | ], 3088 | [ 3089 | 103.8462, 3090 | 1.28677 3091 | ], 3092 | [ 3093 | 103.84617, 3094 | 1.28674 3095 | ], 3096 | [ 3097 | 103.84616, 3098 | 1.28672 3099 | ], 3100 | [ 3101 | 103.84597, 3102 | 1.28648 3103 | ], 3104 | [ 3105 | 103.84597, 3106 | 1.28647 3107 | ], 3108 | [ 3109 | 103.84592, 3110 | 1.2864 3111 | ], 3112 | [ 3113 | 103.8459, 3114 | 1.28638 3115 | ], 3116 | [ 3117 | 103.84592, 3118 | 1.28637 3119 | ], 3120 | [ 3121 | 103.84599, 3122 | 1.28632 3123 | ], 3124 | [ 3125 | 103.84608, 3126 | 1.28627 3127 | ], 3128 | [ 3129 | 103.84614, 3130 | 1.28624 3131 | ], 3132 | [ 3133 | 103.84618, 3134 | 1.28622 3135 | ], 3136 | [ 3137 | 103.84619, 3138 | 1.28621 3139 | ], 3140 | [ 3141 | 103.84625, 3142 | 1.28618 3143 | ], 3144 | [ 3145 | 103.84626, 3146 | 1.28617 3147 | ], 3148 | [ 3149 | 103.84625, 3150 | 1.28616 3151 | ], 3152 | [ 3153 | 103.84623, 3154 | 1.28612 3155 | ], 3156 | [ 3157 | 103.84629, 3158 | 1.28608 3159 | ], 3160 | [ 3161 | 103.84636, 3162 | 1.28604 3163 | ], 3164 | [ 3165 | 103.84643, 3166 | 1.286 3167 | ], 3168 | [ 3169 | 103.84659, 3170 | 1.2859 3171 | ], 3172 | [ 3173 | 103.84666, 3174 | 1.28587 3175 | ], 3176 | [ 3177 | 103.84673, 3178 | 1.28583 3179 | ], 3180 | [ 3181 | 103.84679, 3182 | 1.28579 3183 | ], 3184 | [ 3185 | 103.84714, 3186 | 1.28559 3187 | ], 3188 | [ 3189 | 103.84717, 3190 | 1.28558 3191 | ], 3192 | [ 3193 | 103.84731, 3194 | 1.2855 3195 | ], 3196 | [ 3197 | 103.8473, 3198 | 1.28548 3199 | ], 3200 | [ 3201 | 103.84723, 3202 | 1.28534 3203 | ], 3204 | [ 3205 | 103.8472, 3206 | 1.28525 3207 | ], 3208 | [ 3209 | 103.84723, 3210 | 1.28526 3211 | ], 3212 | [ 3213 | 103.84745, 3214 | 1.28514 3215 | ], 3216 | [ 3217 | 103.84747, 3218 | 1.28513 3219 | ], 3220 | [ 3221 | 103.84749, 3222 | 1.28512 3223 | ], 3224 | [ 3225 | 103.84752, 3226 | 1.2851 3227 | ], 3228 | [ 3229 | 103.84776, 3230 | 1.28496 3231 | ], 3232 | [ 3233 | 103.84798, 3234 | 1.28484 3235 | ], 3236 | [ 3237 | 103.84802, 3238 | 1.28482 3239 | ], 3240 | [ 3241 | 103.84804, 3242 | 1.28481 3243 | ], 3244 | [ 3245 | 103.84809, 3246 | 1.28478 3247 | ], 3248 | [ 3249 | 103.84825, 3250 | 1.28469 3251 | ], 3252 | [ 3253 | 103.84827, 3254 | 1.28465 3255 | ], 3256 | [ 3257 | 103.84831, 3258 | 1.28464 3259 | ], 3260 | [ 3261 | 103.84833, 3262 | 1.28462 3263 | ], 3264 | [ 3265 | 103.84838, 3266 | 1.2846 3267 | ], 3268 | [ 3269 | 103.8484, 3270 | 1.28458 3271 | ], 3272 | [ 3273 | 103.84843, 3274 | 1.28457 3275 | ], 3276 | [ 3277 | 103.84846, 3278 | 1.28455 3279 | ], 3280 | [ 3281 | 103.84851, 3282 | 1.28457 3283 | ], 3284 | [ 3285 | 103.84867, 3286 | 1.28449 3287 | ], 3288 | [ 3289 | 103.84871, 3290 | 1.28446 3291 | ], 3292 | [ 3293 | 103.84874, 3294 | 1.28444 3295 | ], 3296 | [ 3297 | 103.84896, 3298 | 1.28431 3299 | ], 3300 | [ 3301 | 103.84912, 3302 | 1.28419 3303 | ], 3304 | [ 3305 | 103.84913, 3306 | 1.28418 3307 | ], 3308 | [ 3309 | 103.84923, 3310 | 1.28408 3311 | ], 3312 | [ 3313 | 103.84936, 3314 | 1.28394 3315 | ], 3316 | [ 3317 | 103.84939, 3318 | 1.28393 3319 | ], 3320 | [ 3321 | 103.84947, 3322 | 1.28384 3323 | ], 3324 | [ 3325 | 103.84951, 3326 | 1.28379 3327 | ], 3328 | [ 3329 | 103.84951, 3330 | 1.28378 3331 | ], 3332 | [ 3333 | 103.84953, 3334 | 1.28376 3335 | ], 3336 | [ 3337 | 103.84956, 3338 | 1.28371 3339 | ], 3340 | [ 3341 | 103.84959, 3342 | 1.28367 3343 | ], 3344 | [ 3345 | 103.8496, 3346 | 1.28361 3347 | ], 3348 | [ 3349 | 103.84958, 3350 | 1.28358 3351 | ], 3352 | [ 3353 | 103.84948, 3354 | 1.2835 3355 | ], 3356 | [ 3357 | 103.84945, 3358 | 1.28348 3359 | ], 3360 | [ 3361 | 103.84939, 3362 | 1.28341 3363 | ], 3364 | [ 3365 | 103.84936, 3366 | 1.28339 3367 | ], 3368 | [ 3369 | 103.84935, 3370 | 1.28337 3371 | ], 3372 | [ 3373 | 103.84935, 3374 | 1.28329 3375 | ], 3376 | [ 3377 | 103.84925, 3378 | 1.28317 3379 | ], 3380 | [ 3381 | 103.84921, 3382 | 1.28316 3383 | ], 3384 | [ 3385 | 103.84908, 3386 | 1.28295 3387 | ], 3388 | [ 3389 | 103.84899, 3390 | 1.2828 3391 | ], 3392 | [ 3393 | 103.84894, 3394 | 1.28276 3395 | ], 3396 | [ 3397 | 103.84884, 3398 | 1.28261 3399 | ], 3400 | [ 3401 | 103.84883, 3402 | 1.2826 3403 | ], 3404 | [ 3405 | 103.84877, 3406 | 1.2825 3407 | ], 3408 | [ 3409 | 103.848773, 3410 | 1.282497 3411 | ] 3412 | ] 3413 | } 3414 | }, 3415 | { 3416 | "type": "Feature", 3417 | "properties": { 3418 | "duration_min": 10, 3419 | "station_codes_1": "NE5", 3420 | "station_codes_2": "DT18", 3421 | "exit_name_1": "A", 3422 | "exit_name_2": "B" 3423 | }, 3424 | "geometry": { 3425 | "type": "Point", 3426 | "coordinates": [ 3427 | 103.84791983993394, 3428 | 1.284872814584496 3429 | ] 3430 | } 3431 | }, 3432 | { 3433 | "type": "Feature", 3434 | "properties": {}, 3435 | "geometry": { 3436 | "type": "LineString", 3437 | "coordinates": [ 3438 | [ 3439 | 103.853014, 3440 | 1.279176 3441 | ], 3442 | [ 3443 | 103.85299, 3444 | 1.27917 3445 | ], 3446 | [ 3447 | 103.85299, 3448 | 1.27915 3449 | ], 3450 | [ 3451 | 103.85304, 3452 | 1.27914 3453 | ], 3454 | [ 3455 | 103.85316, 3456 | 1.27907 3457 | ], 3458 | [ 3459 | 103.85317, 3460 | 1.27902 3461 | ], 3462 | [ 3463 | 103.85321, 3464 | 1.27903 3465 | ], 3466 | [ 3467 | 103.85351, 3468 | 1.27884 3469 | ], 3470 | [ 3471 | 103.85365, 3472 | 1.27875 3473 | ], 3474 | [ 3475 | 103.8537, 3476 | 1.27872 3477 | ], 3478 | [ 3479 | 103.85384, 3480 | 1.27863 3481 | ], 3482 | [ 3483 | 103.85386, 3484 | 1.27862 3485 | ], 3486 | [ 3487 | 103.85388, 3488 | 1.2786 3489 | ], 3490 | [ 3491 | 103.8539, 3492 | 1.27859 3493 | ], 3494 | [ 3495 | 103.85392, 3496 | 1.27857 3497 | ], 3498 | [ 3499 | 103.85394, 3500 | 1.27856 3501 | ], 3502 | [ 3503 | 103.85396, 3504 | 1.27855 3505 | ], 3506 | [ 3507 | 103.854, 3508 | 1.27852 3509 | ], 3510 | [ 3511 | 103.85401, 3512 | 1.27852 3513 | ], 3514 | [ 3515 | 103.85402, 3516 | 1.27851 3517 | ], 3518 | [ 3519 | 103.85403, 3520 | 1.27851 3521 | ], 3522 | [ 3523 | 103.85403, 3524 | 1.2785 3525 | ], 3526 | [ 3527 | 103.85404, 3528 | 1.2785 3529 | ], 3530 | [ 3531 | 103.85405, 3532 | 1.27849 3533 | ], 3534 | [ 3535 | 103.85406, 3536 | 1.27848 3537 | ], 3538 | [ 3539 | 103.85407, 3540 | 1.27848 3541 | ], 3542 | [ 3543 | 103.85408, 3544 | 1.27847 3545 | ], 3546 | [ 3547 | 103.8541, 3548 | 1.27846 3549 | ], 3550 | [ 3551 | 103.85413, 3552 | 1.27844 3553 | ], 3554 | [ 3555 | 103.85416, 3556 | 1.27842 3557 | ], 3558 | [ 3559 | 103.85419, 3560 | 1.2784 3561 | ], 3562 | [ 3563 | 103.8542, 3564 | 1.2784 3565 | ], 3566 | [ 3567 | 103.8542, 3568 | 1.27839 3569 | ], 3570 | [ 3571 | 103.85421, 3572 | 1.27839 3573 | ], 3574 | [ 3575 | 103.85422, 3576 | 1.27838 3577 | ], 3578 | [ 3579 | 103.85423, 3580 | 1.27838 3581 | ], 3582 | [ 3583 | 103.85423, 3584 | 1.27837 3585 | ], 3586 | [ 3587 | 103.85424, 3588 | 1.27836 3589 | ], 3590 | [ 3591 | 103.85426, 3592 | 1.27836 3593 | ], 3594 | [ 3595 | 103.85429, 3596 | 1.27834 3597 | ], 3598 | [ 3599 | 103.85431, 3600 | 1.27833 3601 | ], 3602 | [ 3603 | 103.85433, 3604 | 1.27831 3605 | ], 3606 | [ 3607 | 103.85438, 3608 | 1.27828 3609 | ], 3610 | [ 3611 | 103.85439, 3612 | 1.27827 3613 | ], 3614 | [ 3615 | 103.85441, 3616 | 1.27826 3617 | ], 3618 | [ 3619 | 103.85443, 3620 | 1.27819 3621 | ], 3622 | [ 3623 | 103.85442, 3624 | 1.27817 3625 | ], 3626 | [ 3627 | 103.8546, 3628 | 1.27815 3629 | ], 3630 | [ 3631 | 103.85463, 3632 | 1.27813 3633 | ], 3634 | [ 3635 | 103.85463, 3636 | 1.27812 3637 | ], 3638 | [ 3639 | 103.85442, 3640 | 1.27775 3641 | ], 3642 | [ 3643 | 103.85439, 3644 | 1.27773 3645 | ], 3646 | [ 3647 | 103.85437, 3648 | 1.27766 3649 | ], 3650 | [ 3651 | 103.85445, 3652 | 1.27735 3653 | ], 3654 | [ 3655 | 103.85447, 3656 | 1.277353 3657 | ] 3658 | ] 3659 | } 3660 | }, 3661 | { 3662 | "type": "Feature", 3663 | "properties": { 3664 | "duration_min": 4, 3665 | "station_codes_1": "DT17", 3666 | "station_codes_2": "NS27-CE2-TE20", 3667 | "exit_name_1": "D", 3668 | "exit_name_2": "1" 3669 | }, 3670 | "geometry": { 3671 | "type": "Point", 3672 | "coordinates": [ 3673 | 103.85414913542569, 3674 | 1.278427243049618 3675 | ] 3676 | } 3677 | }, 3678 | { 3679 | "type": "Feature", 3680 | "properties": {}, 3681 | "geometry": { 3682 | "type": "LineString", 3683 | "coordinates": [ 3684 | [ 3685 | 103.852428, 3686 | 1.279796 3687 | ], 3688 | [ 3689 | 103.85245, 3690 | 1.27982 3691 | ], 3692 | [ 3693 | 103.85211, 3694 | 1.28004 3695 | ], 3696 | [ 3697 | 103.85188, 3698 | 1.28019 3699 | ], 3700 | [ 3701 | 103.85172, 3702 | 1.2803 3703 | ], 3704 | [ 3705 | 103.85169, 3706 | 1.28031 3707 | ], 3708 | [ 3709 | 103.85164, 3710 | 1.28037 3711 | ], 3712 | [ 3713 | 103.85156, 3714 | 1.28046 3715 | ], 3716 | [ 3717 | 103.85149, 3718 | 1.28052 3719 | ], 3720 | [ 3721 | 103.85144, 3722 | 1.28057 3723 | ], 3724 | [ 3725 | 103.85134, 3726 | 1.28066 3727 | ], 3728 | [ 3729 | 103.85127, 3730 | 1.28072 3731 | ], 3732 | [ 3733 | 103.85125, 3734 | 1.28072 3735 | ], 3736 | [ 3737 | 103.85124, 3738 | 1.28071 3739 | ], 3740 | [ 3741 | 103.85121, 3742 | 1.28074 3743 | ], 3744 | [ 3745 | 103.85121, 3746 | 1.28083 3747 | ], 3748 | [ 3749 | 103.85105, 3750 | 1.28093 3751 | ], 3752 | [ 3753 | 103.85103, 3754 | 1.28095 3755 | ], 3756 | [ 3757 | 103.85133, 3758 | 1.2814 3759 | ], 3760 | [ 3761 | 103.85133, 3762 | 1.28142 3763 | ], 3764 | [ 3765 | 103.85134, 3766 | 1.28143 3767 | ], 3768 | [ 3769 | 103.85134, 3770 | 1.28145 3771 | ], 3772 | [ 3773 | 103.85135, 3774 | 1.28146 3775 | ], 3776 | [ 3777 | 103.85141, 3778 | 1.28155 3779 | ], 3780 | [ 3781 | 103.85142, 3782 | 1.28157 3783 | ], 3784 | [ 3785 | 103.85146, 3786 | 1.28164 3787 | ], 3788 | [ 3789 | 103.85148, 3790 | 1.28168 3791 | ], 3792 | [ 3793 | 103.85164, 3794 | 1.28192 3795 | ], 3796 | [ 3797 | 103.85165, 3798 | 1.28193 3799 | ], 3800 | [ 3801 | 103.85174, 3802 | 1.28208 3803 | ], 3804 | [ 3805 | 103.85175, 3806 | 1.28208 3807 | ], 3808 | [ 3809 | 103.85175, 3810 | 1.2821 3811 | ], 3812 | [ 3813 | 103.85176, 3814 | 1.2821 3815 | ], 3816 | [ 3817 | 103.85176, 3818 | 1.28212 3819 | ], 3820 | [ 3821 | 103.85177, 3822 | 1.28212 3823 | ], 3824 | [ 3825 | 103.85177, 3826 | 1.28217 3827 | ], 3828 | [ 3829 | 103.85176, 3830 | 1.28218 3831 | ], 3832 | [ 3833 | 103.85175, 3834 | 1.28219 3835 | ], 3836 | [ 3837 | 103.85173, 3838 | 1.28221 3839 | ], 3840 | [ 3841 | 103.85169, 3842 | 1.28223 3843 | ], 3844 | [ 3845 | 103.85157, 3846 | 1.28231 3847 | ], 3848 | [ 3849 | 103.85152, 3850 | 1.28234 3851 | ], 3852 | [ 3853 | 103.85147, 3854 | 1.28241 3855 | ], 3856 | [ 3857 | 103.85145, 3858 | 1.28242 3859 | ], 3860 | [ 3861 | 103.851433, 3862 | 1.282382 3863 | ] 3864 | ] 3865 | } 3866 | }, 3867 | { 3868 | "type": "Feature", 3869 | "properties": { 3870 | "duration_min": 5, 3871 | "station_codes_1": "DT17", 3872 | "station_codes_2": "NS26-EW14", 3873 | "exit_name_1": "F", 3874 | "exit_name_2": "I" 3875 | }, 3876 | "geometry": { 3877 | "type": "Point", 3878 | "coordinates": [ 3879 | 103.85107410894942, 3880 | 1.280914931907757 3881 | ] 3882 | } 3883 | }, 3884 | { 3885 | "type": "Feature", 3886 | "properties": {}, 3887 | "geometry": { 3888 | "type": "LineString", 3889 | "coordinates": [ 3890 | [ 3891 | 103.852478, 3892 | 1.279528 3893 | ], 3894 | [ 3895 | 103.85247, 3896 | 1.27952 3897 | ], 3898 | [ 3899 | 103.85246, 3900 | 1.27953 3901 | ], 3902 | [ 3903 | 103.85242, 3904 | 1.27955 3905 | ], 3906 | [ 3907 | 103.8524, 3908 | 1.27954 3909 | ], 3910 | [ 3911 | 103.85238, 3912 | 1.27952 3913 | ], 3914 | [ 3915 | 103.85237, 3916 | 1.2795 3917 | ], 3918 | [ 3919 | 103.85237, 3920 | 1.27948 3921 | ], 3922 | [ 3923 | 103.8523, 3924 | 1.27928 3925 | ], 3926 | [ 3927 | 103.85212, 3928 | 1.27902 3929 | ], 3930 | [ 3931 | 103.85205, 3932 | 1.27892 3933 | ], 3934 | [ 3935 | 103.85168, 3936 | 1.27834 3937 | ], 3938 | [ 3939 | 103.85133, 3940 | 1.27778 3941 | ], 3942 | [ 3943 | 103.851836, 3944 | 1.277462 3945 | ] 3946 | ] 3947 | } 3948 | }, 3949 | { 3950 | "type": "Feature", 3951 | "properties": { 3952 | "duration_min": 3, 3953 | "station_codes_1": "DT17", 3954 | "station_codes_2": "TE19", 3955 | "exit_name_1": "E", 3956 | "exit_name_2": "1" 3957 | }, 3958 | "geometry": { 3959 | "type": "Point", 3960 | "coordinates": [ 3961 | 103.8519118352004, 3962 | 1.2787034173780691 3963 | ] 3964 | } 3965 | }, 3966 | { 3967 | "type": "Feature", 3968 | "properties": {}, 3969 | "geometry": { 3970 | "type": "LineString", 3971 | "coordinates": [ 3972 | [ 3973 | 103.83384, 3974 | 1.286677 3975 | ], 3976 | [ 3977 | 103.83384, 3978 | 1.28669 3979 | ], 3980 | [ 3981 | 103.83376, 3982 | 1.28669 3983 | ], 3984 | [ 3985 | 103.83374, 3986 | 1.28634 3987 | ], 3988 | [ 3989 | 103.83357, 3990 | 1.28634 3991 | ], 3992 | [ 3993 | 103.83357, 3994 | 1.28626 3995 | ], 3996 | [ 3997 | 103.83356, 3998 | 1.28622 3999 | ], 4000 | [ 4001 | 103.83355, 4002 | 1.28618 4003 | ], 4004 | [ 4005 | 103.83351, 4006 | 1.28608 4007 | ], 4008 | [ 4009 | 103.83349, 4010 | 1.28606 4011 | ], 4012 | [ 4013 | 103.83348, 4014 | 1.28605 4015 | ], 4016 | [ 4017 | 103.83347, 4018 | 1.28604 4019 | ], 4020 | [ 4021 | 103.83339, 4022 | 1.28599 4023 | ], 4024 | [ 4025 | 103.8333, 4026 | 1.28597 4027 | ], 4028 | [ 4029 | 103.83313, 4030 | 1.28597 4031 | ], 4032 | [ 4033 | 103.83299, 4034 | 1.28604 4035 | ], 4036 | [ 4037 | 103.83296, 4038 | 1.28606 4039 | ], 4040 | [ 4041 | 103.83292, 4042 | 1.28608 4043 | ], 4044 | [ 4045 | 103.83284, 4046 | 1.28611 4047 | ], 4048 | [ 4049 | 103.83273, 4050 | 1.28608 4051 | ], 4052 | [ 4053 | 103.83267, 4054 | 1.28605 4055 | ], 4056 | [ 4057 | 103.83263, 4058 | 1.28603 4059 | ], 4060 | [ 4061 | 103.8326, 4062 | 1.28604 4063 | ], 4064 | [ 4065 | 103.83208, 4066 | 1.28602 4067 | ], 4068 | [ 4069 | 103.83194, 4070 | 1.28602 4071 | ], 4072 | [ 4073 | 103.83167, 4074 | 1.28601 4075 | ], 4076 | [ 4077 | 103.83162, 4078 | 1.28601 4079 | ], 4080 | [ 4081 | 103.83108, 4082 | 1.286 4083 | ], 4084 | [ 4085 | 103.83026, 4086 | 1.28596 4087 | ], 4088 | [ 4089 | 103.83018, 4090 | 1.28597 4091 | ], 4092 | [ 4093 | 103.83017, 4094 | 1.28597 4095 | ], 4096 | [ 4097 | 103.83016, 4098 | 1.28598 4099 | ], 4100 | [ 4101 | 103.83014, 4102 | 1.28599 4103 | ], 4104 | [ 4105 | 103.83005, 4106 | 1.28599 4107 | ], 4108 | [ 4109 | 103.83004, 4110 | 1.28598 4111 | ], 4112 | [ 4113 | 103.83, 4114 | 1.28598 4115 | ], 4116 | [ 4117 | 103.83001, 4118 | 1.28602 4119 | ], 4120 | [ 4121 | 103.82997, 4122 | 1.28603 4123 | ], 4124 | [ 4125 | 103.82994, 4126 | 1.28603 4127 | ], 4128 | [ 4129 | 103.82956, 4130 | 1.28601 4131 | ], 4132 | [ 4133 | 103.82932, 4134 | 1.286 4135 | ], 4136 | [ 4137 | 103.8293, 4138 | 1.286 4139 | ], 4140 | [ 4141 | 103.82883, 4142 | 1.28598 4143 | ], 4144 | [ 4145 | 103.82852, 4146 | 1.28596 4147 | ], 4148 | [ 4149 | 103.82847, 4150 | 1.28597 4151 | ], 4152 | [ 4153 | 103.82844, 4154 | 1.28596 4155 | ], 4156 | [ 4157 | 103.82843, 4158 | 1.28597 4159 | ], 4160 | [ 4161 | 103.82841, 4162 | 1.28595 4163 | ], 4164 | [ 4165 | 103.82828, 4166 | 1.28595 4167 | ], 4168 | [ 4169 | 103.82828, 4170 | 1.28593 4171 | ], 4172 | [ 4173 | 103.8282, 4174 | 1.28592 4175 | ], 4176 | [ 4177 | 103.828, 4178 | 1.28592 4179 | ], 4180 | [ 4181 | 103.82792, 4182 | 1.28593 4183 | ], 4184 | [ 4185 | 103.82787, 4186 | 1.28594 4187 | ], 4188 | [ 4189 | 103.82776, 4190 | 1.28596 4191 | ], 4192 | [ 4193 | 103.8276, 4194 | 1.28599 4195 | ], 4196 | [ 4197 | 103.82752, 4198 | 1.286 4199 | ], 4200 | [ 4201 | 103.82748, 4202 | 1.28601 4203 | ], 4204 | [ 4205 | 103.82747, 4206 | 1.28601 4207 | ], 4208 | [ 4209 | 103.8275, 4210 | 1.28612 4211 | ], 4212 | [ 4213 | 103.8275, 4214 | 1.28613 4215 | ], 4216 | [ 4217 | 103.82752, 4218 | 1.28624 4219 | ], 4220 | [ 4221 | 103.82753, 4222 | 1.28629 4223 | ], 4224 | [ 4225 | 103.82754, 4226 | 1.28631 4227 | ], 4228 | [ 4229 | 103.82749, 4230 | 1.28632 4231 | ], 4232 | [ 4233 | 103.827496, 4234 | 1.286362 4235 | ] 4236 | ] 4237 | } 4238 | }, 4239 | { 4240 | "type": "Feature", 4241 | "properties": { 4242 | "duration_min": 10, 4243 | "station_codes_1": "TE16", 4244 | "station_codes_2": "EW17", 4245 | "exit_name_1": "1", 4246 | "exit_name_2": "B" 4247 | }, 4248 | "geometry": { 4249 | "type": "Point", 4250 | "coordinates": [ 4251 | 103.83074965226317, 4252 | 1.2859838855080754 4253 | ] 4254 | } 4255 | }, 4256 | { 4257 | "type": "Feature", 4258 | "properties": {}, 4259 | "geometry": { 4260 | "type": "LineString", 4261 | "coordinates": [ 4262 | [ 4263 | 103.855245, 4264 | 1.305467 4265 | ], 4266 | [ 4267 | 103.85526, 4268 | 1.30546 4269 | ], 4270 | [ 4271 | 103.85524, 4272 | 1.30544 4273 | ], 4274 | [ 4275 | 103.85523, 4276 | 1.30542 4277 | ], 4278 | [ 4279 | 103.8552, 4280 | 1.30542 4281 | ], 4282 | [ 4283 | 103.85514, 4284 | 1.30533 4285 | ], 4286 | [ 4287 | 103.85513, 4288 | 1.30532 4289 | ], 4290 | [ 4291 | 103.85498, 4292 | 1.30543 4293 | ], 4294 | [ 4295 | 103.85496, 4296 | 1.30545 4297 | ], 4298 | [ 4299 | 103.8548, 4300 | 1.3052 4301 | ], 4302 | [ 4303 | 103.85412, 4304 | 1.30567 4305 | ], 4306 | [ 4307 | 103.85403, 4308 | 1.30574 4309 | ], 4310 | [ 4311 | 103.85351, 4312 | 1.30612 4313 | ], 4314 | [ 4315 | 103.85326, 4316 | 1.30609 4317 | ], 4318 | [ 4319 | 103.85319, 4320 | 1.30606 4321 | ], 4322 | [ 4323 | 103.8531, 4324 | 1.30614 4325 | ], 4326 | [ 4327 | 103.85305, 4328 | 1.30627 4329 | ], 4330 | [ 4331 | 103.85294, 4332 | 1.30624 4333 | ], 4334 | [ 4335 | 103.85292, 4336 | 1.30623 4337 | ], 4338 | [ 4339 | 103.85267, 4340 | 1.30635 4341 | ], 4342 | [ 4343 | 103.85265, 4344 | 1.30635 4345 | ], 4346 | [ 4347 | 103.85264, 4348 | 1.30636 4349 | ], 4350 | [ 4351 | 103.85245, 4352 | 1.30645 4353 | ], 4354 | [ 4355 | 103.85222, 4356 | 1.30656 4357 | ], 4358 | [ 4359 | 103.8522, 4360 | 1.30656 4361 | ], 4362 | [ 4363 | 103.85217, 4364 | 1.30657 4365 | ], 4366 | [ 4367 | 103.85202, 4368 | 1.30664 4369 | ], 4370 | [ 4371 | 103.85202, 4372 | 1.30666 4373 | ], 4374 | [ 4375 | 103.852, 4376 | 1.30663 4377 | ], 4378 | [ 4379 | 103.85199, 4380 | 1.30666 4381 | ], 4382 | [ 4383 | 103.85189, 4384 | 1.30673 4385 | ], 4386 | [ 4387 | 103.85183, 4388 | 1.30665 4389 | ], 4390 | [ 4391 | 103.85156, 4392 | 1.30686 4393 | ], 4394 | [ 4395 | 103.85143, 4396 | 1.30697 4397 | ], 4398 | [ 4399 | 103.85136, 4400 | 1.30688 4401 | ], 4402 | [ 4403 | 103.85124, 4404 | 1.30699 4405 | ], 4406 | [ 4407 | 103.85095, 4408 | 1.30721 4409 | ], 4410 | [ 4411 | 103.85081, 4412 | 1.30703 4413 | ], 4414 | [ 4415 | 103.85037, 4416 | 1.30739 4417 | ], 4418 | [ 4419 | 103.850322, 4420 | 1.307426 4421 | ] 4422 | ] 4423 | } 4424 | }, 4425 | { 4426 | "type": "Feature", 4427 | "properties": { 4428 | "duration_min": 9, 4429 | "station_codes_1": "DT22", 4430 | "station_codes_2": "NE7-DT12", 4431 | "exit_name_1": "B", 4432 | "exit_name_2": "E" 4433 | }, 4434 | "geometry": { 4435 | "type": "Point", 4436 | "coordinates": [ 4437 | 103.85283813078772, 4438 | 1.3062692972258996 4439 | ] 4440 | } 4441 | }, 4442 | { 4443 | "type": "Feature", 4444 | "properties": {}, 4445 | "geometry": { 4446 | "type": "LineString", 4447 | "coordinates": [ 4448 | [ 4449 | 103.855296, 4450 | 1.30489 4451 | ], 4452 | [ 4453 | 103.8552, 4454 | 1.30495 4455 | ], 4456 | [ 4457 | 103.8549, 4458 | 1.30447 4459 | ], 4460 | [ 4461 | 103.85486, 4462 | 1.3045 4463 | ], 4464 | [ 4465 | 103.85481, 4466 | 1.30447 4467 | ], 4468 | [ 4469 | 103.85468, 4470 | 1.30456 4471 | ], 4472 | [ 4473 | 103.85459, 4474 | 1.30442 4475 | ], 4476 | [ 4477 | 103.85457, 4478 | 1.30439 4479 | ], 4480 | [ 4481 | 103.85447, 4482 | 1.30449 4483 | ], 4484 | [ 4485 | 103.85434, 4486 | 1.30433 4487 | ], 4488 | [ 4489 | 103.85426, 4490 | 1.30426 4491 | ], 4492 | [ 4493 | 103.85401, 4494 | 1.30397 4495 | ], 4496 | [ 4497 | 103.85394, 4498 | 1.30389 4499 | ], 4500 | [ 4501 | 103.85382, 4502 | 1.30375 4503 | ], 4504 | [ 4505 | 103.85322, 4506 | 1.3042 4507 | ], 4508 | [ 4509 | 103.85314, 4510 | 1.30426 4511 | ], 4512 | [ 4513 | 103.853104, 4514 | 1.304215 4515 | ] 4516 | ] 4517 | } 4518 | }, 4519 | { 4520 | "type": "Feature", 4521 | "properties": { 4522 | "duration_min": 4, 4523 | "station_codes_1": "DT22", 4524 | "station_codes_2": "DT13", 4525 | "exit_name_1": "A", 4526 | "exit_name_2": "B" 4527 | }, 4528 | "geometry": { 4529 | "type": "Point", 4530 | "coordinates": [ 4531 | 103.85433864702196, 4532 | 1.3043288161442717 4533 | ] 4534 | } 4535 | }, 4536 | { 4537 | "type": "Feature", 4538 | "properties": {}, 4539 | "geometry": { 4540 | "type": "LineString", 4541 | "coordinates": [ 4542 | [ 4543 | 103.844895, 4544 | 1.280919 4545 | ], 4546 | [ 4547 | 103.84473, 4548 | 1.28103 4549 | ], 4550 | [ 4551 | 103.84472, 4552 | 1.28102 4553 | ], 4554 | [ 4555 | 103.84466, 4556 | 1.28092 4557 | ], 4558 | [ 4559 | 103.8446, 4560 | 1.28096 4561 | ], 4562 | [ 4563 | 103.8446, 4564 | 1.28094 4565 | ], 4566 | [ 4567 | 103.84458, 4568 | 1.28092 4569 | ], 4570 | [ 4571 | 103.84455, 4572 | 1.28087 4573 | ], 4574 | [ 4575 | 103.84448, 4576 | 1.28076 4577 | ], 4578 | [ 4579 | 103.84435, 4580 | 1.28057 4581 | ], 4582 | [ 4583 | 103.84429, 4584 | 1.28047 4585 | ], 4586 | [ 4587 | 103.84429, 4588 | 1.28039 4589 | ], 4590 | [ 4591 | 103.84431, 4592 | 1.28037 4593 | ], 4594 | [ 4595 | 103.84433, 4596 | 1.28033 4597 | ], 4598 | [ 4599 | 103.8447, 4600 | 1.27986 4601 | ], 4602 | [ 4603 | 103.84472, 4604 | 1.27984 4605 | ], 4606 | [ 4607 | 103.84473, 4608 | 1.27985 4609 | ], 4610 | [ 4611 | 103.84476, 4612 | 1.27982 4613 | ], 4614 | [ 4615 | 103.84481, 4616 | 1.27977 4617 | ], 4618 | [ 4619 | 103.84481, 4620 | 1.27973 4621 | ], 4622 | [ 4623 | 103.84505, 4624 | 1.27945 4625 | ], 4626 | [ 4627 | 103.84509, 4628 | 1.27939 4629 | ], 4630 | [ 4631 | 103.84534, 4632 | 1.27908 4633 | ], 4634 | [ 4635 | 103.84538, 4636 | 1.27902 4637 | ], 4638 | [ 4639 | 103.84568, 4640 | 1.27863 4641 | ], 4642 | [ 4643 | 103.84569, 4644 | 1.27861 4645 | ], 4646 | [ 4647 | 103.84598, 4648 | 1.27825 4649 | ], 4650 | [ 4651 | 103.84602, 4652 | 1.2782 4653 | ], 4654 | [ 4655 | 103.84614, 4656 | 1.27805 4657 | ], 4658 | [ 4659 | 103.84623, 4660 | 1.27812 4661 | ], 4662 | [ 4663 | 103.84637, 4664 | 1.27804 4665 | ], 4666 | [ 4667 | 103.84635, 4668 | 1.27798 4669 | ], 4670 | [ 4671 | 103.84633, 4672 | 1.27792 4673 | ], 4674 | [ 4675 | 103.84633, 4676 | 1.27787 4677 | ], 4678 | [ 4679 | 103.84635, 4680 | 1.27785 4681 | ], 4682 | [ 4683 | 103.84637, 4684 | 1.27783 4685 | ], 4686 | [ 4687 | 103.84639, 4688 | 1.27781 4689 | ], 4690 | [ 4691 | 103.84644, 4692 | 1.27778 4693 | ], 4694 | [ 4695 | 103.84647, 4696 | 1.27776 4697 | ], 4698 | [ 4699 | 103.84648, 4700 | 1.27775 4701 | ], 4702 | [ 4703 | 103.84656, 4704 | 1.27769 4705 | ], 4706 | [ 4707 | 103.84661, 4708 | 1.27764 4709 | ], 4710 | [ 4711 | 103.84664, 4712 | 1.27761 4713 | ], 4714 | [ 4715 | 103.84671, 4716 | 1.27755 4717 | ], 4718 | [ 4719 | 103.84678, 4720 | 1.27752 4721 | ], 4722 | [ 4723 | 103.84681, 4724 | 1.27753 4725 | ], 4726 | [ 4727 | 103.84684, 4728 | 1.27753 4729 | ], 4730 | [ 4731 | 103.84688, 4732 | 1.27754 4733 | ], 4734 | [ 4735 | 103.84701, 4736 | 1.27775 4737 | ], 4738 | [ 4739 | 103.846953, 4740 | 1.277785 4741 | ] 4742 | ] 4743 | } 4744 | }, 4745 | { 4746 | "type": "Feature", 4747 | "properties": { 4748 | "duration_min": 7, 4749 | "station_codes_1": "TE18", 4750 | "station_codes_2": "EW15", 4751 | "exit_name_1": "2", 4752 | "exit_name_2": "G" 4753 | }, 4754 | "geometry": { 4755 | "type": "Point", 4756 | "coordinates": [ 4757 | 103.84524041014043, 4758 | 1.2792034914377506 4759 | ] 4760 | } 4761 | }, 4762 | { 4763 | "type": "Feature", 4764 | "properties": {}, 4765 | "geometry": { 4766 | "type": "LineString", 4767 | "coordinates": [ 4768 | [ 4769 | 103.844895, 4770 | 1.280919 4771 | ], 4772 | [ 4773 | 103.84473, 4774 | 1.28103 4775 | ], 4776 | [ 4777 | 103.84482, 4778 | 1.28117 4779 | ], 4780 | [ 4781 | 103.84478, 4782 | 1.28131 4783 | ], 4784 | [ 4785 | 103.8448, 4786 | 1.28133 4787 | ], 4788 | [ 4789 | 103.84481, 4790 | 1.28133 4791 | ], 4792 | [ 4793 | 103.84484, 4794 | 1.28138 4795 | ], 4796 | [ 4797 | 103.84485, 4798 | 1.28139 4799 | ], 4800 | [ 4801 | 103.84483, 4802 | 1.28141 4803 | ], 4804 | [ 4805 | 103.84493, 4806 | 1.28155 4807 | ], 4808 | [ 4809 | 103.84499, 4810 | 1.28166 4811 | ], 4812 | [ 4813 | 103.84502, 4814 | 1.28167 4815 | ], 4816 | [ 4817 | 103.84503, 4818 | 1.28169 4819 | ], 4820 | [ 4821 | 103.84503, 4822 | 1.2817 4823 | ], 4824 | [ 4825 | 103.84505, 4826 | 1.28174 4827 | ], 4828 | [ 4829 | 103.84506, 4830 | 1.28176 4831 | ], 4832 | [ 4833 | 103.84527, 4834 | 1.2821 4835 | ], 4836 | [ 4837 | 103.84528, 4838 | 1.28211 4839 | ], 4840 | [ 4841 | 103.8453, 4842 | 1.28214 4843 | ], 4844 | [ 4845 | 103.84549, 4846 | 1.28247 4847 | ], 4848 | [ 4849 | 103.84553, 4850 | 1.28255 4851 | ], 4852 | [ 4853 | 103.84561, 4854 | 1.28268 4855 | ], 4856 | [ 4857 | 103.84569, 4858 | 1.28282 4859 | ], 4860 | [ 4861 | 103.8457, 4862 | 1.28283 4863 | ], 4864 | [ 4865 | 103.84572, 4866 | 1.28286 4867 | ], 4868 | [ 4869 | 103.84573, 4870 | 1.28288 4871 | ], 4872 | [ 4873 | 103.84574, 4874 | 1.2829 4875 | ], 4876 | [ 4877 | 103.84577, 4878 | 1.28296 4879 | ], 4880 | [ 4881 | 103.84592, 4882 | 1.2832 4883 | ], 4884 | [ 4885 | 103.84595, 4886 | 1.28326 4887 | ], 4888 | [ 4889 | 103.84604, 4890 | 1.28342 4891 | ], 4892 | [ 4893 | 103.84606, 4894 | 1.28345 4895 | ], 4896 | [ 4897 | 103.84607, 4898 | 1.28344 4899 | ], 4900 | [ 4901 | 103.84609, 4902 | 1.28347 4903 | ], 4904 | [ 4905 | 103.8461, 4906 | 1.28348 4907 | ], 4908 | [ 4909 | 103.84612, 4910 | 1.28347 4911 | ], 4912 | [ 4913 | 103.84621, 4914 | 1.28341 4915 | ], 4916 | [ 4917 | 103.84623, 4918 | 1.2834 4919 | ], 4920 | [ 4921 | 103.84632, 4922 | 1.28334 4923 | ], 4924 | [ 4925 | 103.84635, 4926 | 1.28333 4927 | ], 4928 | [ 4929 | 103.84645, 4930 | 1.28326 4931 | ], 4932 | [ 4933 | 103.84661, 4934 | 1.28317 4935 | ], 4936 | [ 4937 | 103.84666, 4938 | 1.28313 4939 | ], 4940 | [ 4941 | 103.84698, 4942 | 1.28294 4943 | ], 4944 | [ 4945 | 103.84703, 4946 | 1.28291 4947 | ], 4948 | [ 4949 | 103.84715, 4950 | 1.28283 4951 | ], 4952 | [ 4953 | 103.84717, 4954 | 1.28282 4955 | ], 4956 | [ 4957 | 103.84723, 4958 | 1.28279 4959 | ], 4960 | [ 4961 | 103.84725, 4962 | 1.28277 4963 | ], 4964 | [ 4965 | 103.84734, 4966 | 1.28272 4967 | ], 4968 | [ 4969 | 103.84744, 4970 | 1.28267 4971 | ], 4972 | [ 4973 | 103.84752, 4974 | 1.28262 4975 | ], 4976 | [ 4977 | 103.84791, 4978 | 1.28245 4979 | ], 4980 | [ 4981 | 103.84792, 4982 | 1.28244 4983 | ], 4984 | [ 4985 | 103.84791, 4986 | 1.28243 4987 | ], 4988 | [ 4989 | 103.84791, 4990 | 1.28242 4991 | ], 4992 | [ 4993 | 103.84792, 4994 | 1.28241 4995 | ], 4996 | [ 4997 | 103.848, 4998 | 1.28237 4999 | ], 5000 | [ 5001 | 103.84801, 5002 | 1.28234 5003 | ], 5004 | [ 5005 | 103.84813, 5006 | 1.28227 5007 | ], 5008 | [ 5009 | 103.84818, 5010 | 1.28224 5011 | ], 5012 | [ 5013 | 103.8483, 5014 | 1.28216 5015 | ], 5016 | [ 5017 | 103.84831, 5018 | 1.28215 5019 | ], 5020 | [ 5021 | 103.8484, 5022 | 1.28216 5023 | ], 5024 | [ 5025 | 103.84841, 5026 | 1.28214 5027 | ], 5028 | [ 5029 | 103.84841, 5030 | 1.28213 5031 | ], 5032 | [ 5033 | 103.84848, 5034 | 1.28209 5035 | ], 5036 | [ 5037 | 103.84849, 5038 | 1.28208 5039 | ], 5040 | [ 5041 | 103.84849, 5042 | 1.28207 5043 | ], 5044 | [ 5045 | 103.84852, 5046 | 1.2819 5047 | ], 5048 | [ 5049 | 103.84851, 5050 | 1.28188 5051 | ], 5052 | [ 5053 | 103.848507, 5054 | 1.281887 5055 | ] 5056 | ] 5057 | } 5058 | }, 5059 | { 5060 | "type": "Feature", 5061 | "properties": { 5062 | "duration_min": 8, 5063 | "station_codes_1": "TE18", 5064 | "station_codes_2": "DT18", 5065 | "exit_name_1": "2", 5066 | "exit_name_2": "A" 5067 | }, 5068 | "geometry": { 5069 | "type": "Point", 5070 | "coordinates": [ 5071 | 103.84602040343633, 5072 | 1.283385161666554 5073 | ] 5074 | } 5075 | }, 5076 | { 5077 | "type": "Feature", 5078 | "properties": {}, 5079 | "geometry": { 5080 | "type": "LineString", 5081 | "coordinates": [ 5082 | [ 5083 | 103.851433, 5084 | 1.282382 5085 | ], 5086 | [ 5087 | 103.85145, 5088 | 1.28242 5089 | ], 5090 | [ 5091 | 103.85147, 5092 | 1.28241 5093 | ], 5094 | [ 5095 | 103.85152, 5096 | 1.28234 5097 | ], 5098 | [ 5099 | 103.85157, 5100 | 1.28231 5101 | ], 5102 | [ 5103 | 103.85169, 5104 | 1.28223 5105 | ], 5106 | [ 5107 | 103.85173, 5108 | 1.28221 5109 | ], 5110 | [ 5111 | 103.85175, 5112 | 1.28219 5113 | ], 5114 | [ 5115 | 103.85176, 5116 | 1.28218 5117 | ], 5118 | [ 5119 | 103.85177, 5120 | 1.28217 5121 | ], 5122 | [ 5123 | 103.85177, 5124 | 1.28212 5125 | ], 5126 | [ 5127 | 103.85176, 5128 | 1.28212 5129 | ], 5130 | [ 5131 | 103.85176, 5132 | 1.2821 5133 | ], 5134 | [ 5135 | 103.85175, 5136 | 1.2821 5137 | ], 5138 | [ 5139 | 103.85175, 5140 | 1.28208 5141 | ], 5142 | [ 5143 | 103.85174, 5144 | 1.28208 5145 | ], 5146 | [ 5147 | 103.85165, 5148 | 1.28193 5149 | ], 5150 | [ 5151 | 103.85164, 5152 | 1.28192 5153 | ], 5154 | [ 5155 | 103.85148, 5156 | 1.28168 5157 | ], 5158 | [ 5159 | 103.85146, 5160 | 1.28164 5161 | ], 5162 | [ 5163 | 103.85142, 5164 | 1.28157 5165 | ], 5166 | [ 5167 | 103.85141, 5168 | 1.28155 5169 | ], 5170 | [ 5171 | 103.85135, 5172 | 1.28146 5173 | ], 5174 | [ 5175 | 103.85134, 5176 | 1.28145 5177 | ], 5178 | [ 5179 | 103.85134, 5180 | 1.28143 5181 | ], 5182 | [ 5183 | 103.85133, 5184 | 1.28142 5185 | ], 5186 | [ 5187 | 103.85133, 5188 | 1.2814 5189 | ], 5190 | [ 5191 | 103.85103, 5192 | 1.28095 5193 | ], 5194 | [ 5195 | 103.85105, 5196 | 1.28093 5197 | ], 5198 | [ 5199 | 103.85121, 5200 | 1.28083 5201 | ], 5202 | [ 5203 | 103.85121, 5204 | 1.28074 5205 | ], 5206 | [ 5207 | 103.8511, 5208 | 1.28056 5209 | ], 5210 | [ 5211 | 103.85107, 5212 | 1.28051 5213 | ], 5214 | [ 5215 | 103.85107, 5216 | 1.2805 5217 | ], 5218 | [ 5219 | 103.85096, 5220 | 1.28032 5221 | ], 5222 | [ 5223 | 103.85095, 5224 | 1.2803 5225 | ], 5226 | [ 5227 | 103.85075, 5228 | 1.27997 5229 | ], 5230 | [ 5231 | 103.85075, 5232 | 1.27994 5233 | ], 5234 | [ 5235 | 103.85073, 5236 | 1.27996 5237 | ], 5238 | [ 5239 | 103.85069, 5240 | 1.27993 5241 | ], 5242 | [ 5243 | 103.85063, 5244 | 1.27985 5245 | ], 5246 | [ 5247 | 103.85063, 5248 | 1.27982 5249 | ], 5250 | [ 5251 | 103.85064, 5252 | 1.27978 5253 | ], 5254 | [ 5255 | 103.85069, 5256 | 1.2798 5257 | ], 5258 | [ 5259 | 103.85077, 5260 | 1.27975 5261 | ], 5262 | [ 5263 | 103.85089, 5264 | 1.27968 5265 | ], 5266 | [ 5267 | 103.8509, 5268 | 1.27964 5269 | ], 5270 | [ 5271 | 103.85091, 5272 | 1.27959 5273 | ], 5274 | [ 5275 | 103.85083, 5276 | 1.27947 5277 | ], 5278 | [ 5279 | 103.85081, 5280 | 1.27945 5281 | ], 5282 | [ 5283 | 103.85079, 5284 | 1.27941 5285 | ], 5286 | [ 5287 | 103.85073, 5288 | 1.27931 5289 | ], 5290 | [ 5291 | 103.85071, 5292 | 1.27928 5293 | ], 5294 | [ 5295 | 103.8507, 5296 | 1.27926 5297 | ], 5298 | [ 5299 | 103.85068, 5300 | 1.27922 5301 | ], 5302 | [ 5303 | 103.85061, 5304 | 1.27911 5305 | ], 5306 | [ 5307 | 103.85059, 5308 | 1.27908 5309 | ], 5310 | [ 5311 | 103.85054, 5312 | 1.279 5313 | ], 5314 | [ 5315 | 103.85052, 5316 | 1.27897 5317 | ], 5318 | [ 5319 | 103.85044, 5320 | 1.27882 5321 | ], 5322 | [ 5323 | 103.85026, 5324 | 1.27853 5325 | ], 5326 | [ 5327 | 103.85008, 5328 | 1.27822 5329 | ], 5330 | [ 5331 | 103.85014, 5332 | 1.27816 5333 | ], 5334 | [ 5335 | 103.849893, 5336 | 1.277929 5337 | ] 5338 | ] 5339 | } 5340 | }, 5341 | { 5342 | "type": "Feature", 5343 | "properties": { 5344 | "duration_min": 8, 5345 | "station_codes_1": "NS26-EW14", 5346 | "station_codes_2": "TE19", 5347 | "exit_name_1": "I", 5348 | "exit_name_2": "6" 5349 | }, 5350 | "geometry": { 5351 | "type": "Point", 5352 | "coordinates": [ 5353 | 103.85097267394714, 5354 | 1.2803407391877586 5355 | ] 5356 | } 5357 | }, 5358 | { 5359 | "type": "Feature", 5360 | "properties": {}, 5361 | "geometry": { 5362 | "type": "LineString", 5363 | "coordinates": [ 5364 | [ 5365 | 103.850961, 5366 | 1.282539 5367 | ], 5368 | [ 5369 | 103.85093, 5370 | 1.28254 5371 | ], 5372 | [ 5373 | 103.85093, 5374 | 1.28256 5375 | ], 5376 | [ 5377 | 103.85087, 5378 | 1.28257 5379 | ], 5380 | [ 5381 | 103.85065, 5382 | 1.28258 5383 | ], 5384 | [ 5385 | 103.85059, 5386 | 1.28258 5387 | ], 5388 | [ 5389 | 103.85048, 5390 | 1.28259 5391 | ], 5392 | [ 5393 | 103.85042, 5394 | 1.28258 5395 | ], 5396 | [ 5397 | 103.85035, 5398 | 1.28257 5399 | ], 5400 | [ 5401 | 103.85031, 5402 | 1.28256 5403 | ], 5404 | [ 5405 | 103.85032, 5406 | 1.28242 5407 | ], 5408 | [ 5409 | 103.85029, 5410 | 1.28237 5411 | ], 5412 | [ 5413 | 103.85025, 5414 | 1.28235 5415 | ], 5416 | [ 5417 | 103.8502, 5418 | 1.28239 5419 | ], 5420 | [ 5421 | 103.85013, 5422 | 1.2824 5423 | ], 5424 | [ 5425 | 103.85009, 5426 | 1.28237 5427 | ], 5428 | [ 5429 | 103.8499, 5430 | 1.28211 5431 | ], 5432 | [ 5433 | 103.84972, 5434 | 1.28214 5435 | ], 5436 | [ 5437 | 103.84952, 5438 | 1.2818 5439 | ], 5440 | [ 5441 | 103.84949, 5442 | 1.28176 5443 | ], 5444 | [ 5445 | 103.84947, 5446 | 1.28176 5447 | ], 5448 | [ 5449 | 103.84944, 5450 | 1.28178 5451 | ], 5452 | [ 5453 | 103.84914, 5454 | 1.28196 5455 | ], 5456 | [ 5457 | 103.84913, 5458 | 1.28196 5459 | ], 5460 | [ 5461 | 103.84913, 5462 | 1.28197 5463 | ], 5464 | [ 5465 | 103.84912, 5466 | 1.28197 5467 | ], 5468 | [ 5469 | 103.84912, 5470 | 1.28199 5471 | ], 5472 | [ 5473 | 103.84907, 5474 | 1.28202 5475 | ], 5476 | [ 5477 | 103.84906, 5478 | 1.28203 5479 | ], 5480 | [ 5481 | 103.84903, 5482 | 1.28203 5483 | ], 5484 | [ 5485 | 103.84879, 5486 | 1.28216 5487 | ], 5488 | [ 5489 | 103.848842, 5490 | 1.282251 5491 | ] 5492 | ] 5493 | } 5494 | }, 5495 | { 5496 | "type": "Feature", 5497 | "properties": { 5498 | "duration_min": 4, 5499 | "station_codes_1": "NS26-EW14", 5500 | "station_codes_2": "DT18", 5501 | "exit_name_1": "F", 5502 | "exit_name_2": "C" 5503 | }, 5504 | "geometry": { 5505 | "type": "Point", 5506 | "coordinates": [ 5507 | 103.8499078343161, 5508 | 1.2821207206443923 5509 | ] 5510 | } 5511 | }, 5512 | { 5513 | "type": "Feature", 5514 | "properties": {}, 5515 | "geometry": { 5516 | "type": "LineString", 5517 | "coordinates": [ 5518 | [ 5519 | 103.849893, 5520 | 1.277929 5521 | ], 5522 | [ 5523 | 103.85014, 5524 | 1.27816 5525 | ], 5526 | [ 5527 | 103.85008, 5528 | 1.27822 5529 | ], 5530 | [ 5531 | 103.85026, 5532 | 1.27853 5533 | ], 5534 | [ 5535 | 103.85044, 5536 | 1.27882 5537 | ], 5538 | [ 5539 | 103.85052, 5540 | 1.27897 5541 | ], 5542 | [ 5543 | 103.85054, 5544 | 1.279 5545 | ], 5546 | [ 5547 | 103.85059, 5548 | 1.27908 5549 | ], 5550 | [ 5551 | 103.85061, 5552 | 1.27911 5553 | ], 5554 | [ 5555 | 103.85068, 5556 | 1.27922 5557 | ], 5558 | [ 5559 | 103.8507, 5560 | 1.27926 5561 | ], 5562 | [ 5563 | 103.85071, 5564 | 1.27928 5565 | ], 5566 | [ 5567 | 103.85073, 5568 | 1.27931 5569 | ], 5570 | [ 5571 | 103.85079, 5572 | 1.27941 5573 | ], 5574 | [ 5575 | 103.85081, 5576 | 1.27945 5577 | ], 5578 | [ 5579 | 103.85083, 5580 | 1.27947 5581 | ], 5582 | [ 5583 | 103.85091, 5584 | 1.27959 5585 | ], 5586 | [ 5587 | 103.8509, 5588 | 1.27964 5589 | ], 5590 | [ 5591 | 103.85089, 5592 | 1.27968 5593 | ], 5594 | [ 5595 | 103.85077, 5596 | 1.27975 5597 | ], 5598 | [ 5599 | 103.85069, 5600 | 1.2798 5601 | ], 5602 | [ 5603 | 103.85064, 5604 | 1.27978 5605 | ], 5606 | [ 5607 | 103.85063, 5608 | 1.27982 5609 | ], 5610 | [ 5611 | 103.85063, 5612 | 1.27985 5613 | ], 5614 | [ 5615 | 103.85069, 5616 | 1.27993 5617 | ], 5618 | [ 5619 | 103.8507, 5620 | 1.28 5621 | ], 5622 | [ 5623 | 103.85053, 5624 | 1.28009 5625 | ], 5626 | [ 5627 | 103.85051, 5628 | 1.28013 5629 | ], 5630 | [ 5631 | 103.85048, 5632 | 1.28031 5633 | ], 5634 | [ 5635 | 103.85039, 5636 | 1.28064 5637 | ], 5638 | [ 5639 | 103.85032, 5640 | 1.2809 5641 | ], 5642 | [ 5643 | 103.85036, 5644 | 1.28107 5645 | ], 5646 | [ 5647 | 103.85031, 5648 | 1.28109 5649 | ], 5650 | [ 5651 | 103.85015, 5652 | 1.28118 5653 | ], 5654 | [ 5655 | 103.85012, 5656 | 1.2812 5657 | ], 5658 | [ 5659 | 103.85011, 5660 | 1.28124 5661 | ], 5662 | [ 5663 | 103.84991, 5664 | 1.28135 5665 | ], 5666 | [ 5667 | 103.84957, 5668 | 1.28154 5669 | ], 5670 | [ 5671 | 103.84957, 5672 | 1.28157 5673 | ], 5674 | [ 5675 | 103.84963, 5676 | 1.28168 5677 | ], 5678 | [ 5679 | 103.84965, 5680 | 1.2817 5681 | ], 5682 | [ 5683 | 103.84965, 5684 | 1.28171 5685 | ], 5686 | [ 5687 | 103.84963, 5688 | 1.28172 5689 | ], 5690 | [ 5691 | 103.84952, 5692 | 1.2818 5693 | ], 5694 | [ 5695 | 103.84949, 5696 | 1.28176 5697 | ], 5698 | [ 5699 | 103.84947, 5700 | 1.28176 5701 | ], 5702 | [ 5703 | 103.84944, 5704 | 1.28178 5705 | ], 5706 | [ 5707 | 103.84914, 5708 | 1.28196 5709 | ], 5710 | [ 5711 | 103.84913, 5712 | 1.28196 5713 | ], 5714 | [ 5715 | 103.84913, 5716 | 1.28197 5717 | ], 5718 | [ 5719 | 103.84912, 5720 | 1.28197 5721 | ], 5722 | [ 5723 | 103.84912, 5724 | 1.28199 5725 | ], 5726 | [ 5727 | 103.84907, 5728 | 1.28202 5729 | ], 5730 | [ 5731 | 103.84906, 5732 | 1.28203 5733 | ], 5734 | [ 5735 | 103.84903, 5736 | 1.28203 5737 | ], 5738 | [ 5739 | 103.84879, 5740 | 1.28216 5741 | ], 5742 | [ 5743 | 103.848842, 5744 | 1.282251 5745 | ] 5746 | ] 5747 | } 5748 | }, 5749 | { 5750 | "type": "Feature", 5751 | "properties": { 5752 | "duration_min": 8, 5753 | "station_codes_1": "TE19", 5754 | "station_codes_2": "DT18", 5755 | "exit_name_1": "6", 5756 | "exit_name_2": "C" 5757 | }, 5758 | "geometry": { 5759 | "type": "Point", 5760 | "coordinates": [ 5761 | 103.85054427515107, 5762 | 1.2800824425677655 5763 | ] 5764 | } 5765 | }, 5766 | { 5767 | "type": "Feature", 5768 | "properties": {}, 5769 | "geometry": { 5770 | "type": "LineString", 5771 | "coordinates": [ 5772 | [ 5773 | 103.846953, 5774 | 1.277785 5775 | ], 5776 | [ 5777 | 103.84701, 5778 | 1.27775 5779 | ], 5780 | [ 5781 | 103.84702, 5782 | 1.27777 5783 | ], 5784 | [ 5785 | 103.84707, 5786 | 1.27786 5787 | ], 5788 | [ 5789 | 103.84707, 5790 | 1.27789 5791 | ], 5792 | [ 5793 | 103.84696, 5794 | 1.27796 5795 | ], 5796 | [ 5797 | 103.84689, 5798 | 1.27801 5799 | ], 5800 | [ 5801 | 103.84681, 5802 | 1.27812 5803 | ], 5804 | [ 5805 | 103.8468, 5806 | 1.27827 5807 | ], 5808 | [ 5809 | 103.84678, 5810 | 1.27843 5811 | ], 5812 | [ 5813 | 103.84678, 5814 | 1.2788 5815 | ], 5816 | [ 5817 | 103.84684, 5818 | 1.27906 5819 | ], 5820 | [ 5821 | 103.84685, 5822 | 1.27914 5823 | ], 5824 | [ 5825 | 103.84694, 5826 | 1.27944 5827 | ], 5828 | [ 5829 | 103.847, 5830 | 1.27957 5831 | ], 5832 | [ 5833 | 103.84706, 5834 | 1.27972 5835 | ], 5836 | [ 5837 | 103.84705, 5838 | 1.27975 5839 | ], 5840 | [ 5841 | 103.84708, 5842 | 1.27984 5843 | ], 5844 | [ 5845 | 103.84716, 5846 | 1.27982 5847 | ], 5848 | [ 5849 | 103.84717, 5850 | 1.27982 5851 | ], 5852 | [ 5853 | 103.84717, 5854 | 1.27983 5855 | ], 5856 | [ 5857 | 103.84725, 5858 | 1.27983 5859 | ], 5860 | [ 5861 | 103.84724, 5862 | 1.27984 5863 | ], 5864 | [ 5865 | 103.84733, 5866 | 1.27998 5867 | ], 5868 | [ 5869 | 103.84756, 5870 | 1.28044 5871 | ], 5872 | [ 5873 | 103.8477, 5874 | 1.28073 5875 | ], 5876 | [ 5877 | 103.84772, 5878 | 1.28076 5879 | ], 5880 | [ 5881 | 103.84779, 5882 | 1.28089 5883 | ], 5884 | [ 5885 | 103.84789, 5886 | 1.28108 5887 | ], 5888 | [ 5889 | 103.84803, 5890 | 1.28132 5891 | ], 5892 | [ 5893 | 103.84804, 5894 | 1.28134 5895 | ], 5896 | [ 5897 | 103.84805, 5898 | 1.28135 5899 | ], 5900 | [ 5901 | 103.84812, 5902 | 1.28148 5903 | ], 5904 | [ 5905 | 103.84828, 5906 | 1.28175 5907 | ], 5908 | [ 5909 | 103.84835, 5910 | 1.28187 5911 | ], 5912 | [ 5913 | 103.84836, 5914 | 1.2819 5915 | ], 5916 | [ 5917 | 103.84838, 5918 | 1.28192 5919 | ], 5920 | [ 5921 | 103.8485, 5922 | 1.28186 5923 | ], 5924 | [ 5925 | 103.84851, 5926 | 1.28188 5927 | ], 5928 | [ 5929 | 103.848507, 5930 | 1.281887 5931 | ] 5932 | ] 5933 | } 5934 | }, 5935 | { 5936 | "type": "Feature", 5937 | "properties": { 5938 | "duration_min": 7, 5939 | "station_codes_1": "EW15", 5940 | "station_codes_2": "DT18", 5941 | "exit_name_1": "G", 5942 | "exit_name_2": "A" 5943 | }, 5944 | "geometry": { 5945 | "type": "Point", 5946 | "coordinates": [ 5947 | 103.84721518469844, 5948 | 1.2798300000003067 5949 | ] 5950 | } 5951 | } 5952 | ] 5953 | } --------------------------------------------------------------------------------