14 Commits

Author SHA1 Message Date
765923ca0a Complete map 0230 to Standish Jn 2026-02-14 20:14:42 +00:00
1393f458db Adjust tunnel component to offer mid-tunnel section. 2026-02-13 22:30:48 +00:00
3f1ad2cf39 Ensure 'Kemble Tunnel' name is present 2026-02-13 22:28:02 +00:00
2016497c9e Route 0230: Draft covers as far as Kemble from Swindon 2026-02-13 22:27:34 +00:00
454561e481 Add additional meta tags 2026-02-12 20:49:43 +00:00
488217923f Update favicon 2026-02-12 20:12:36 +00:00
6232277de1 Re-introduce visible SVG overflow. Add electrification type to electrificationChange component.
Begin route 0230 (Swindon Jn - Standish Jn
2026-02-12 16:28:13 +00:00
cff62fa343 Remove 'checked' values from incomplete maps 2026-02-11 21:03:55 +00:00
f359938d78 Standardize junction abbreviation to Jn 2026-02-11 21:02:14 +00:00
7e68192312 Standardise & styles and improve performance on small displays.
Add inter-route linking from Junctions.
2026-02-11 20:58:01 +00:00
e94b0e811a Adjust sizes on manifest icons 2026-02-11 19:17:43 +00:00
04f6a28100 Provide new 'short_name' OB Maps to better fit on Android app drawer.
Update theme colour to accent colour to provide thematic separation of notification bar and header bar when running full screen on android.
2026-02-11 19:03:49 +00:00
54e3483a39 Include tabler icons and switch buttons to use icons 2026-02-11 19:01:24 +00:00
117d1f752e Switch to new resized logo with text 2026-02-11 18:37:10 +00:00
18 changed files with 964 additions and 96 deletions

29
package-lock.json generated
View File

@@ -13,6 +13,7 @@
"@sveltejs/adapter-node": "^5.5.2", "@sveltejs/adapter-node": "^5.5.2",
"@sveltejs/kit": "^2.50.1", "@sveltejs/kit": "^2.50.1",
"@sveltejs/vite-plugin-svelte": "^6.2.4", "@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tabler/icons-svelte": "^3.36.1",
"@types/node": "^22", "@types/node": "^22",
"eslint": "^9.39.2", "eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
@@ -1344,6 +1345,34 @@
"vite": "^6.3.0 || ^7.0.0" "vite": "^6.3.0 || ^7.0.0"
} }
}, },
"node_modules/@tabler/icons": {
"version": "3.36.1",
"resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.36.1.tgz",
"integrity": "sha512-f4Jg3Fof/Vru5ioix/UO4GX+sdDsF9wQo47FbtvG+utIYYVQ/QVAC0QYgcBbAjQGfbdOh2CCf0BgiFOF9Ixtjw==",
"dev": true,
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/codecalm"
}
},
"node_modules/@tabler/icons-svelte": {
"version": "3.36.1",
"resolved": "https://registry.npmjs.org/@tabler/icons-svelte/-/icons-svelte-3.36.1.tgz",
"integrity": "sha512-f48RDkXJr7dMbbWHho81rR91QiPleHTlOwJUM5uFhTqo7dXH4mNZxJo3tksQNmlIauh7PqoS3i+RY7YlZxg5yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@tabler/icons": ""
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/codecalm"
},
"peerDependencies": {
"svelte": ">=3 <6 || >=5.0.0-next.0"
}
},
"node_modules/@types/cookie": { "node_modules/@types/cookie": {
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",

View File

@@ -19,6 +19,7 @@
"@sveltejs/adapter-node": "^5.5.2", "@sveltejs/adapter-node": "^5.5.2",
"@sveltejs/kit": "^2.50.1", "@sveltejs/kit": "^2.50.1",
"@sveltejs/vite-plugin-svelte": "^6.2.4", "@sveltejs/vite-plugin-svelte": "^6.2.4",
"@tabler/icons-svelte": "^3.36.1",
"@types/node": "^22", "@types/node": "^22",
"eslint": "^9.39.2", "eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",

View File

@@ -7,6 +7,13 @@
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"
/> />
<link rel="manifest" href="/manifest.webmanifest" /> <link rel="manifest" href="/manifest.webmanifest" />
<meta name="title" content="OwlBoard Maps | Railway route schematics to assist with learning & refreshing routes" />
<meta name="description" content="Schematic route diagrams showing stations, junctions, crossings, bridges and more" />
<meta name="theme-color" content="#4fd1d1" />
<link rel="canonical" href="https://maps.owlboard.info" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://maps.owlboard.info" />
<title>OwlBoard Maps</title>
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover">

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -1,12 +1,19 @@
<script lang="ts"> <script lang="ts">
import { components } from '$lib/mapRegistry'; import { components } from '$lib/mapRegistry';
import type { ElecType } from '$lib/railStyles';
import { IconArrowNarrowRight } from '@tabler/icons-svelte';
export let feature: any; // Raw Object type featureType = "station" | "junction" | "crossovers" | "siteof" | "bridge" | "minorBridge" | "crossover" | "crossing" | "loop" | "loops" | "signallerChange" | "electrificationChange" | "default" | "tunnel";
export let activeElec: string; // Active Electrification Type export let feature: {name: string; type: featureType; goto?: string; entryPoint?: string; miles: number; chains: number; description?: string}; // Raw Object
export let activeElec: ElecType; // Active Electrification Type
export let reversed: boolean = false; export let reversed: boolean = false;
$: Icon = components[feature.type] || components.default; $: Icon = components[feature.type] || components.default;
// Linking Logic
$: isLinkable = !!(feature.goto && feature.entryPoint);
$: href = `/map/${feature.goto}#${feature.entryPoint}`;
const slugify = (str?: string) => const slugify = (str?: string) =>
str?.toLocaleLowerCase().trim().replace(/\s+/g, '-') ?? 'unknown'; str?.toLocaleLowerCase().trim().replace(/\s+/g, '-') ?? 'unknown';
</script> </script>
@@ -18,9 +25,10 @@
</div> </div>
<div class="icon-col"> <div class="icon-col">
<svelte:component this={Icon} {feature} {activeElec} {reversed} /> <svelte:component this={Icon} feature={feature as any} {activeElec} {reversed} />
</div> </div>
<svelte:element this={isLinkable ? 'a' : 'div'} {...(isLinkable ? { href } : {})} class="link-wrapper">
<div class="label-col"> <div class="label-col">
{#if feature.name} {#if feature.name}
<div class="feature-name">{feature.name}</div> <div class="feature-name">{feature.name}</div>
@@ -29,18 +37,31 @@
<div class="feature-desc">{feature.description}</div> <div class="feature-desc">{feature.description}</div>
{/if} {/if}
</div> </div>
{#if isLinkable}
<div class="link-indicator">
<IconArrowNarrowRight />
</div>
{/if}
</svelte:element>
</div> </div>
<style> <style>
a {
cursor: pointer;
text-decoration: none;
}
.row-container { .row-container {
display: grid; display: grid;
/* Balanced columns: 1fr on both sides keeps the 64px icon in the dead center */
grid-template-columns: 3.5rem 64px 1fr; grid-template-columns: 3.5rem 64px 1fr;
width: 100%; width: 100%;
height: 64px; height: 64px;
max-height: 64px;
align-items: center; align-items: center;
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow: hidden;
} }
.mileage-col { .mileage-col {
@@ -50,7 +71,7 @@
padding-right: 12px; padding-right: 12px;
font-family: 'Courier New', Courier, monospace; font-family: 'Courier New', Courier, monospace;
font-size: 0.85rem; font-size: 0.85rem;
color: #64748b; /* Adjusted slightly for contrast */ color: #64748b;
} }
.miles { .miles {
@@ -62,13 +83,46 @@
font-size: 0.7rem; font-size: 0.7rem;
} }
.icon-col { .icon-col {
width: 64px; width: 64px;
height: 64px; height: 64px;
/* Ensure the icon itself is centered if the SVG is smaller than 64px */
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
overflow: visible;
}
.link-wrapper {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
height: 100%;
text-decoration: none;
color: inherit;
padding: 0;
box-sizing: border-box;
}
.link-indicator {
display: flex;
align-items: center;
margin-left: 5px;
margin-right: 8px;
flex-shrink: 0;
color: #e1ebeb;
background-color: #3c6f79;
padding: 2px 2px;
border-radius: 999px;
transition: all 0.3s ease;
}
.link-wrapper:hover .link-indicator {
background-color: #404c55;
transform: rotate(-45deg);
} }
.label-col { .label-col {
@@ -76,20 +130,16 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
/* FIX: Allow children to manage their own wrapping */
overflow: hidden; overflow: hidden;
/* min-width: 0 is critical for flex children to allow truncation */
min-width: 0; min-width: 0;
} }
.feature-name { .feature-name {
font-weight: 700; font-weight: 700;
font-family: sans-serif;
color: #1e293b; color: #1e293b;
font-size: 0.8rem; font-size: 0.8rem;
text-transform: capitalize; text-transform: capitalize;
/* Allow the title to wrap naturally onto multiple lines */
white-space: normal; white-space: normal;
line-height: 1.2; line-height: 1.2;
margin-bottom: 2px; margin-bottom: 2px;
@@ -98,12 +148,11 @@
.feature-desc { .feature-desc {
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
font-family: sans-serif;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
line-clamp: 2;
overflow: hidden; overflow: hidden;
/* Firefox Fix: Ensure white-space is normal here too */
white-space: normal; white-space: normal;
line-height: 1.2rem; line-height: 1.2rem;
max-height: 2.4rem; max-height: 2.4rem;
font-size: 0.75rem; font-size: 0.75rem;
@@ -111,21 +160,26 @@
word-break: break-word; word-break: break-word;
} }
/* Tablet and Desktop scaling */ @media (max-width: 320px) {
.feature-desc {
display: none;
}
}
@media (min-width: 480px) { @media (min-width: 480px) {
.feature-name { .feature-name {
font-size: 1rem; /* The larger title you requested */ font-size: 1rem;
margin-bottom: 4px; margin-bottom: 4px;
} }
.feature-desc { .feature-desc {
font-size: 0.85rem; /* Slightly larger desc to match */ font-size: 0.85rem;
line-height: 1.3rem; line-height: 1.3rem;
max-height: 2.6rem; max-height: 2.6rem;
} }
.label-col { .label-col {
padding-left: 24px; /* More "breathing room" on big screens */ padding-left: 24px;
} }
} }
</style> </style>

View File

@@ -9,10 +9,9 @@
$: type = feature.kind.toLowerCase(); $: type = feature.kind.toLowerCase();
$: isFoot = type === 'foot'; $: isFoot = type === 'foot';
$: filterCategory = isFoot ? 'foot' : type === 'uwc' ? 'uwc' : 'level-crossing';
</script> </script>
<svg viewBox="0 0 64 64" width="64" height="64" class={filterCategory}> <svg viewBox="0 0 64 64" width="64" height="64">
<BaseTrack {activeElec} height={64} /> <BaseTrack {activeElec} height={64} />
{#if type === 'foot'} {#if type === 'foot'}

View File

@@ -37,13 +37,13 @@
<g font-family="sans-serif" font-size="10" font-weight="800" text-anchor="start"> <g font-family="sans-serif" font-size="10" font-weight="800" text-anchor="start">
{#if showFromEco} {#if showFromEco}
<text x="75" y="24" fill="#b91c1c" style="text-transform: uppercase;"> <text x="75" y="24" fill="#b91c1c" style="text-transform: uppercase;">
ECO: {feature.from.eco} ECO: {feature.from.eco} | Type: {feature.from.elec}
</text> </text>
{/if} {/if}
{#if showToEco} {#if showToEco}
<text x="75" y="48" fill="#b91c1c" style="text-transform: uppercase;"> <text x="75" y="48" fill="#b91c1c" style="text-transform: uppercase;">
ECO: {feature.to.eco} ECO: {feature.to.eco} | Type: {feature.from.elec}
</text> </text>
{/if} {/if}
</g> </g>

View File

@@ -6,6 +6,8 @@
direction: 'up' | 'down'; direction: 'up' | 'down';
diverges: 'left' | 'right' | 'both'; diverges: 'left' | 'right' | 'both';
elecBranch?: string; elecBranch?: string;
goto?: string;
entryPoint?: string;
}; };
export let activeElec: any; export let activeElec: any;
export let reversed: boolean = false; export let reversed: boolean = false;

View File

@@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { IconArrowNarrowRight } from '@tabler/icons-svelte';
export let feature: { export let feature: {
routeName: string; routeName: string;
routeId: string; routeId: string;
@@ -17,16 +18,7 @@
</div> </div>
<div class="icon-circle"> <div class="icon-circle">
<svg viewBox="0 0 24 24" width="20" height="20"> <IconArrowNarrowRight />
<path
d="M5 12h14M12 5l7 7-7 7"
fill="none"
stroke="currentColor"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</div> </div>
</a> </a>
</div> </div>
@@ -69,12 +61,14 @@
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.05em; letter-spacing: 0.05em;
font-family: "urwgothic";
color: #64748b; color: #64748b;
} }
.route-id-chip { .route-id-chip {
font-size: 0.6rem; font-size: 0.6rem;
font-weight: 800; font-weight: 800;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
background: #f1f5f9; background: #f1f5f9;
color: #475569; color: #475569;
padding: 2px 6px; padding: 2px 6px;
@@ -83,6 +77,7 @@
} }
.main-text { .main-text {
font-family: "urwgothic";
font-size: 1rem; font-size: 1rem;
font-weight: 800; font-weight: 800;
color: #0f172a; color: #0f172a;
@@ -92,16 +87,15 @@
} }
.icon-circle { .icon-circle {
width: 40px;
height: 40px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: #f8fafc;
border-radius: 50%; color: #e1ebeb;
color: #94a3b8; background-color: #3c6f79;
padding: 4px 4px;
border-radius: 999px;
transition: all 0.3s ease; transition: all 0.3s ease;
margin-left: 12px;
} }
.wide-button:hover { .wide-button:hover {
@@ -111,8 +105,7 @@
} }
.wide-button:hover .icon-circle { .wide-button:hover .icon-circle {
background: #4f46e5; background-color: #404c55;
color: #ffffff;
transform: rotate(-45deg); transform: rotate(-45deg);
} }

View File

@@ -2,7 +2,7 @@
import BaseTrack from './BaseTrack.svelte'; import BaseTrack from './BaseTrack.svelte';
export let feature: { export let feature: {
tunnelType: 'start' | 'whole' | 'end'; tunnelType: 'start' | 'whole' | 'end' | 'mid';
length: string; length: string;
}; };
@@ -13,7 +13,7 @@
const portalColour = '#475569'; // Slate grey const portalColour = '#475569'; // Slate grey
$: effectiveType = (() => { $: effectiveType = (() => {
if (!reversed || feature.tunnelType === 'whole') return feature.tunnelType; if (!reversed || feature.tunnelType === 'whole' || feature.tunnelType === 'mid') return feature.tunnelType;
return feature.tunnelType === 'start' ? 'end' : 'start'; return feature.tunnelType === 'start' ? 'end' : 'start';
})(); })();
</script> </script>
@@ -32,7 +32,7 @@
{/if} {/if}
</g> </g>
{#if feature.tunnelType === 'whole' && feature.length} {#if feature.length}
<rect x="12" y="26" width="40" height="12" fill="white" /> <rect x="12" y="26" width="40" height="12" fill="white" />
<text <text
x="32" x="32"

View File

@@ -9,21 +9,21 @@ export const prerender = true;
export const GET: RequestHandler = ({ url }) => { export const GET: RequestHandler = ({ url }) => {
const manifest = { const manifest = {
name: 'OwlBoard Maps', name: 'OwlBoard Maps',
short_name: 'OwlBoard Maps', short_name: 'OB Maps',
start_url: '/', start_url: '/',
display: 'standalone', display: 'standalone',
theme_color: '#3c6f79', theme_color: '#4fd1d1',
background_color: '#3d4952', background_color: '#3d4952',
icons: [ icons: [
{ {
src: logo, src: logo,
sizes: 'any', sizes: '48x48 72x72 96x96 128x128 256x256 512x512 any',
type: 'image/svg+xml', type: 'image/svg+xml',
purpose: 'any' purpose: 'any'
}, },
{ {
src: maskableLogo, src: maskableLogo,
sizes: 'any', sizes: '48x48 72x72 96x96 128x128 256x256 512x512 any',
type: 'image/svg+xml', type: 'image/svg+xml',
purpose: 'maskable' purpose: 'maskable'
}, },

View File

@@ -5,6 +5,7 @@
import { resolve } from '$app/paths'; import { resolve } from '$app/paths';
import logo from '$lib/assets/round-logo.svg'; import logo from '$lib/assets/round-logo.svg';
import { IconArrowsExchange, IconSettings } from '@tabler/icons-svelte';
// data.route contains: routeStart, routeEnd, routeId, elecStart, elecEnd, routeDetail[] // data.route contains: routeStart, routeEnd, routeId, elecStart, elecEnd, routeDetail[]
export let data; export let data;
@@ -21,7 +22,8 @@
electrificationChange: true, electrificationChange: true,
siteof: true, siteof: true,
junction: true, junction: true,
tunnel: true tunnel: true,
crossing: true,
}; };
let showFilters = false; let showFilters = false;
@@ -74,7 +76,8 @@
{reversed ? data.route.routeEnd : data.route.routeStart} {reversed ? data.route.routeEnd : data.route.routeStart}
</h1> </h1>
<span class="secondary-station"> <span class="secondary-station">
to {reversed ? data.route.routeStart : data.route.routeEnd} <span class="route-stack-to">
to</span> {reversed ? data.route.routeStart : data.route.routeEnd}
</span> </span>
{/if} {/if}
</div> </div>
@@ -82,9 +85,9 @@
<div class="quick-actions"> <div class="quick-actions">
<button class="icon-btn" onclick={() => (reversed = !reversed)}> <button class="icon-btn" onclick={() => (reversed = !reversed)}>
{reversed ? 'UP' : 'DN'} <IconArrowsExchange />
</button> </button>
<button class="icon-btn" onclick={() => (showFilters = !showFilters)}> Settings </button> <button class="icon-btn" onclick={() => (showFilters = !showFilters)}> <IconSettings /> </button>
</div> </div>
</header> </header>
@@ -184,11 +187,20 @@
width: 52px; width: 52px;
height: 52px; height: 52px;
padding-left: 0; padding-left: 0;
margin-left: 0; margin-left: 15px;
margin-right: 0;
padding-right: 0;
flex-shrink: 0; flex-shrink: 0;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
@media (max-width: 350px) {
.home-link {
width: 42px;
height: 42px;
}
}
.home-link:hover { .home-link:hover {
transform: translateY(-1px) scale(1.05); transform: translateY(-1px) scale(1.05);
filter: brightness(1.1); filter: brightness(1.1);
@@ -200,8 +212,14 @@
.route-stack { .route-stack {
display: flex; display: flex;
font-family: "urwgothic";
flex-direction: column; flex-direction: column;
min-width: 0; min-width: 0;
margin-left: 0;
}
.route-stack-to {
text-transform: lowercase;
} }
.primary-station { .primary-station {
@@ -217,32 +235,30 @@
.secondary-station { .secondary-station {
font-size: 0.7rem; font-size: 0.7rem;
color: #cce9e9; color: #cce9e9;
text-transform: uppercase; text-transform: capitalize;
font-weight: 600; font-weight: 600;
} }
.quick-actions { .quick-actions {
display: flex; display: flex;
gap: 0.5rem; gap: 0.5rem;
margin-right: 15px;
} }
.map-spine { .map-spine {
padding-top: 72px; padding-top: 72px;
} }
@media (min-width: 768px) { @media (min-width: 536px) {
.primary-station { .primary-station {
font-size: 1.5rem; font-size: 1.5rem;
} }
.secondary-station { .secondary-station {
font-size: 1rem; font-size: 1rem;
} }
.top-nav {
padding: 0 2rem;
height: 80px;
} }
@media (min-width: 768px) {
h1 { h1 {
font-size: 1.5rem; font-size: 1.5rem;
letter-spacing: -0.03em; letter-spacing: -0.03em;
@@ -359,6 +375,12 @@
transition: all 0.3s ease; transition: all 0.3s ease;
} }
@media (max-width: 390px) {
.icon-btn {
padding: 0.3rem 0.3rem;
}
}
.icon-btn:hover { .icon-btn:hover {
background: #2d2d2d; background: #2d2d2d;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

@@ -52,7 +52,7 @@ routeDetail:
chains: 52 chains: 52
- type: crossovers - type: crossovers
name: Subway Junction name: Subway Jn
miles: 0 miles: 0
chains: 61 chains: 61
@@ -85,7 +85,7 @@ routeDetail:
chains: 18 chains: 18
- type: junction - type: junction
name: Westbourne Park Junction name: Westbourne Park Jn
diverges: left diverges: left
direction: up direction: up
description: to Crossrail Core Operating Section description: to Crossrail Core Operating Section
@@ -93,7 +93,7 @@ routeDetail:
chains: 21 chains: 21
- type: crossovers - type: crossovers
name: Portobello Junction name: Portobello Jn
miles: 1 miles: 1
chains: 33 chains: 33
@@ -120,7 +120,7 @@ routeDetail:
chains: 73 chains: 73
- type: junction - type: junction
name: Kensal Green East Junction name: Kensal Green East Jn
diverges: both diverges: both
direction: down direction: down
description: to Crossrail & North Pole Depots description: to Crossrail & North Pole Depots
@@ -177,7 +177,7 @@ routeDetail:
chains: 45 chains: 45
- type: junction - type: junction
name: Friars Junction name: Friars Jn
diverges: left diverges: left
direction: up direction: up
elecBranch: none elecBranch: none
@@ -207,7 +207,7 @@ routeDetail:
chains: 80 chains: 80
- type: junction - type: junction
name: Acton East Junction name: Acton East Jn
diverges: left diverges: left
direction: up direction: up
description: Up/Dn Poplar to Acton Wells Jn description: Up/Dn Poplar to Acton Wells Jn
@@ -312,7 +312,7 @@ routeDetail:
chains: 46 chains: 46
- type: junction - type: junction
name: West Ealing Junction name: West Ealing Jn
diverges: left diverges: left
direction: down direction: down
elecBranch: none elecBranch: none
@@ -328,7 +328,7 @@ routeDetail:
chains: 71 chains: 71
- type: junction - type: junction
name: Hanwell Junction name: Hanwell Jn
diverges: left diverges: left
direction: up direction: up
elecBranch: none elecBranch: none
@@ -394,7 +394,7 @@ routeDetail:
chains: 46 chains: 46
- type: junction - type: junction
name: Southall East Junction name: Southall East Jn
diverges: right diverges: right
direction: up direction: up
elecBranch: none elecBranch: none
@@ -423,7 +423,7 @@ routeDetail:
chains: 53 chains: 53
- type: crossovers - type: crossovers
name: Southall West Junction name: Southall West Jn
description: Southall Sidings Diverge description: Southall Sidings Diverge
miles: 9 miles: 9
chains: 70 chains: 70
@@ -490,7 +490,7 @@ routeDetail:
chains: 77 chains: 77
- type: junction - type: junction
name: Heathrow Airport Junction name: Heathrow Airport Jn
diverges: both diverges: both
direction: down direction: down
miles: 11 miles: 11
@@ -506,7 +506,7 @@ routeDetail:
chains: 28 chains: 28
- type: crossovers - type: crossovers
name: Stockley Bridge Junction name: Stockley Bridge Jn
miles: 12 miles: 12
chains: 9 chains: 9
@@ -519,7 +519,7 @@ routeDetail:
chains: 22 chains: 22
- type: crossovers - type: crossovers
name: West Drayton East Junction name: West Drayton East Jn
miles: 12 miles: 12
chains: 67 chains: 67
@@ -544,7 +544,7 @@ routeDetail:
chains: 56 chains: 56
- type: junction - type: junction
name: West Drayton Junction name: West Drayton Jn
diverges: left diverges: left
direction: down direction: down
description: Colnbrook Freight (near Heathrow) description: Colnbrook Freight (near Heathrow)
@@ -725,7 +725,7 @@ routeDetail:
chains: 42 chains: 42
- type: junction - type: junction
name: Windsor Branch Junction name: Windsor Branch Jn
diverges: right diverges: right
direction: down direction: down
description: Windsor Branch from platforms 1 & 2 Only description: Windsor Branch from platforms 1 & 2 Only
@@ -1048,7 +1048,7 @@ routeDetail:
chains: 1 chains: 1
- type: junction - type: junction
name: Henley Branch Junction name: Henley Branch Jn
diverges: left diverges: left
direction: down direction: down
description: Henley-on-Thames from Platform 4 only description: Henley-on-Thames from Platform 4 only
@@ -1169,7 +1169,7 @@ routeDetail:
chains: 77 chains: 77
- type: crossovers - type: crossovers
name: Kennet Bridge Junction name: Kennet Bridge Jn
miles: 35 miles: 35
chains: 10 chains: 10
@@ -1182,7 +1182,7 @@ routeDetail:
chains: 28 chains: 28
- type: junction - type: junction
name: Reading New Junction name: Reading New Jn
diverges: right diverges: right
direction: up direction: up
elecBranch: none elecBranch: none
@@ -1199,7 +1199,7 @@ routeDetail:
chains: 40 chains: 40
- type: junction - type: junction
name: Reading East Junction name: Reading East Jn
diverges: left diverges: left
direction: up direction: up
elecBranch: none elecBranch: none
@@ -1222,3 +1222,4 @@ routeDetail:
- type: continues - type: continues
routeName: Reading - Bristol TM routeName: Reading - Bristol TM
routeId: '0002' routeId: '0002'
entryPoint: reading

View File

@@ -14,6 +14,7 @@ routeDetail:
- type: continues - type: continues
routeName: Paddington - Reading routeName: Paddington - Reading
routeId: '0001' routeId: '0001'
entryPoint: reading
- type: station - type: station
name: Reading name: Reading
@@ -30,21 +31,25 @@ routeDetail:
- type: junction - type: junction
diverges: right diverges: right
direction: down direction: down
name: Westbury Line Junction name: Westbury Line Jn
description: to Oxford Road Jn description: to Oxford Road Jn
goto: "0201"
entryPoint: "oxford-road-jn"
miles: 36 miles: 36
chains: 17 chains: 17
- type: junction - type: junction
diverges: right diverges: right
direction: down direction: down
name: Caversham Road Junction name: Caversham Road Jn
description: Reading Feeder Main/Relief diverge and pass under Reading Viaduct to Oxford Rd Jn description: Reading Feeder Main/Relief diverge and pass under Reading Viaduct to Oxford Rd Jn
goto: "0201"
entryPoint: "oxford-road-jn"
miles: 36 miles: 36
chains: 22 chains: 22
- type: crossovers - type: crossovers
name: Reading High Level Junction name: Reading High Level Jn
description: Down Reading Festival Connects to Down Main description: Down Reading Festival Connects to Down Main
miles: 36 miles: 36
chains: 47 chains: 47
@@ -52,7 +57,9 @@ routeDetail:
- type: junction - type: junction
diverges: right diverges: right
direction: up direction: up
name: Reading West Junction name: Reading West Jn
description: to Oxford Road Junction (From relief lines only) description: to Oxford Road Junction (From relief lines only)
goto: "0201"
entryPoint: "oxford-road-jn"
miles: 37 miles: 37
chains: 17 chains: 17

View File

@@ -1,8 +1,8 @@
routeStart: Swindon Junction routeStart: Swindon Junction
routeEnd: Standish Junction routeEnd: Standish Junction
routeId: 0230 routeId: 0230
updated: 2026-02-11 updated: 2026-02-14
checked: 2026-02-11 checked: 2025-02-14
signallerStart: TVSC Swindon WS signallerStart: TVSC Swindon WS
signallerEnd: Gloucester PSB signallerEnd: Gloucester PSB
elecStart: elecStart:
@@ -10,3 +10,754 @@ elecStart:
eco: Didcot (TVSC) eco: Didcot (TVSC)
elecEnd: elecEnd:
elec: none elec: none
routeDetail:
- type: continues
routeName: Reading - Bristol TM
routeId: '0002'
entryPoint: swindon
- type: junction
name: Swindon Jn
diverges: right
goto: "0002"
entryPoint: swindon-jn
miles: 77
chains: 36
- type: electrificationChange
miles: 77
chains: 58
from:
elec: 25kvac
eco: Didcot
to:
elec: none
- type: minorBridge
name: Bruce Street
position: under
category: road
miles: 78
chains: 7
- type: crossovers
name: Rodbourne Jn
description: Limit of bidirectional running from Swindon
miles: 78
chains: 30
- type: bridge
name: River Hay
position: under
category: waterway
miles: 78
chains: 71
- type: minorBridge
name: Former MSWJ Railway
position: under
category: foot
miles: 79
chains: 20
- type: minorBridge
name: Edward's Bridge
position: under
category: road
miles: 79
chains: 33
- type: minorBridge
name: Mill Brook
position: under
category: stream
miles: 79
chains: 34
- type: bridge
name: Purton Road
description: Double bridge
position: over
category: road
roadName: B4534
miles: 79
chains: 53
- type: minorBridge
position: under
category: road
miles: 80
chains: 0
- type: minorBridge
position: over
category: road
roadName: B4553
miles: 80
chains: 30
- type: crossing
kind: foot
name: Purton No.72 Foot Crossing
miles: 80
chains: 63
- type: crossing
kind: AHB
name: Purton Collins Lane LC
miles: 81
chains: 9
- type: crossing
name: Purton No.64 Foot Crossing
kind: foot
miles: 81
chains: 25
- type: crossing
name: Purton No.60 Foot Crossing
kind: foot
miles: 81
chains: 46
- type: crossing
name: Purton Common Crossing
kind: MSL
miles: 81
chains: 65
- type: crossing
name: Purton No.129 Foot Crossing
kind: foot
miles: 82
chains: 9
- type: minorBridge
name: Farm Bridge
position: over
category: road
miles: 82
chains: 13
- type: crossing
name: Purton No.34 Foot Crossing
kind: foot
miles: 82
chains: 30
- type: minorBridge
name: Carpenter's
position: under
category: road
miles: 82
chains: 39
- type: minorBridge
name: Braydon Brook
position: under
category: stream
miles: 82
chains: 53
- type: minorBridge
name: Oak Hill (Coxhill Farm)
position: under
category: road
miles: 82
chains: 69
- type: crossing
kind: uwc
name: Clover's Foot Crossing
miles: 83
chains: 11
- type: minorBridge
name: Farm Bridge
position: over
category: road
miles: 83
chains: 28
- type: crossing
name: Gambols Farm Crossing
kind: uwc
miles: 83
chains: 57
- type: minorBridge
name: Black Dog Road
roadName: B4696
category: road
position: over
miles: 84
chains: 25
- type: crossing
kind: uwc
name: Gryphon Lodge Crossing
miles: 84
chains: 66
- type: minorBridge
position: under
category: stream
miles: 84
chains: 22
- type: minorBridge
position: over
name: Station Road
roadName: B4040
category: road
miles: 85
chains: 36
- type: siteof
name: Minety & Ashton Keynes
description: Former station
miles: 85
chains: 37
- type: crossing
kind: foot
name: Minety No.44 Foot Crossing
miles: 85
chains: 62
- type: crossing
kind: foot
name: Minety No.6 Foot Crossing
miles: 86
chains: 06
- type: minorBridge
nam: Askew Bridge
category: road
position: under
miles: 86
chains: 18
- type: crossing
kind: foot
name: Minety No.3 Foot Crossing
miles: 86
chains: 23
- type: minorBridge
position: under
category: road
name: Minety Moor
miles: 86
chains: 36
- type: crossing
kind: foot
name: Minety No.5 Foot Crossing
miles: 86
chains: 42
- type: crossing
kind: CCTV
name: Minety LC
description: CCTV by TVSC (LC Workstation)
miles: 86
chains: 74
- type: crossing
kind: foot
name: Minety No.26 Foot Crossing
miles: 87
chains: 4
- type: crossing
kind: foot
name: Minety No.26 Foot Crossing
miles: 87
chains: 31
- type: minorBridge
position: under
category: road
name: Slurt Bridge
miles: 87
chains: 63
- type: minorBridge
position: under
category: stream
name: Swill Brook
miles: 88
chains: 5
- type: crossing
kind: foot
name: Oaksey No.5 Foot Crossing
miles: 88
chains: 31
- type: minorBridge
position: over
name: Oaksey Road
category: road
miles: 88
chains: 37
- type: crossing
name: Oaksey No.4 Foot Crossing
kind: foot
miles: 88
chains: 56
- type: minorBridge
position: under
category: road
miles: 88
chains: 77
- type: crossing
name: West End Farm Foot Crossing
kind: foot
miles: 89
chains: 29
- type: minorBridge
name: Poole Keynes
position: under
category: road
miles: 89
chains: 30
- type: crossing
name: Kemble Wick Foot Crossing
kind: foot
miles: 89
chains: 59
- type: minorBridge
name: Wick Bridge
position: over
category: road
miles: 90
chains: 3
- type: tunnel
tunnelType: whole
name: Kemble Tunnel
length: 0mi 409yd
miles: 90
chains: 50
- type: crossovers
name: Kemble Jn
miles: 90
chains: 65
- type: junction
diverges: left
direction: down
description: Up Kemble Siding (Former platform)
miles: 90
chains: 74
name: Kemble GF
- type: station
name: Kemble
miles: 90
chains: 79
- type: minorBridge
name: Windmill/Tarlton Road
position: under
category: road
miles: 91
chains: 28
- type: minorBridge
name: Tetbury Road
position: under
roadName: A433
category: aroad
miles: 91
chains: 60
- type: crossing
kind: foot
name: Old Quarry Foot Crossing
miles: 91
chains: 77
- type: minorBridge
position: under
category: stream
name: Thames & Severn Canal
description: Disused Canal
miles: 92
chains: 67
- type: minorBridge
name: Coates
description: to Tarlton Road
category: road
position: under
miles: 92
chains: 77
- type: crossing
kind: foot
name: Coates Tunnel House Foot Crossing
miles: 93
chains: 21
- type: minorBridge
position: under
miles: 93
chains: 42
- type: minorBridge
position: over
miles: 93
chains: 66
- type: signallerChange
from: TVSC Swindon WS (SW)
to: Gloucester PSB Panel C (G)
miles: 93
chains: 79
- type: minorBridge
position: over
miles: 94
chains: 4
- type: minorBridge
name: Hailey Farm
position: over
miles: 94
chains: 40
- type: tunnel
tunnelType: whole
name: Sapperton Short Tunnel
length: 0mi 352yd
miles: 94
chains: 58
- type: tunnel
tunnelType: whole
name: Sapperton Long Tunnel
length: 1mi 104yd
miles: 95
chains: 40
- type: crossing
kind: foot
name: Frampton Common Foot Crossing
miles: 96
chains: 5
- type: crossing
kind: OMSL
name: Frampton Level Crossing
miles: 96
chains: 32
- type: crossing
kins: foot
name: Frampton Mansell Foot Crossing
miles: 96
chains: 43
- type: bridge
position: under
name: Frampton Mansell Viaduct
miles: 96
chians: 57
- type: minorBridge
position: under
category: road
name: Lower Manor
miles: 96
chains: 65
- type: minorBridge
position: over
miles: 97
chains: 4
- type: minorBridge
name: Marley Lane
position: over
category: road
miles: 97
chains: 39
- type: crossing
kind: foot
name: Chalford Foot Crossing
miles: 97
chains: 52
- type: bridge
name: Chalford Viaduct
position: under
miles: 97
chains: 61
- type: bridge
name: Cowcombe Hill
roadName: A419
category: aroad
position: over
miles: 98
chains: 4
- type: minorBridge
name: Chalford Bottom
position: under
miles: 98
chains: 36
- type: crossing
kind: foot
name: Hampton Road Foot Crossing
miles: 98
chains: 53
- type: crossing
name: St. Mary's Level Crossing
kind: MCG
miles: 98
chains: 64
- type: crossing
kind: foot
name: Brimscombe Foot Crossing
miles: 99
chains: 22
- type: minorBridge
name: Knap Lane
position: under
category: road
miles: 99
chains: 34
- type: bridge
name: Bourne Viaduct
position: under
miles: 99
chains: 51
- type: minorBridge
name: Brimscombe Hill
position: over
category: road
miles: 99
chains: 76
- type: minorBridge
name: Orchard Lane
position: under
category: road
miles: 100
chains: 12
- type: crossing
kind: foot
name: Bagpath Foot Crossing
miles: 100
chains: 37
- type: crrossing
kind: MSL
name: Ham Mill Foot Crossing
miles: 100
chains: 63
- type: crossing
name: Thrupp Foot Crossing
kind: foot
miles: 100
chains: 75
- type: crossing
kind: foot
name: Butterrow Foot Crossing
miles: 101
chains: 21
- type: crossing
kind: MSL
name: Bowbridge Foot Crossing
miles: 101
chains: 36
- type: minorBridge
name: Butterrow Hill
position: over
category: road
miles: 101
chains: 44
- type: bridge
name: Capels Viaduct
position: under
category: stream
description: Also crosses A419
miles: 101
chains: 66
- type: station
name: Stroud
miles: 102
chains: 13
- type: bridge
name: Watts Viaduct
roadName: A46
category: aroad
position: under
miles: 102
chains: 19
- type: bridge
name: Stratford Viaduct
position: under
miles: 102
chains: 32
- type: crossing
kind: OMSL
name: Gannicox Foot Crossing
miles: 102
chains: 50
- type: minorBridge
name: Footbridge
position: over
category: foot
miles: 102
chains: 65
- type: bridge
category: aroad
position: under
roadName: A4171
miles: 103
chains: 3
- type: minorBridge
position: under
miles: 103
chains: 11
- type: minorBridge
position: over
category: road
name: Cashes Green Road
miles: 103
chains: 21
- type: crossing
kind: MSL
name: Ebley Crossing
miles: 103
chains: 49
- type: minorBridge
name: Foxmoor Lane
position: under
category: road
miles: 103
chains: 41
- type: minorBridge
position: under
miles: 104
chains: 40
- type: minorBridge
position: over
miles: 104
chains: 45
- type: minorBridge
name: Brown's Lane
position: over
miles: 104
chains: 47
- type: crossing
kind: foot
name: Stonehouse 26 Foot Crossing
miles: 104
chains: 63
- type: station
name: Stonehouse
miles: 104
chains: 74
- type: minorBridge
name: Queen's Road
position: under
category: road
miles: 104
chains: 79
- type: crossing
kind: MSL
name: Globe Inn Foot Crossing
miles: 105
chains: 10
- type: minorBridge
name: Gloucester Road
roadName: B4008
position: under
miles: 105
chains: 17
- type: bridge
name: Oldends Lane
position: under
category: road
miles: 105
chains: 35
- type: crossing
category: foot
name: Little Australia Foot Crossing
miles: 105
chains: 56
- type: minorBridge
position: under
miles: 105
chains: 64
- type: minorBridge
name: Black Bridge
position: over
miles: 106
chains: 13
- type: minorBridge
name: Gloucester Road
roadName: B4008
position: over
miles: 106
chains: 60
- type: junction
name: Standish Jn
description: Up to Gloucester, Dn to Bristol
miles: 106
chains: 74
goto: 2420
entryPoint: standish-jn

View File

@@ -1,5 +1,5 @@
routeStart: Wootton Bassett Junction routeStart: Wootton Bassett Jn
routeEnd: Stoke Gifford Junction routeEnd: Stoke Gifford Jn
routeId: 0240 routeId: 0240
updated: 2026-02-11 updated: 2026-02-11
checked: 2026-02-11 checked: 2026-02-11
@@ -14,14 +14,16 @@ elecEnd:
routeDetail: routeDetail:
- type: continues - type: continues
routeName: Reading - Bristol TM routeName: Reading - Bristol TM
entryPoint: wootton-bassett-junction entryPoint: wootton-bassett-jn
routeId: '0002' routeId: '0002'
- type: junction - type: junction
diverges: right diverges: right
direction: down direction: down
name: Wootton Basset Junction name: Wootton Basset Jn
description: to Chippenham & Bristol via Bath description: to Chippenham & Bristol via Bath
goto: "0002"
entryPoint: wootton-bassett-jn
miles: 83 miles: 83
chains: 7 chains: 7
@@ -486,7 +488,7 @@ routeDetail:
- type: junction - type: junction
diverges: left diverges: left
direction: up direction: up
name: Westerleigh Junction name: Westerleigh Jn
miles: 107 miles: 107
chains: 14 chains: 14
description: Up/Dn Charfield towards Gloucester description: Up/Dn Charfield towards Gloucester
@@ -614,7 +616,7 @@ routeDetail:
chains: 14 chains: 14
- type: crossovers - type: crossovers
name: Stoke Gifford East Junction name: Stoke Gifford East Jn
miles: 111 miles: 111
chains: 20 chains: 20
@@ -639,7 +641,7 @@ routeDetail:
chains: 77 chains: 77
- type: junction - type: junction
name: Stoke Gifford No.1 Junction name: Stoke Gifford No.1 Jn
diverges: right diverges: right
direction: down direction: down
description: Up/Dn Filton & Bristol TM description: Up/Dn Filton & Bristol TM

View File

@@ -1,8 +1,8 @@
routeStart: Westerleigh Junction routeStart: Westerleigh Jn
routeEnd: Gloucester routeEnd: Gloucester
routeId: 2420 routeId: 2420
updated: 2026-02-11 updated: 2026-02-11
checked: 2026-02-11 checked:
signallerStart: TVSC Swindon WS signallerStart: TVSC Swindon WS
signallerEnd: Gloucester PSB signallerEnd: Gloucester PSB
elecStart: elecStart: