(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 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RailRouter SG
2 |
3 | 
4 |
5 | 
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 | 
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 |
48 |
RailRouter SG
49 |
50 | Explore MRT and
51 | LRT rail routes in Singapore.
52 | Zoom in to see the location of the stations and their
53 | entrances/exits.
54 |
55 |
56 | Built
60 | by
61 | @cheeaun.
63 | ©
65 | LTA
72 | ©
74 | Data.gov.sg
80 | ©
82 | SMRT
86 | ©
88 | SBS
92 |
93 |
94 | Sister sites:
95 | 🚍 BusRouter SG
98 | 🚖 TaxiRouter SG
101 |
102 |
103 |
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 |
121 |
141 |
142 |
143 |
144 |
151 |
152 |
153 |
157 |
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 |
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 | |
318 | Arrival times powered by SMRT Trains Ltd.
319 | |
320 |
321 |
322 |
`;
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 |
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 | }
--------------------------------------------------------------------------------