Add yard signage
This commit is contained in:
1 parent
5d5441642d
commit
7886fc2303
5 files changed
+169
-25
No files matched your search
@@ -28,4 +28,15 @@ export const altitudeGradient = [
|
|||||||
new Color('#235f7b'),
|
new Color('#235f7b'),
|
||||||
new Color('#51c34e'),
|
new Color('#51c34e'),
|
||||||
new Color('#fce51e'),
|
new Color('#fce51e'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
export const sidingUsageMeanings = {
|
||||||
|
I:'Inbound',
|
||||||
|
O:'Outbound',
|
||||||
|
L:'Loading',
|
||||||
|
P:'Locomotive Parking',
|
||||||
|
S:'Car Storage',
|
||||||
|
LP:'Passenger Transfer',
|
||||||
|
SP:'Passenger Car Storage',
|
||||||
|
D:'Service & Repair',
|
||||||
|
}
|
||||||
@@ -36,6 +36,10 @@
|
|||||||
stroke-width: 6px;
|
stroke-width: 6px;
|
||||||
paint-order: stroke fill;
|
paint-order: stroke fill;
|
||||||
}
|
}
|
||||||
|
.yardSignage{
|
||||||
|
font: 200px "Noto Sans Mono";
|
||||||
|
text-anchor: middle;
|
||||||
|
}
|
||||||
.rail{
|
.rail{
|
||||||
fill: none;
|
fill: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ let mapData = [];
|
|||||||
let trackNameCounting = {};
|
let trackNameCounting = {};
|
||||||
let poiData = [];
|
let poiData = [];
|
||||||
let tracks = [];
|
let tracks = [];
|
||||||
|
let yardMarkers = {};
|
||||||
let markers = [];
|
let markers = [];
|
||||||
|
|
||||||
//let currentMapNav = {};
|
//let currentMapNav = {};
|
||||||
@@ -321,22 +322,24 @@ function fillSvg(){
|
|||||||
switch(obj.type){
|
switch(obj.type){
|
||||||
case 'bezier':
|
case 'bezier':
|
||||||
drawTracks(obj);
|
drawTracks(obj);
|
||||||
|
createTrackSignage(obj);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
createYardSignage();
|
||||||
sortTracks();
|
sortTracks();
|
||||||
setTrackColorMode('Grade');
|
setTrackColorMode('Grade');
|
||||||
drawMarkers();
|
drawSignage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Insert individual rail paths, as well as creating signage data for each path*/
|
/** Insert individual rail paths into the SVG */
|
||||||
function drawTracks(bezierData){
|
function drawTracks(bezierData){
|
||||||
if(trackNameCounting[bezierData.name] == null){
|
if(trackNameCounting[bezierData.name] == null){
|
||||||
trackNameCounting[bezierData.name] = 0;
|
trackNameCounting[bezierData.name] = 0;
|
||||||
}else{
|
}else{
|
||||||
trackNameCounting[bezierData.name]++;
|
trackNameCounting[bezierData.name]++;
|
||||||
}
|
}
|
||||||
let yardData = /\[(#)\]|\[(Y)\][_-]\[(.*?)\][_-]\[((.*?)[_-]*(.*?)[_-]*(.*?))\]/.exec(bezierData.name);
|
let yardData = /\[(#)\]|\[(Y)\][_-]\[(.*?)\][_-]\[((.*?)[_-](.*?)[_-](.*?)|.*)\]/.exec(bezierData.name);
|
||||||
if(yardData){
|
if(yardData){
|
||||||
if(yardData[1]){ // track is [#], thus in yard limits, but not a specific designated yard.
|
if(yardData[1]){ // track is [#], thus in yard limits, but not a specific designated yard.
|
||||||
bezierData.isYard = true;
|
bezierData.isYard = true;
|
||||||
@@ -396,8 +399,10 @@ function drawTracks(bezierData){
|
|||||||
].join('\n');
|
].join('\n');
|
||||||
bezierData.points[i].element.appendChild(title);
|
bezierData.points[i].element.appendChild(title);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add Signage
|
/** Create signage associated with the track section */
|
||||||
|
function createTrackSignage(bezierData){
|
||||||
let trackZoneData = {};
|
let trackZoneData = {};
|
||||||
let finalSegment = false;
|
let finalSegment = false;
|
||||||
for(let i=0; i<bezierData.points.length; i++){
|
for(let i=0; i<bezierData.points.length; i++){
|
||||||
@@ -412,7 +417,7 @@ function drawTracks(bezierData){
|
|||||||
trackZoneData.gradeCount = 0;
|
trackZoneData.gradeCount = 0;
|
||||||
trackZoneData.gradeSectionLength = 0;
|
trackZoneData.gradeSectionLength = 0;
|
||||||
};
|
};
|
||||||
let resetTzdSpeed = (eb) => {
|
let resetTzdSpeed = () => {
|
||||||
trackZoneData.prevSpeed = trackZoneData.speed;
|
trackZoneData.prevSpeed = trackZoneData.speed;
|
||||||
trackZoneData.speed = bezierData.points[i].postedSpeed;
|
trackZoneData.speed = bezierData.points[i].postedSpeed;
|
||||||
trackZoneData.speedCount = 0;
|
trackZoneData.speedCount = 0;
|
||||||
@@ -490,6 +495,53 @@ function drawTracks(bezierData){
|
|||||||
trackZoneData.speedCount++;
|
trackZoneData.speedCount++;
|
||||||
trackZoneData.speedSectionLength += bezierData.points[curSeg].bezLength;
|
trackZoneData.speedSectionLength += bezierData.points[curSeg].bezLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Yard Signage
|
||||||
|
if(bezierData.yardDesignation && bezierData.yardDesignation != '--'){
|
||||||
|
if(!yardMarkers[bezierData.yardStation]) yardMarkers[bezierData.yardStation] = {};
|
||||||
|
let centerIndex = Math.floor((bezierData.points.length-1)/2);
|
||||||
|
let yardSignPos = bezierData.points[centerIndex].position;
|
||||||
|
if(bezierData.points.length % 2 == 0){
|
||||||
|
yardSignPos = Bezier.evaluatePoint(
|
||||||
|
bezierData.points[centerIndex].position,
|
||||||
|
bezierData.points[centerIndex].h2,
|
||||||
|
bezierData.points[centerIndex+1].h1,
|
||||||
|
bezierData.points[centerIndex].position,
|
||||||
|
0.5);
|
||||||
|
}
|
||||||
|
if(bezierData.yardName){
|
||||||
|
if(!yardMarkers[bezierData.yardStation][bezierData.yardName]) yardMarkers[bezierData.yardStation][bezierData.yardName] = {accCenter:{x:0,y:0,z:0}, accCount:0};
|
||||||
|
yardMarkers[bezierData.yardStation][bezierData.yardName].accCenter.x += yardSignPos.x;
|
||||||
|
yardMarkers[bezierData.yardStation][bezierData.yardName].accCenter.y += yardSignPos.y;
|
||||||
|
yardMarkers[bezierData.yardStation][bezierData.yardName].accCenter.z += yardSignPos.z;
|
||||||
|
yardMarkers[bezierData.yardStation][bezierData.yardName].accCount++;
|
||||||
|
}
|
||||||
|
markers.push({
|
||||||
|
type: 'yardSiding',
|
||||||
|
name: bezierData.yardDesignation,
|
||||||
|
station: bezierData.yardStation,
|
||||||
|
yard: bezierData.yardName,
|
||||||
|
siding: bezierData.yardSidingNumber,
|
||||||
|
usage: bezierData.yardUsage,
|
||||||
|
position: yardSignPos
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createYardSignage(){
|
||||||
|
for(let station in yardMarkers){
|
||||||
|
for(let yard in yardMarkers[station]){
|
||||||
|
markers.push({
|
||||||
|
type: 'yard',
|
||||||
|
value: yard,
|
||||||
|
position: {
|
||||||
|
x: yardMarkers[station][yard].accCenter.x/yardMarkers[station][yard].accCount,
|
||||||
|
y: yardMarkers[station][yard].accCenter.y/yardMarkers[station][yard].accCount,
|
||||||
|
z: yardMarkers[station][yard].accCenter.z/yardMarkers[station][yard].accCount,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sort the tracks and put them into the svg */
|
/** Sort the tracks and put them into the svg */
|
||||||
@@ -594,21 +646,23 @@ export function setTrackColorMode(mode){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Create the signage */
|
/** Create the signage */
|
||||||
function drawMarkers(){
|
function drawSignage(){
|
||||||
const signage_container = document.createElementNS(svgns, 'g');
|
const signage_container = document.createElementNS(svgns, 'g');
|
||||||
const gradeSigns = document.createElementNS(svgns, 'g');
|
const gradeSigns = document.createElementNS(svgns, 'g');
|
||||||
const speedSigns = document.createElementNS(svgns, 'g');
|
const speedSigns = document.createElementNS(svgns, 'g');
|
||||||
|
const yardSigns = document.createElementNS(svgns, 'g');
|
||||||
|
|
||||||
signage_container.setAttribute('id', 'signage_container');
|
signage_container.setAttribute('id', 'signage_container');
|
||||||
gradeSigns.setAttribute('id', 'signage_grade');
|
gradeSigns.setAttribute('id', 'signage_grade');
|
||||||
speedSigns.setAttribute('id', 'signage_speed');
|
speedSigns.setAttribute('id', 'signage_speed');
|
||||||
|
yardSigns.setAttribute('id', 'signage_yard');
|
||||||
|
|
||||||
map_markers.appendChild(signage_container);
|
map_markers.appendChild(signage_container);
|
||||||
signage_container.appendChild(gradeSigns);
|
signage_container.appendChild(gradeSigns);
|
||||||
signage_container.appendChild(speedSigns);
|
signage_container.appendChild(speedSigns);
|
||||||
|
signage_container.appendChild(yardSigns);
|
||||||
|
|
||||||
for(const markerData of markers){
|
for(const markerData of markers){
|
||||||
//if(markerData.skip) continue;
|
|
||||||
let markerElement = document.createElementNS(svgns, 'g');
|
let markerElement = document.createElementNS(svgns, 'g');
|
||||||
let markerImg = document.createElementNS(svgns, 'use');
|
let markerImg = document.createElementNS(svgns, 'use');
|
||||||
let markerTooltip = document.createElementNS(svgns, 'title');
|
let markerTooltip = document.createElementNS(svgns, 'title');
|
||||||
@@ -616,22 +670,89 @@ function drawMarkers(){
|
|||||||
markerElement.appendChild(markerTooltip);
|
markerElement.appendChild(markerTooltip);
|
||||||
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
|
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
|
||||||
markerImg.classList.add('fixedScale', 'sign');
|
markerImg.classList.add('fixedScale', 'sign');
|
||||||
// Grade signs
|
switch(markerData.type){
|
||||||
if(markerData.type == 'grade'){
|
case 'grade':
|
||||||
markerImg.classList.add('gradeArrow');
|
markerImg.classList.add('gradeArrow');
|
||||||
markerImg.setAttribute('href', '#gradeArrow');
|
markerImg.setAttribute('href', '#gradeArrow');
|
||||||
markerImg.setAttribute('fill', Config.gradeColors['grade_'+markerData.gradeClass]);
|
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 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);
|
const rot = Math.atan2(markerData.tangent.x/tanLen, -markerData.tangent.z/tanLen) * (180/Math.PI);
|
||||||
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z}) rotate(${rot})`);
|
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\nCovers ${markerData.sectionCount} sections`;
|
markerTooltip.innerHTML = `${Math.round(markerData.value*1000)/10}% Grade\nSection Length: ${markerData.sectionLength.toFixed(1)} meters\nCovers ${markerData.sectionCount} sections`;
|
||||||
gradeSigns.appendChild(markerElement);
|
gradeSigns.appendChild(markerElement);
|
||||||
// Speed Signs
|
break;
|
||||||
}else if(markerData.type == 'speed'){
|
case 'speed':
|
||||||
markerImg.setAttribute('href', `#speedSign_${Math.round(markerData.value/10)}`);
|
markerImg.setAttribute('href', `#speedSign_${Math.round(markerData.value/10)}`);
|
||||||
markerTooltip.innerHTML = `${Math.round(markerData.value)} km/h\nSection Length: ${markerData.sectionLength.toFixed(1)} meters\nCovers ${markerData.sectionCount} sections`;
|
markerTooltip.innerHTML = `${Math.round(markerData.value)} km/h\nSection Length: ${markerData.sectionLength.toFixed(1)} meters\nCovers ${markerData.sectionCount} sections`;
|
||||||
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
|
markerElement.setAttribute('transform', `translate(${markerData.position.x} ${markerData.position.z})`);
|
||||||
speedSigns.appendChild(markerElement);
|
speedSigns.appendChild(markerElement);
|
||||||
|
break;
|
||||||
|
case 'yardSiding':
|
||||||
|
markerImg.remove();
|
||||||
|
let yardSidingSign = document.createElementNS(svgns,'g');
|
||||||
|
yardSidingSign.classList.add('fixedScale', 'sign', 'yardSignage', 'minZoomCull_5');
|
||||||
|
markerElement.appendChild(yardSidingSign);
|
||||||
|
|
||||||
|
let yardSidingBoard = document.createElementNS(svgns, 'rect');
|
||||||
|
let sidingBoardHeight = 230;
|
||||||
|
let sidingBoardWidth = (markerData.name.length+1) * 121;
|
||||||
|
yardSidingBoard.setAttribute('width', sidingBoardWidth);
|
||||||
|
yardSidingBoard.setAttribute('height', sidingBoardHeight);
|
||||||
|
yardSidingBoard.setAttribute('fill', '#fff');
|
||||||
|
yardSidingBoard.setAttribute('stroke', '#000');
|
||||||
|
yardSidingBoard.setAttribute('stroke-width', 30);
|
||||||
|
yardSidingBoard.setAttribute('rx', 45);
|
||||||
|
yardSidingBoard.setAttribute('transform', `translate(-${sidingBoardWidth/2}, -${sidingBoardHeight/2})`);
|
||||||
|
yardSidingBoard.appendChild(markerTooltip);
|
||||||
|
yardSidingSign.appendChild(yardSidingBoard);
|
||||||
|
|
||||||
|
let yardSidingText = document.createElementNS(svgns, 'text');
|
||||||
|
yardSidingText.innerHTML = markerData.name;
|
||||||
|
yardSidingText.setAttribute('transform', 'translate(0, 70)');
|
||||||
|
yardSidingText.setAttribute('pointer-events', 'none');
|
||||||
|
yardSidingSign.appendChild(yardSidingText);
|
||||||
|
if(markerData.yard && markerData.siding && markerData.usage){
|
||||||
|
if(!Config.sidingUsageMeanings[markerData.usage]) console.log(markerData.station+' '+markerData.name);
|
||||||
|
markerTooltip.innerHTML = `${markerData.yard}-${markerData.siding}, ${Config.sidingUsageMeanings[markerData.usage]}`;
|
||||||
|
}else{
|
||||||
|
markerTooltip.innerHTML = markerData.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
yardSigns.appendChild(markerElement);
|
||||||
|
break;
|
||||||
|
case 'yard':
|
||||||
|
markerImg.remove();
|
||||||
|
let yardSign = document.createElementNS(svgns,'g');
|
||||||
|
yardSign.classList.add('fixedScale', 'sign', 'yardSignage', 'maxZoomCull_5', 'minZoomCull_2');
|
||||||
|
markerElement.appendChild(yardSign);
|
||||||
|
|
||||||
|
let signText = markerData.value+' Yard';
|
||||||
|
|
||||||
|
let yardBoard = document.createElementNS(svgns, 'rect');
|
||||||
|
let boardHeight = 230;
|
||||||
|
let boardWidth = (signText.length+1) * 121;
|
||||||
|
yardBoard.setAttribute('width', boardWidth);
|
||||||
|
yardBoard.setAttribute('height', boardHeight);
|
||||||
|
yardBoard.setAttribute('fill', '#fff');
|
||||||
|
yardBoard.setAttribute('stroke', '#000');
|
||||||
|
yardBoard.setAttribute('stroke-width', 30);
|
||||||
|
yardBoard.setAttribute('rx', 45);
|
||||||
|
yardBoard.setAttribute('transform', `translate(-${boardWidth/2}, -${boardHeight/2})`);
|
||||||
|
yardBoard.appendChild(markerTooltip);
|
||||||
|
yardSign.appendChild(yardBoard);
|
||||||
|
|
||||||
|
let yardText = document.createElementNS(svgns, 'text');
|
||||||
|
yardText.innerHTML = signText;
|
||||||
|
yardText.setAttribute('transform', 'translate(0, 70)');
|
||||||
|
yardText.setAttribute('pointer-events', 'none');
|
||||||
|
yardSign.appendChild(yardText);
|
||||||
|
markerTooltip.innerHTML = signText;
|
||||||
|
|
||||||
|
yardSigns.appendChild(markerElement);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
markerElement.remove();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(markerData.debug != null) markerTooltip.innerHTML += '\n'+markerData.debug;
|
if(markerData.debug != null) markerTooltip.innerHTML += '\n'+markerData.debug;
|
||||||
|
|||||||
@@ -46,6 +46,14 @@ let settingEntries = [
|
|||||||
func: state =>{
|
func: state =>{
|
||||||
document.getElementById('signage_grade').style.display = state ? 'unset' : 'none';
|
document.getElementById('signage_grade').style.display = state ? 'unset' : 'none';
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Yard Signage',
|
||||||
|
id: 'toggle_yardSigns',
|
||||||
|
state: true,
|
||||||
|
func: state =>{
|
||||||
|
document.getElementById('signage_yard').style.display = state ? 'unset' : 'none';
|
||||||
|
},
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@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');
|
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&family=Noto+Sans:ital,wdth,wght@0,62.5..100,100..900;1,62.5..100,100..900&family=Protest+Strike&display=swap');
|
||||||
|
|
||||||
:root{
|
:root{
|
||||||
--absScale: 1;
|
--absScale: 1;
|
||||||
|
|||||||
Reference in new issue
Block a user