Merge pull request #21 from PyroNicampt/poi_system

PoI System
This commit is contained in:
Pyro Nicampt authored and GitHub committed 2024-12-28 22:13:25 -06:00
commit c6fb27f690
9 files changed
+6525 -6228

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
'use strict';
export const gradeColors = {
grade_flat: '#fff',
grade_0: '#f4f7cd',
grade_1: '#f8ff99',
grade_2: '#edfc1b',
grade_3: '#fcb520',
grade_4: '#f07837',
grade_5: '#e66441',
grade_6: '#ce3f57',
grade_7: '#c33577',
grade_8: '#a3008d',
grade_9: '#690097',
}
+59 -40
View File
@@ -18,10 +18,10 @@
<div id="mapNavigator">
<svg id="map" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 10000 10000">
<style>
.sign{
transform: scale(var(--signScale));
.fixedScale{
transform: scale(var(--markerScale));
}
.sign, .rail, .signText{
.sign, .rail, .signText, .poi{
cursor: default;
}
.signText{
@@ -105,84 +105,103 @@
.gradeSign.grade_9{
fill: var(--grade_9);
}
.cullThreshold_0{
display: var(--cullThreshold_state_0);
}
.cullThreshold_1{
display: var(--cullThreshold_state_1);
}
.cullThreshold_2{
display: var(--cullThreshold_state_2);
}
.cullThreshold_3{
display: var(--cullThreshold_state_3);
}
.cullThreshold_4{
display: var(--cullThreshold_state_4);
}
.cullThreshold_5{
display: var(--cullThreshold_state_5);
}
.cullThreshold_6{
display: var(--cullThreshold_state_6);
}
</style>
<style id="zoomStyle"></style>
<defs>
<g id="gradeArrow" transform="scale(10)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="gradeArrow" transform="scale(30)" viewBox="0 0 10 10" >
<path d="M 0 -7 L 3.8 4 L -3.8 4 z" fill="black"/>
<path d="M 0 -5 L 3 4 L 0 5 L -3 4 z"/>
</g>
<g id="speedSign" transform="scale(15)" viewBox="0 0 10 10" refX="5" refY="5" style="fill:#fff; stroke:#e73819">
<g id="speedSign" transform="scale(15)" viewBox="0 0 10 10" style="fill:#fff; stroke:#e73819">
<circle cx="0" cy="0" r="3"/>
</g>
<g id="speedSignWarning" transform="scale(15)" viewBox="0 0 10 10" refX="5" refY="5" style="fill:#702012; stroke:#e73819">
<g id="speedSignWarning" transform="scale(15)" viewBox="0 0 10 10" style="fill:#702012; stroke:#e73819">
<circle cx="0" cy="0" r="3"/>
</g>
<g id="speedSign_1" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_1" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSignWarning"></use>
<text class="signText" style="fill:#fff;transform:translate(-15px, 20px)">1</text>
</g>
<g id="speedSign_2" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_2" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSignWarning"></use>
<text class="signText" style="fill:#fff;transform:translate(-15px, 20px)">2</text>
</g>
<g id="speedSign_3" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_3" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSignWarning"></use>
<text class="signText" style="fill:#fff;transform:translate(-15px, 20px)">3</text>
</g>
<g id="speedSign_4" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_4" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-15px, 20px)">4</text>
</g>
<g id="speedSign_5" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_5" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-16px, 20px)">5</text>
</g>
<g id="speedSign_6" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_6" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-15px, 20px)">6</text>
</g>
<g id="speedSign_7" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_7" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-15px, 20px)">7</text>
</g>
<g id="speedSign_8" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_8" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-16px, 20px)">8</text>
</g>
<g id="speedSign_9" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_9" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-15px, 20px)">9</text>
</g>
<g id="speedSign_10" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_10" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-35px, 20px)">10</text>
</g>
<g id="speedSign_12" transform="scale(1)" viewBox="0 0 10 10" refX="5" refY="5">
<g id="speedSign_12" transform="scale(3)" viewBox="0 0 10 10">
<use href="#speedSign"></use>
<text class="signText" style="transform:translate(-35px, 20px)">12</text>
</g>
<g id="mrk_office" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="M10 3.8l5.56 6.03h-1.66v5.2h-2.51v-3.93h-2.78v3.93h-2.51v-5.2h-1.66z" fill="#fff"></path>
</g>
<g id="mrk_water" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="M10 2c-1.02 2.01-7.08 14.38 0 14.38 7.08 0 1.02-12.46 0-14.38z" fill="#fff"></path>
</g>
<g id="mrk_coal" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="M10.75 2.98 7.85 4.02 5.64 7.39 5.74 7.54 7.08 7.06 10.14 9.03 10.47 8.6 13.67 7.4 14.65 8.03 14.94 7.21 13.65 4.97ZM7.07 7.6 4.18 8.64 1.96 12.01 3.49 15.33h6.78l.99-3.5-1.3-2.25zm6.61.47-2.9 1.04-.27.4.17.13 1.22 2.21-.91 3.48h5.88l.99-3.02-1.3-2.25z" fill="#fff"></path>
</g>
<g id="mrk_landmark" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="m11.39 1.43c-.2-.09-.42 0-.51.2L4.22 16.88c-.09.2 0 .42.2.5.2.09.42 0 .51-.2L11.59 1.93c.09-.2 0-.42-.2-.51zm.53.93-2.39 5.48c.21 0 .42 0 .62.01.2.01.41.02.61.03.2.01.4.03.6.05.2.02.39.04.59.06.19.02.39.05.58.08.19.03.38.06.57.1.09.02.18.04.28.05l2.12-2.56c-.01-.01-.02-.03-.04-.05C15.31 5.46 15.18 5.3 15.05 5.14 14.91 4.99 14.78 4.83 14.64 4.68 14.5 4.53 14.36 4.39 14.22 4.24 14.08 4.1 13.93 3.96 13.79 3.82 13.64 3.68 13.49 3.55 13.34 3.42 13.27 3.35 13.19 3.29 13.12 3.23 13.04 3.16 12.96 3.1 12.88 3.04 12.81 2.98 12.73 2.92 12.65 2.86 12.57 2.8 12.49 2.74 12.41 2.69 12.33 2.63 12.25 2.57 12.16 2.52 12.08 2.47 12 2.41 11.92 2.36Zm3.37 4.06-2.12 2.56c.1.02.19.04.29.06.19.04.37.08.55.13.18.04.37.09.55.14.18.05.36.1.54.15.18.05.36.1.53.16.18.05.35.11.53.17.18.06.35.12.53.17.17.06.35.12.52.18.35.12.69.25 1.04.37C18 10.15 17.76 9.79 17.51 9.44 17.27 9.09 17.02 8.74 16.78 8.39 16.65 8.22 16.53 8.05 16.4 7.88 16.28 7.7 16.15 7.53 16.02 7.36 15.9 7.2 15.77 7.03 15.64 6.86 15.53 6.71 15.41 6.57 15.29 6.42Z" fill="#fff"></path>
</g>
<g id="mrk_shop" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="M9.25 17.9V16.35C8.29 16.26 7.75 15.91 7.12 15.31 6.49 14.71 6.14 13.86 6.06 12.75l2.2-.49c.03.65.21 1.14.54 1.49.33.35.75.52 1.24.52.47 0 .81-.13 1.03-.4.23-.27.34-.55.34-.85 0-.39-.11-.71-.34-.94-.23-.24-.52-.46-.88-.65L8.66 10.62C7.91 10.23 7.33 9.75 6.9 9.2 6.48 8.65 6.27 7.92 6.27 7.02 6.27 6.37 6.41 5.8 6.68 5.31 6.97 4.8 7.35 4.4 7.83 4.1 8.32 3.8 8.63 3.61 9.25 3.54V2.1h1.65v1.48c.91.12 1.41.49 1.94 1.1.53.6.82 1.39.88 2.36L11.65 7.47C11.62 6.87 11.45 6.41 11.15 6.08 10.86 5.75 10.5 5.58 10.07 5.58 9.66 5.58 9.33 5.7 9.08 5.94 8.84 6.17 8.72 6.48 8.72 6.88c0 .36.11.65.32.86.21.21.51.42.88.63l1.63.86c.83.45 1.43.95 1.82 1.51.39.55.58 1.23.58 2.02 0 .6-.13 1.16-.4 1.67-.25.51-.63.95-1.12 1.3-.48.33-.84.54-1.53.63v1.4z" fill="#fff"></path>
</g>
<g id="mrk_garage" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="M10 2.88 2.98 6.42 2.98 15.1 5.53 15.1 5.53 8.91 14.47 8.91 14.47 15.1 17.02 15.1 17.02 6.42 10 2.88z" fill="#fff"></path>
</g>
<g id="mrk_service" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="m8.92 1.99q3.29 0 4.68 1.13 1.39 1.1 1.39 2.74 0 2.06-1.78 3.36-.67.5-1.63.91l-.38.17q-.17.07-.34 1.01-.14.91-.14 1.32-.12.12-.7.29-.55.14-.94.14-.36 0-.55-.05-.26-.43-.26-1.87 0-1.44.12-1.85 3.79-.91 3.79-3.07 0-1.87-3.46-1.87-1.22 0-1.78.24-.14-.24-.14-1.01 0-.77.22-1.3.65-.29 1.9-.29zm-.7 15.5q-.46-.48-.46-1.15 0-.67.46-1.13.48-.48 1.15-.48.67 0 1.13.48.48.46.48 1.13 0 .67-.48 1.15-.46.46-1.13.46-.67 0-1.15-.46z" fill="#fff"></path>
</g>
<g id="mrk_service_repair" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="m12.88 2.82c-.1.01-.2.05-.28.13l-2.19 2.19c-.15.16-.17.39-.03.53l1.12 1.12c.29-.29.37.07.57.58l-1.61 1.6 1.77 1.72 1.7-1.7c.44.03.82-.06.99.11.22.22.19.59-.06.85l-.02.02c1.48 1.26 3.85-1.11 2.59-2.59l-.02.02c-.25.25-.63.28-.85.06-.3-.3.23-1.31-.61-2.15l-.1-.1c-.73-.74-2.07-.7-1.6-1.18l-1.12-1.12c-.06-.06-.16-.09-.25-.09zM5.63 3.68c-.28 0-.55.05-.83.14l2.02 2.02-1.85 1.86-2.02-2.02c-.72 2.23 1.45 4.34 3.67 3.55l7.27 7.27c.46.47 1.22.47 1.71-.02.49-.49.5-1.25.03-1.72L8.36 7.49c.69-1.94-.84-3.84-2.73-3.81zm2.41 7.72-3.36 3.35c-.47.47-.47 1.23.02 1.72.49.49 1.25.49 1.72.02l3.38-3.38z" fill="#fff"></path>
</g>
<g id="mrk_service_diesel" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="m12.67 2.93c-.5-.01-1 .09-1.46.31L9.86 3.88 9.76 3.66 7.64 4.67 7.18 4.02C7.09 3.89 6.92 3.86 6.79 3.95L5.55 4.8C5.43 4.89 5.4 5.07 5.48 5.2L5.87 5.75 5.51 6.22 2.7 10.29c-.2.3-.18.7.06.97-.4.74-.49 1.54-.3 2.26.22.86.77 1.6 1.5 2.16 1.46 1.12 3.68 1.56 5.63.5 1.07-.59 2.19-.79 2.99-.64.8.14 1.26.52 1.39 1.32.05.33.36.55.69.5.33-.05.55-.36.5-.69-.2-1.27-1.2-2.1-2.36-2.31-1.16-.21-2.51.08-3.78.77C7.53 15.95 5.8 15.6 4.69 14.74 4.14 14.32 3.76 13.77 3.62 13.23 3.52 12.83 3.53 12.42 3.73 11.99l1.39.96c.81.56 1.93.36 2.49-.46L10.41 8.46 9.88 5.6 10.53 5.29 10.42 5.05 11.76 4.42C12.2 4.21 12.7 4.17 13.17 4.32L16.71 5.44 17.1 4.2 13.56 3.08C13.27 2.99 12.97 2.94 12.67 2.93Zm4.24 3.31c-.39.63-2.7 4.48 0 4.48 2.7 0 .39-3.88 0-4.48zM6.91 7.47 8.22 7.92 7.2 8.58c-.04.03-.08.06-.11.11l-1.55 2.46c-.1.16-.05.38.11.48.16.1.38.05.48-.11L7.64 9.12 8.94 8.29c.24.29.25.71.02 1.03L7.44 11.52C6.92 12.27 5.93 12.48 5.22 11.99L4.36 11.4Z" fill="#fff"></path>
</g>
<g id="mrk_service_charger" transform="scale(20)" viewBox="0 0 20 20">
<circle r="10"></circle>
<path transform="translate(-10 -10)" d="m7.96 2.6h4.56l-1.97 5.8h3.02L8.61 18.36 9.6 10.25H7.26Z" fill="#fff"></path>
</g>
</defs>
</svg>
<svg id="mapMarkers" xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 10000 10000">
@@ -196,13 +215,13 @@
</div>
</div>
<div id="legend" style="display: flex;">
<div style="display:flex; flex-direction:column; width: 400px;">
<div id="legendContents" style="display:flex; flex-direction:column; width: 400px;">
<div class="panel">
Welcome to the WIP community map of <a href="https://www.derailvalley.com/" style="white-space:nowrap;">Derail Valley</a>, a resource for documenting and displaying all tracks and points of interest.
<hr>
Hover over tracks and objects for detailed information.
</div>
<div class="panel">
<div class="panel" style="width:330px">
<h3>Key</h3>
<hr>
<div id="legendKey"></div>
+273 -59
View File
@@ -3,6 +3,7 @@
import * as Vector from './js/vectorlib.js';
import * as Bezier from './js/bezierlib.js';
import * as Utils from './js/utillib.js';
import * as Config from './config.js';
// CONFIG
const bezierGradeResolution = 80;
@@ -57,6 +58,14 @@ map.appendChild(map_rails);
//map_markers.setAttribute('id', 'map_markers');
//map.appendChild(map_markers);
const map_markers = document.getElementById('mapMarkers');
const poiLayers = {
container: document.createElementNS(svgns, 'g'),
stations: document.createElementNS(svgns, 'g'),
service: document.createElementNS(svgns, 'g'),
features: document.createElementNS(svgns, 'g'),
landmarks: document.createElementNS(svgns, 'g')
};
let mapData = [];
let trackNameCounting = {};
@@ -67,8 +76,17 @@ let markers = [];
let currentMapNav = {};
let previousMapScale = -1;
let MapMatrix = {};
document.addEventListener('DOMContentLoaded', async () => {
let dynamicStyles = [];
for(let i=0; i<scaleCullThresholds.length; i++){
dynamicStyles.push(`.maxZoomCull_${i}{display:var(--maxZoomCull_state_${i});}`);
dynamicStyles.push(`.minZoomCull_${i}{display:var(--minZoomCull_state_${i});}`);
}
document.getElementById('zoomStyle').innerHTML = dynamicStyles.join('\n');
await loadTrackData('trackdata_dv.json');
await loadPoiData('poi_dv.json');
mapScrollSetup();
});
@@ -78,6 +96,21 @@ async function loadTrackData(file){
fillSvg();
}
async function loadPoiData(file){
poiData = await (await fetch(new Request(file))).json();
for(let layerIdx in poiLayers){
poiLayers[layerIdx].setAttribute('id', 'poi_'+layerIdx);
if(layerIdx == 'container') continue;
poiLayers.container.appendChild(poiLayers[layerIdx]);
}
map_markers.appendChild(poiLayers.container);
for(let poi of poiData){
addPoi(poi);
}
}
/** Handling for the map scrolling and zooming */
function mapScrollSetup(){
let mapNav = {x:currentMapNav.x, y:currentMapNav.y, scale:currentMapNav.scale};
@@ -149,10 +182,11 @@ function updateMapview(navData = {x:0, y:0, scale:1}){
}
}
map_rails.setAttribute('stroke-width', Utils.clamp(trackWidth.base/navData.scale, trackWidth.min, trackWidth.max));
styleRoot.style.setProperty('--signScale', Utils.clamp(signSize.base/navData.scale, signSize.min, signSize.max));
styleRoot.style.setProperty('--markerScale', 1/navData.scale);
if(dirtyScale){
for(let i=0; i<scaleCullThresholds.length; i++){
styleRoot.style.setProperty(`--cullThreshold_state_${i}`, navData.scale >= scaleCullThresholds[i].scale ? 'initial' : 'none')
styleRoot.style.setProperty(`--minZoomCull_state_${i}`, navData.scale >= scaleCullThresholds[i].scale ? 'initial' : 'none');
styleRoot.style.setProperty(`--maxZoomCull_state_${i}`, navData.scale <= scaleCullThresholds[i].scale ? 'initial' : 'none');
}
}
previousMapScale = navData.scale;
@@ -171,16 +205,27 @@ function establishDimensions(){
let maxAlt = -Infinity;
for(const obj of mapData){
for(const point of obj.points){
minX = Math.min(minX, point[0].x, point[1].x, point[2].x);
minY = Math.min(minY, point[0].z, point[1].z, point[2].z);
minAlt = Math.min(minAlt, point[0].y, point[1].y, point[2].y);
maxX = Math.max(maxX, point[0].x, point[1].x, point[2].x);
maxY = Math.max(maxY, point[0].z, point[1].z, point[2].z);
maxAlt = Math.max(maxAlt, point[0].y, point[1].y, point[2].y);
minX = Math.min(minX, point.position.x, point.h1.x, point.h2.x);
minY = Math.min(minY, point.position.z, point.h1.z, point.h2.z);
minAlt = Math.min(minAlt, point.position.y, point.h1.y, point.h2.y);
maxX = Math.max(maxX, point.position.x, point.h1.x, point.h2.x);
maxY = Math.max(maxY, point.position.z, point.h1.z, point.h2.z);
maxAlt = Math.max(maxAlt, point.position.y, point.h1.y, point.h2.y);
}
}
let width = maxX-minX;
let height = maxY-minY;
MapMatrix = {
x1: minX,
x2: maxX,
y1: minY,
y2: maxY,
width: width,
height: height,
fixY: yIn => {
return minY+maxY-yIn;
}
}
map.setAttribute('viewBox', `${minX-padding} ${minY-padding} ${width+2*padding} ${height+2*padding}`);
map_markers.setAttribute('viewBox', map.getAttribute('viewBox'));
updateMapview({
@@ -193,9 +238,9 @@ function establishDimensions(){
// Flip the z coordinate so the map doesn't display upside-down
for(const obj of mapData){
for(const point of obj.points){
point[0].z = minY+maxY-point[0].z;
point[1].z = minY+maxY-point[1].z;
point[2].z = minY+maxY-point[2].z;
point.position.z = minY+maxY-point.position.z;
point.h1.z = minY+maxY-point.h1.z;
point.h2.z = minY+maxY-point.h2.z;
}
}
}
@@ -210,6 +255,7 @@ function fillSvg(){
}
}
sortTracks();
setTrackColorMode('Grade');
drawMarkers();
}
@@ -221,12 +267,29 @@ function drawTracks(bezierData){
}else{
trackNameCounting[bezierData.name]++;
}
let yardData = /\[(#)\]|\[(Y)\]_\[(.*?)\]_\[((.*?)-(.*?)-(.*?))\]/.exec(bezierData.name);
if(yardData){
if(yardData[1]){ // track is [#], thus in yard limits, but not a specific designated yard.
bezierData.isYard = true;
}else if(yardData[2]){ // track is [Y], and is a specific yard.
bezierData.isYard = true;
bezierData.yardStation = yardData[3]; // Which station the track belongs to
bezierData.yardDesignation = yardData[4]; // Full yard designation, used on signs
bezierData.yardName = yardData[5]; // A yard, B yard, C yard, etc.
bezierData.yardSidingNumber = yardData[6]; // Which siding within the yard
bezierData.yardUsage = yardData[7]; // Outbound? Parking? Inbound? Loading? That's this.
}
}else if(/Turntable Track/.test(bezierData.name)){
bezierData.isTurntable = true;
}else if(/\[track (diverging|through)\]/.test(bezierData.name)){
bezierData.isPoint = true;
}
for(let i=0; i+1<bezierData.points.length; i++){
const bezStart = bezierData.points[i][0];
const bezHandle1 = bezierData.points[i][2];
const bezHandle2 = bezierData.points[i+1][1];
const bezEnd = bezierData.points[i+1][0];
let newBezier = document.createElementNS(svgns, 'path');
const bezStart = bezierData.points[i].position;
const bezHandle1 = bezierData.points[i].h2;
const bezHandle2 = bezierData.points[i+1].h1;
const bezEnd = bezierData.points[i+1].position;
bezierData.points[i].element = document.createElementNS(svgns, 'path');
let genPath = 'M ';
genPath += `${bezStart.x} ${bezStart.z} `;
genPath += `C ${bezHandle1.x} ${bezHandle1.z} ${bezHandle2.x} ${bezHandle2.z} ${bezEnd.x} ${bezEnd.z} `;
@@ -235,18 +298,20 @@ function drawTracks(bezierData){
bezierData.points[i].bezLength = Bezier.estimateLength(bezStart, bezHandle1, bezHandle2, bezEnd, bezierLengthResolution);
bezierData.points[i].curvature = Bezier.estimateCurvature(bezStart, bezHandle1, bezHandle2, bezEnd, bezierCurvatureResolution);
bezierData.points[i].postedSpeed = Utils.radiusToSpeed(1/bezierData.points[i].curvature);
newBezier.setAttribute('d', genPath);
if(bezierData.isYard || bezierData.isTurntable) bezierData.points[i].postedSpeed = Math.min(bezierData.points[i].postedSpeed, 50);
bezierData.points[i].element.setAttribute('d', genPath);
newBezier.classList.add('rail');
newBezier.classList.add(bezierData.points[i].gradeClass != null ? 'grade_'+bezierData.points[i].gradeClass : 'grade_flat');
bezierData.points[i].element.classList.add('rail');
//bezierData.points[i].element.setAttribute('stroke', Config.gradeColors[bezierData.points[i].gradeClass ? 'grade_'+bezierData.points[i].gradeClass : 'grade_flat']);
//bezierData.points[i].element.classList.add(bezierData.points[i].gradeClass != null ? 'grade_'+bezierData.points[i].gradeClass : 'grade_flat');
//newBezier.setAttribute('stroke', Utils.rgba2hex(bezierData.points[i].grade*50*0,(bezStart.y-113)/(252-113),bezierData.points[i].bezLength*0.01*0,1.0));
//newBezier.setAttribute('stroke', Utils.rgba2hex((1/bezierData.points[i].curvature) * 100,0,0,1.0));
//newBezier.setAttribute('stroke', trackCol);
//newBezier.setAttribute('data-grade', bezierData.points[i].grade);
//newBezier.setAttribute('data-length', bezierData.points[i].bezLength);
//newBezier.setAttribute('data-maxradius', 1/bezierData.points[i].curvature);
tracks.push([(bezStart.y+bezEnd.y)*0.5, newBezier]);
//bezierData.points[i].element.setAttribute('stroke', Utils.rgba2hex(bezierData.points[i].grade*50*0,(bezStart.y-113)/(252-113),bezierData.points[i].bezLength*0.01*0,1.0));
//bezierData.points[i].element.setAttribute('stroke', Utils.rgba2hex((1/bezierData.points[i].curvature) * 100,0,0,1.0));
//bezierData.points[i].element.setAttribute('stroke', trackCol);
//bezierData.points[i].element.setAttribute('data-grade', bezierData.points[i].grade);
//bezierData.points[i].element.setAttribute('data-length', bezierData.points[i].bezLength);
//bezierData.points[i].element.setAttribute('data-maxradius', 1/bezierData.points[i].curvature);
tracks.push([(bezStart.y+bezEnd.y)*0.5, bezierData.points[i].element]);
// Curve tooltip
let title = document.createElementNS(svgns, 'title');
@@ -258,7 +323,7 @@ function drawTracks(bezierData){
`Length: ${Math.round(bezierData.points[i].bezLength*10)/10} meters`,
`Altitude: ${Math.round((bezStart.y+bezEnd.y)*0.5)} meters`,
].join('\n');
newBezier.appendChild(title);
bezierData.points[i].element.appendChild(title);
}
// Add Signage
@@ -283,17 +348,17 @@ function drawTracks(bezierData){
}else{
//Grade Signs
if(trackZoneData.gradeClass != bezierData.points[i].gradeClass || trackZoneData.gradeDirection != Math.sign(bezierData.points[i].grade) || trackZoneData.gradeSectionLength > maxSectionLength || zI > 0){
if(trackZoneData.gradeClass != null){
if(trackZoneData.gradeClass != 'flat'){
let offset = Math.floor((trackZoneData.gradeCount+1)/2)+1;
let center = trackZoneData.gradeCount % 2 ? 1 : 0.5;
let b1 = bezierData.points[(i+zI)-offset][0];
let b2 = bezierData.points[(i+zI)-offset][2];
let b3 = bezierData.points[(i+zI)+1-offset][1];
let b4 = bezierData.points[(i+zI)+1-offset][0];
let b1 = bezierData.points[(i+zI)-offset].position;
let b2 = bezierData.points[(i+zI)-offset].h2;
let b3 = bezierData.points[(i+zI)+1-offset].h1;
let b4 = bezierData.points[(i+zI)+1-offset].position;
markers.push({
type: 'grade',
value: bezierData.points[(i+zI)-offset].grade,
class: 'grade_'+trackZoneData.gradeClass,
gradeClass: trackZoneData.gradeClass,
position: Bezier.evaluatePoint(b1, b2, b3, b4, center),
sectionLength: trackZoneData.gradeSectionLength,
cullLevel: Math.round(scaleCullThresholds.length-1-trackZoneData.gradeSectionLength/scaleCullBaseSectionLength),
@@ -311,10 +376,10 @@ function drawTracks(bezierData){
if(trackZoneData.speed != bezierData.points[i].postedSpeed || trackZoneData.speedSectionLength > maxSectionLength || zI > 0){
let offset = Math.floor((trackZoneData.speedCount+1)/2)+1;
let center = trackZoneData.speedCount % 2 ? 0.75 : 0.25;
let b1 = bezierData.points[(i+zI)-offset][0];
let b2 = bezierData.points[(i+zI)-offset][2];
let b3 = bezierData.points[(i+zI)+1-offset][1];
let b4 = bezierData.points[(i+zI)+1-offset][0];
let b1 = bezierData.points[(i+zI)-offset].position;
let b2 = bezierData.points[(i+zI)-offset].h2;
let b3 = bezierData.points[(i+zI)+1-offset].h1;
let b4 = bezierData.points[(i+zI)+1-offset].position;
let cullLevel = Math.round(scaleCullThresholds.length-1-trackZoneData.gradeSectionLength/scaleCullBaseSectionLengthSpeedboard);
let speedDelta = Math.max(0,
(bezierData.points[i].postedSpeed != null && bezierData.points[i].postedSpeed < 100) ? bezierData.points[i].postedSpeed-trackZoneData.speed : 0,
@@ -330,7 +395,7 @@ function drawTracks(bezierData){
value: trackZoneData.speed,
position: Bezier.evaluatePoint(b1, b2, b3, b4, center),
sectionLength: trackZoneData.speedSectionLength,
cullLevel: cullLevel,
cullLevel: cullLevel == 1 ? 2 : cullLevel,
tangent: Bezier.evaluateVelocity(b1, b2, b3, b4, center)
});
resetTzdSpeed();
@@ -353,45 +418,194 @@ function sortTracks(){
}
}
function setTrackColorMode(mode){
let modeFunction = null;
switch(mode){
case 'Track Type':
modeFunction = (section, curve) => {
let finalColor = '#aaa';
if(curve.isYard && curve.yardDesignation) finalColor = '#4bf';
else if(curve.isYard) finalColor = '#4fb';
else if(curve.isPoint) finalColor = '#fb4';
else if(curve.isTurntable) finalColor = '#b4f';
section.element.setAttribute('stroke', finalColor);
}
break;
case 'Grade':
modeFunction = section => {
section.element.setAttribute('stroke', Config.gradeColors['grade_'+section.gradeClass]);
};
break;
default:
modeFunction = section => {
section.element.setAttribute('stroke', '#fff');
}
break;
}
if(modeFunction !== null){
for(let curve of mapData){
for(let section of curve.points){
if(!section.element) continue;
modeFunction(section, curve);
}
}
}
}
/** Create the signage */
function drawMarkers(){
const signage_container = document.createElementNS(svgns, 'g');
const gradeSigns = document.createElementNS(svgns, 'g');
gradeSigns.setAttribute('id', 'grade_signs');
map_markers.appendChild(gradeSigns);
const speedSigns = document.createElementNS(svgns, 'g');
speedSigns.setAttribute('id', 'speed_signs');
map_markers.appendChild(speedSigns);
signage_container.setAttribute('id', 'signage_container');
gradeSigns.setAttribute('id', 'signage_grade');
speedSigns.setAttribute('id', 'signage_speed');
map_markers.appendChild(signage_container);
signage_container.appendChild(gradeSigns);
signage_container.appendChild(speedSigns);
for(const markerData of markers){
//if(markerData.skip) continue;
let marker = document.createElementNS(svgns, 'g');
let markerElement = document.createElementNS(svgns, 'g');
let markerImg = document.createElementNS(svgns, 'use');
let title = document.createElementNS(svgns, 'title');
marker.appendChild(markerImg);
marker.appendChild(title);
marker.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
let markerTooltip = document.createElementNS(svgns, 'title');
markerElement.appendChild(markerImg);
markerElement.appendChild(markerTooltip);
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
markerImg.classList.add('fixedScale');
// Grade signs
if(markerData.type == 'grade'){
markerImg.setAttribute('href', '#gradeArrow');
markerImg.classList.add('sign', 'gradeSign');
if(markerData.class) markerImg.classList.add(markerData.class);
markerImg.setAttribute('fill', Config.gradeColors['grade_'+markerData.gradeClass]);
const tanLen = Math.sqrt(markerData.tangent.x*markerData.tangent.x + markerData.tangent.z*markerData.tangent.z) * Math.sign(markerData.tangent.y);
const rot = Math.atan2(markerData.tangent.x/tanLen, -markerData.tangent.z/tanLen) * (180/Math.PI);
marker.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z}) rotate(${rot})`);
title.innerHTML = `${Math.round(markerData.value*1000)/10}% Grade\nSection Length: ${markerData.sectionLength.toFixed(1)} meters`;
gradeSigns.appendChild(marker);
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z}) rotate(${rot})`);
markerTooltip.innerHTML = `${Math.round(markerData.value*1000)/10}% Grade\nSection Length: ${markerData.sectionLength.toFixed(1)} meters`;
gradeSigns.appendChild(markerElement);
// Speed Signs
}else if(markerData.type == 'speed'){
markerImg.setAttribute('href', `#speedSign_${Math.round(markerData.value/10)}`);
markerImg.classList.add('sign', 'speedSign');
title.innerHTML = `${Math.round(markerData.value)} km/h\nSection Length: ${markerData.sectionLength.toFixed(1)} meters`;
/*let offset = Vector.normalize({x:markerData.tangent.z, y:0, z:-markerData.tangent.x});
marker.setAttribute('transform', `translate(${markerData.position.x + offset.x*100} ${markerData.position.z + offset.z*50})`);*/
marker.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
speedSigns.appendChild(marker);
markerTooltip.innerHTML = `${Math.round(markerData.value)} km/h\nSection Length: ${markerData.sectionLength.toFixed(1)} meters`;
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
speedSigns.appendChild(markerElement);
}
if(markerData.cullLevel){
marker.classList.add(`cullThreshold_${Math.min(scaleCullThresholds.length-1, markerData.cullLevel)}`);
markerElement.classList.add(`minZoomCull_${Math.min(scaleCullThresholds.length-1, markerData.cullLevel)}`);
}
}
}
function addPoi(poi, level = 0){
let poiElement = document.createElementNS(svgns, 'g');
let poiDisplay = document.createElementNS(svgns, 'g');
let poiIcon = document.createElementNS(svgns, poi.type == 'station' ? 'text' : 'use');
let poiTooltip = document.createElementNS(svgns, 'title');
poiElement.appendChild(poiDisplay);
poiDisplay.appendChild(poiIcon);
poiElement.appendChild(poiTooltip);
poiElement.setAttribute('transform', `translate(${poi.position.x} ${MapMatrix.fixY(poi.position.z)})`);
poiElement.classList.add('poi');
poiDisplay.classList.add('fixedScale');
if(level > 0) poiElement.classList.add('minZoomCull_2');
switch(poi.type){
case 'station':
poiDisplay.classList.remove('fixedScale');
poiElement.setAttribute('fill', poi.color ?? '#fff');
poiTooltip.innerHTML = poi.name;
poiIcon.innerHTML = poi.shorthand;
poiIcon.setAttribute('style', `font-size:400px; stroke:${poi.stroke ?? '#000'}; stroke-width:40px; paint-order:stroke; text-anchor:middle;`);
poiLayers.stations.prepend(poiElement);
break;
case 'office':
poiIcon.setAttribute('href', '#mrk_office');
if(poi.military){
poiDisplay.setAttribute('fill', '#978e47');
poiTooltip.innerHTML = 'Military Office';
}else if(poi.museum){
poiDisplay.setAttribute('fill', '#b44');
poiTooltip.innerHTML = 'Museum Office';
}else{
poiDisplay.setAttribute('fill', '#c4693e');
poiTooltip.innerHTML = 'Station Office';
}
poiLayers.service.prepend(poiElement);
break;
case 'coal':
poiIcon.setAttribute('href', '#mrk_coal');
poiDisplay.setAttribute('fill', '#202020');
poiTooltip.innerHTML = 'Coal Tower';
poiLayers.service.prepend(poiElement);
break;
case 'water':
poiIcon.setAttribute('href', '#mrk_water');
poiDisplay.setAttribute('fill', '#3fa5ff');
poiTooltip.innerHTML = 'Water Tower';
poiLayers.service.prepend(poiElement);
break;
case 'garage':
poiIcon.setAttribute('href', '#mrk_garage');
poiDisplay.setAttribute('fill', '#8b5dd7');
poiTooltip.innerHTML = poi.name ?? 'Unknown Garage';
poiLayers.service.prepend(poiElement);
poiElement.classList.add('minZoomCull_1');
break;
case 'landmark':
poiIcon.setAttribute('href', '#mrk_landmark');
poiDisplay.setAttribute('fill', '#af5757');
poiTooltip.innerHTML = poi.name ?? 'Unknown Landmark';
poiLayers.landmarks.prepend(poiElement);
poiElement.classList.add('minZoomCull_1');
break;
case 'shop':
poiIcon.setAttribute('href', '#mrk_shop');
poiDisplay.setAttribute('fill', '#4f54e9');
poiTooltip.innerHTML = 'Shop';
poiLayers.service.prepend(poiElement);
poiElement.classList.add('minZoomCull_1');
break;
case 'service':
let serviceTypes = [];
if(poi.repair) serviceTypes.push('Repair');
if(poi.diesel) serviceTypes.push('Diesel');
if(poi.charger) serviceTypes.push('Charger');
if(serviceTypes.length == 0){
poiIcon.setAttribute('href', '#mrk_service');
poiDisplay.setAttribute('fill', '#239a96');
poiTooltip.innerHTML = 'Unknown Service';
}else{
poiIcon.setAttribute('href', '#mrk_service_'+serviceTypes[0].toLowerCase());
poiDisplay.setAttribute('fill', '#239a96');
let bumpOffset = -200*(serviceTypes.length-1);
poiIcon.setAttribute('transform', `translate(${bumpOffset} 0)`);
poiTooltip.innerHTML = serviceTypes[0];
for(let i=1; i<serviceTypes.length; i++){
let subIcon = document.createElementNS(svgns, 'use');
subIcon.setAttribute('href', '#mrk_service_'+serviceTypes[i].toLowerCase());
subIcon.setAttribute('transform', `translate(${i*400+bumpOffset} 0)`);
poiDisplay.appendChild(subIcon);
poiTooltip.innerHTML += (i == serviceTypes.length-1 ? (serviceTypes.length == 2 ? ' & ' : ', & ') : ', ')+serviceTypes[i];
}
poiTooltip.innerHTML += ' Service';
if(serviceTypes.length > 1){
let bgrect = document.createElementNS(svgns, 'rect');
bgrect.setAttribute('width', 400*(serviceTypes.length-1));
bgrect.setAttribute('height', 400);
bgrect.setAttribute('transform', `translate(${-200*(serviceTypes.length-1)} -200)`);
poiDisplay.prepend(bgrect);
}
}
poiLayers.service.prepend(poiElement);
break;
}
if(poi.children){
for(let child of poi.children){
addPoi(child, level+1);
}
}
}
+13 -4
View File
@@ -21,9 +21,12 @@ export function estimateGrade(p1, h1, h2, p2, iterationCount = 50){
for(let i=0; i<=iterationCount; i++){
let tan = evaluateVelocity(p1, h1, h2, p2, i/iterationCount);
let newGrade = Math.abs(tan.y)/Math.sqrt(tan.x*tan.x + tan.z*tan.z);
grade = Math.max(grade, newGrade);
totalGrade += newGrade;
if(!Number.isNaN(newGrade)){
grade = Math.max(grade, newGrade);
totalGrade += newGrade;
}
}
if(!grade) return 0;
return grade;
}
@@ -59,14 +62,20 @@ export function estimateCurvature(p1, h1, h2, p2, iterationCount = 50){
let curvature = 0;
let t = 0;
let vel = {};
let totalCount = 0;
for(let i=0; i<iterationCount; i++){
t = i/iterationCount;
vel = evaluateVelocity(p1, h1, h2, p2, t);
curvature +=
let newCurvature =
Vector.length(Vector.cross(vel, evaluateAcceleration(p1, h1, h2, p2, t)))
/Math.pow(Vector.length(vel),3);
if(!Number.isNaN(newCurvature)){
curvature += newCurvature;
totalCount++;
}
}
return curvature/iterationCount;
if(!curvature) return 0.00000001;
return curvature/totalCount;
}
/** Evaluate the bezier at `t`, getting position.
+1
View File
@@ -39,6 +39,7 @@ export function gradeToClass(grade){
return gradeIncrements.length-(j+1);
}
}
return 'flat';
}
export function radiusToSpeed(radius){
+51 -17
View File
@@ -1,6 +1,7 @@
'use strict';
import * as Utils from './js/utillib.js';
import * as Config from './config.js';
let settingEntries = [
{
@@ -8,7 +9,7 @@ let settingEntries = [
id: 'toggle_signage',
state: true,
func: state =>{
document.getElementById('mapMarkers').style.display = state ? 'unset' : 'none';
document.getElementById('signage_container').style.display = state ? 'unset' : 'none';
},
children: [
{
@@ -16,7 +17,7 @@ let settingEntries = [
id: 'toggle_speedSigns',
state: true,
func: state =>{
document.getElementById('speed_signs').style.display = state ? 'unset' : 'none';
document.getElementById('signage_speed').style.display = state ? 'unset' : 'none';
},
},
{
@@ -24,11 +25,37 @@ let settingEntries = [
id: 'toggle_gradeSigns',
state: true,
func: state =>{
document.getElementById('grade_signs').style.display = state ? 'unset' : 'none';
document.getElementById('signage_grade').style.display = state ? 'unset' : 'none';
},
}
],
},
{
label: 'Points of Interest',
id: 'toggle_poi',
state: true,
func: state => {
document.getElementById('poi_container').style.display = state ? 'unset' : 'none';
},
children: [
{
label: 'Services',
id: 'toggle_services',
state: true,
func: state =>{
document.getElementById('poi_service').style.display = state ? 'unset' : 'none';
},
},
{
label: 'Landmarks',
id: 'toggle_landmarks',
state: true,
func: state =>{
document.getElementById('poi_landmarks').style.display = state ? 'unset' : 'none';
},
},
]
},
{
label: 'Track Color',
id: 'radio_trackColor',
@@ -116,27 +143,34 @@ function populateKey(){
}else if(i >= 0){
gradeValue += ` - ${getGradeValue(i+1)}%`;
}
let gradeIcon = document.createElement('svg');
gradeIcon.classList.add('inlineSvg');
gradeIcon.setAttribute('viewBox', '-50 -50 100 100');
gradeIcon.innerHTML = `<use class="gradeSign grade_${gradeIndex}" href="#gradeArrow" transform="rotate(90)"/>`;
addKeyEntry(gradeIcon, ` ${gradeValue} Grade`);
addKeyEntry(`<use fill="${Config.gradeColors['grade_'+gradeIndex]}" href="#gradeArrow" transform="rotate(90)"/>`, ` ${gradeValue} Grade`);
}
let speedSignIcon = document.createElement('svg');
speedSignIcon.classList.add('inlineSvg');
speedSignIcon.setAttribute('viewBox', '-50 -50 100 100');
speedSignIcon.innerHTML = `<use class="speedSign" href="#speedSign_5"/>`;
addKeyEntry(speedSignIcon, ' Speed Limit');
addKeyEntry('<use href="#speedSign_5"/>', ' Speed Limit');
addKeyEntry('<use href="#mrk_office" fill="#c4693e" transform="scale(0.75)"/>', ' Station Office');
addKeyEntry('<use href="#mrk_shop" fill="#4f54e9" transform="scale(0.75)"/>', ' Shop');
addKeyEntry('<use href="#mrk_coal" fill="#202020" transform="scale(0.75)"/>', ' Coal Tower');
addKeyEntry('<use href="#mrk_water" fill="#3fa5ff" transform="scale(0.75)"/>', ' Water Tower');
addKeyEntry('<use href="#mrk_landmark" fill="#af5757" transform="scale(0.75)"/>', ' Landmark');
addKeyEntry('<use href="#mrk_garage" fill="#8b5dd7" transform="scale(0.75)"/>', ' Garage');
addKeyEntry('<use href="#mrk_service_repair" fill="#239a96" transform="scale(0.75)"/>', ' Repair Service');
addKeyEntry('<use href="#mrk_service_diesel" fill="#239a96" transform="scale(0.75)"/>', ' Diesel Refuel');
addKeyEntry('<use href="#mrk_service_charger" fill="#239a96" transform="scale(0.75)"/>', ' Electric Charger');
}
/**
* Add an entry to the map key.
* @param {Element} keyImage
* @param {string} keyLabel
* @param {string} keyImageHTML
* @param {string} keyLabel
*/
function addKeyEntry(keyImage, keyLabel){
function addKeyEntry(keyImageHTML, keyLabel){
let keyDiv = document.createElement('div');
if(keyImage) keyDiv.appendChild(keyImage);
if(keyImageHTML){
let keyImage = document.createElement('svg');
keyImage.innerHTML = keyImageHTML;
keyImage.classList.add('inlineSvg');
keyImage.setAttribute('viewBox', '-150 -150 300 300');
keyDiv.appendChild(keyImage);
}
keyDiv.innerHTML += keyLabel;
legendKey.appendChild(keyDiv);
}
+28 -20
View File
@@ -4,7 +4,7 @@
"type":"station",
"shorthand":"CME",
"color":"#958177",
"position":{"x":15622.98,"y":204.2502,"z":11220.5},
"position":{"x":15622.98,"y":204.2502,"z":10620.5},
"children":[
{
"type":"office",
@@ -31,7 +31,7 @@
"type":"station",
"shorthand":"CMS",
"color":"#6f6a58",
"position":{"x":8531.313,"y":156.2595,"z":3448.419},
"position":{"x":9251.313,"y":156.2595,"z":3408.419},
"children":[
{
"type":"office",
@@ -53,7 +53,7 @@
"type":"station",
"shorthand":"CP",
"color":"#824e4a",
"position":{"x":2064.521,"y":145.1,"z":9031.848},
"position":{"x":2064.521,"y":145.1,"z":8231.848},
"children":[
{
"type":"office",
@@ -74,7 +74,7 @@
"type":"station",
"shorthand":"CS",
"color":"#dfd7dc",
"position":{"x":9985.819,"y":134.6823,"z":1388.548},
"position":{"x":9785.819,"y":134.6823,"z":1488.548},
"children":[
{
"type":"office",
@@ -100,6 +100,10 @@
"type":"water",
"position":{"x":10249.08,"y":134.7365,"z":1468.002}
},
{
"type":"water",
"position":{"x":10050.59,"y":134.7859,"z":1370.713}
},
{
"name":"Olaf's Garage",
"type":"garage",
@@ -112,7 +116,7 @@
"type":"station",
"shorthand":"CW",
"color":"#f1cdbb",
"position": {"x":1956,"y":122,"z":5692},
"position": {"x":1456,"y":122,"z":5692},
"children":[
{
"type":"office",
@@ -141,7 +145,7 @@
"type":"station",
"shorthand":"FF",
"color":"#b2d1ff",
"position":{"x":9435.343,"y":119.1784,"z":13504.95},
"position":{"x":9035.343,"y":119.1784,"z":13504.95},
"children":[
{
"type":"office",
@@ -169,7 +173,7 @@
"type":"station",
"shorthand":"FM",
"color":"#ffda62",
"position":{"x":6027.609,"y":123.8593,"z":6704.711},
"position":{"x":6027.609,"y":123.8593,"z":7074.711},
"children":[
{
"type":"office",
@@ -186,7 +190,7 @@
"type":"station",
"shorthand":"FRC",
"color":"#d3e075",
"position":{"x":5727.74,"y":144.9063,"z":8757.236},
"position":{"x":6427.74,"y":144.9063,"z":8757.236},
"children":[
{
"type":"office",
@@ -203,7 +207,7 @@
"type":"station",
"shorthand":"FRS",
"color":"#8db16c",
"position":{"x":5340.794,"y":175.1235,"z":3787.574},
"position":{"x":5890.794,"y":175.1235,"z":3787.574},
"children":[
{
"type":"office",
@@ -221,7 +225,7 @@
"type":"station",
"shorthand":"GF",
"color":"#ff9db9",
"position":{"x":13002.78,"y":140.2193,"z":10995.55},
"position":{"x":13202.78,"y":140.2193,"z":10495.55},
"children":[
{
"type":"office",
@@ -254,7 +258,7 @@
"type":"station",
"shorthand":"HB",
"color":"#ff9db9",
"position":{"x":13066.07,"y":113.082,"z":3596.37},
"position":{"x":13066.07,"y":113.082,"z":3876.37},
"children":[
{
"type":"office",
@@ -292,7 +296,7 @@
"type":"station",
"shorthand":"IME",
"color":"#ff836f",
"position":{"x":15041.38,"y":248.062,"z":15341.35},
"position":{"x":15041.38,"y":248.062,"z":15741.35},
"children":[
{
"type":"office",
@@ -319,7 +323,7 @@
"type":"station",
"shorthand":"IMW",
"color":"#dc6f54",
"position":{"x":2103.091,"y":133.5531,"z":13359.38},
"position":{"x":2163.091,"y":133.5531,"z":13759.38},
"children":[
{
"type":"office",
@@ -345,7 +349,7 @@
"type":"station",
"shorthand":"MB",
"color":"#d6ac71",
"position":{"x":12524,"y":215.3452,"z":14749.98},
"position":{"x":12524,"y":215.3452,"z":14349.98},
"children":[
{
"type":"office",
@@ -364,7 +368,7 @@
"type":"station",
"shorthand":"MF",
"color":"#ffad6d",
"position":{"x":2348.254,"y":159.2693,"z":10823.74},
"position":{"x":2848.254,"y":159.2693,"z":10523.74},
"children":[
{
"type":"office",
@@ -401,7 +405,7 @@
"type":"station",
"shorthand":"OR",
"color":"#cf6884",
"position":{"x":6404.917,"y":143.8076,"z":11133.96},
"position":{"x":6934.917,"y":143.8076,"z":11133.96},
"children":[
{
"type":"office",
@@ -423,7 +427,7 @@
"type":"station",
"shorthand":"OWC",
"color":"#7b6f6e",
"position":{"x":4866.821,"y":122.9323,"z":6291.179},
"position":{"x":4466.821,"y":122.9323,"z":6651.179},
"children":[
{
"type":"office",
@@ -446,7 +450,7 @@
"type":"station",
"shorthand":"OWN",
"color":"#8b715e",
"position":{"x":11570.04,"y":122.3343,"z":11554.65},
"position":{"x":11570.04,"y":122.3343,"z":11954.65},
"children":[
{
"type":"office",
@@ -465,7 +469,7 @@
"type":"station",
"shorthand":"SM",
"color":"#ac9da2",
"position": {"x":7821,"y":131,"z":7277},
"position": {"x":8321,"y":131,"z":6707},
"children":[
{
"type":"office",
@@ -485,6 +489,10 @@
{
"type":"water",
"position":{"x":7981.461,"y":131.77,"z":7392.4}
},
{
"type":"water",
"position":{"x":7998.145,"y":131.7769,"z":7477.136}
}
]
},
@@ -493,7 +501,7 @@
"type":"station",
"shorthand":"SW",
"color":"#ffce98",
"position":{"x":1364.217,"y":147.2043,"z":2194.633},
"position":{"x":964.217,"y":147.2043,"z":1794.633},
"children":[
{
"type":"office",
+9 -12
View File
@@ -1,18 +1,6 @@
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wdth,wght@0,62.5..100,100..900;1,62.5..100,100..900&family=Protest+Strike&display=swap');
:root{
--grade_flat: #ffff;
--grade_0: #f4f7cd;
--grade_1: #f8ff99;
--grade_2: #edfc1b;
--grade_3: #fcb520;
--grade_4: #f07837;
--grade_5: #e66441;
--grade_6: #ce3f57;
--grade_7: #c33577;
--grade_8: #a3008d;
--grade_9: #690097;
--signScale: 1;
--cullThreshold_state_0: none;
--cullThreshold_state_1: none;
@@ -21,6 +9,8 @@
--cullThreshold_state_4: none;
--cullThreshold_state_5: none;
--cullThreshold_state_6: none;
--absScale: 1;
}
html, body, #map, #mapContainer, h1, h2, h3, h4, h5{
@@ -89,6 +79,9 @@ a:visited{
#legendKey{
font-size: 15px;
display: flex;
flex-flow: column wrap;
max-height: 310px;
}
#footer{
@@ -127,4 +120,8 @@ a:visited{
width: 1em;
height: 1em;
vertical-align: -0.1em;
}
.poi{
font-variation-settings: "wght" 700;
}
+6076 -6076
View File
File diff suppressed because it is too large. Load diff