Mechanical signals rendering

+Added support for mechanical signals in extended signals rendering mode
This commit is contained in:
izawartka 2025-07-01 21:18:37 +02:00
parent e0149037cf
commit 6fb032a70f
7 changed files with 106 additions and 1 deletions

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g stroke-linecap="round">
<path d="m74 40c-3.5725 5.2e-5 -6.8746 1.9059-8.661 4.9997h-50.339c-2.216 0-4.0003 1.7843-4.0003 4.0003v1.9999c0 2.216 1.7843 3.9998 4.0003 3.9998h50.34c1.7862 3.094 5.0874 5.0001 8.6599 5.0002 5.523 2.34e-4 10-4.4769 10-9.9999-5e-5 -5.523-4.4774-10-10-9.9999z" class="background" />
<path d="m74 37c-3.9976 5.8e-5 -7.6615 1.9196-10.105 5h-48.895c-3.8264 0-7 3.1736-7 7v2c0 3.8264 3.1741 7 7 7h48.896c2.4436 3.0804 6.1058 4.9998 10.104 5 7.1443 3.03e-4 13-5.8557 13-13-6.5e-5 -7.1443-5.8557-13-13-13zm0 6c3.9016-1.65e-4 7 3.0984 7 7-3.8e-5 3.9016-3.0984 7.0002-7 7-2.5056-1.11e-4 -4.8097-1.33-6.0625-3.5l-0.86523-1.5h-52.072c-0.60611 0-1-0.39436-1-1v-2c0-0.60564 0.39435-1 1-1h52.07l0.86719-1.5c1.2526-2.1694 3.557-3.5 6.0625-3.5z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 925 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m56 15v69l-6 5-6-5v-69c0-2.216 1.784-4 4-4h4c2.216 0 4 1.784 4 4z" class="background" />
<path d="m59 15c0-3.8261-3.1739-7-7-7h-4c-3.8261 0-7 3.1739-7 7v69a3.0003 3.0003 0 0 0 1.0801 2.3047l6 5a3.0003 3.0003 0 0 0 3.8398 0l6-5a3.0003 3.0003 0 0 0 1.0801-2.3047zm-6 0v67.596l-3 2.5-3-2.5v-67.596c0-0.60589 0.39411-1 1-1h4c0.60589 0 1 0.39411 1 1z" />
</svg>

After

Width:  |  Height:  |  Size: 513 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m79.2 50a29.2 29.2 0 0 1-29.2 29.2 29.2 29.2 0 0 1-29.2-29.2 29.2 29.2 0 0 1 29.2-29.2 29.2 29.2 0 0 1 29.2 29.2z" class="background" />
<path d="m50 17.801c-17.748 0-32.199 14.451-32.199 32.199s14.451 32.199 32.199 32.199 32.199-14.451 32.199-32.199-14.451-32.199-32.199-32.199zm0 6c14.505 0 26.199 11.694 26.199 26.199s-11.694 26.199-26.199 26.199-26.199-11.694-26.199-26.199 11.694-26.199 26.199-26.199z" />
</svg>

After

Width:  |  Height:  |  Size: 574 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path transform="rotate(45)" d="m47.711-27h46c2.216 0 4 1.784 4 4v46c0 2.216-1.784 4-4 4h-46c-2.216 0-4-1.784-4-4v-46c0-2.216 1.784-4 4-4z" class="background" />
<path transform="rotate(45)" d="m47.711-30c-3.8261 0-7 3.1739-7 7v46c0 3.8261 3.1739 7 7 7h46c3.8261 0 7-3.1739 7-7v-46c0-3.8261-3.1739-7-7-7zm0 6h46c0.60589 0 1 0.39411 1 1v46c0 0.60589-0.39411 1-1 1h-46c-0.60589 0-1-0.39411-1-1v-46c0-0.60589 0.39411-1 1-1z" />
</svg>

After

Width:  |  Height:  |  Size: 579 B

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<path d="m28 20h44c4.432 0 8 3.568 8 8v44c0 4.432-3.568 8-8 8h-44c-4.432 0-8-3.568-8-8v-44c0-4.432 3.568-8 8-8z" />
<path d="m71 50a21 21 0 0 1-21 21 21 21 0 0 1-21-21 21 21 0 0 1 21-21 21 21 0 0 1 21 21z" class="background" />
<path d="m27.12 45.71h45.76v8.58h-45.76z" />
</svg>

After

Width:  |  Height:  |  Size: 428 B

View File

@ -91,6 +91,14 @@
fill: #111; fill: #111;
} }
.map svg g.signal-head-mech path {
fill: #eee;
}
.map svg g.signal-head-mech path.background {
fill: #111;
}
.map svg g.nevp path { .map svg g.nevp path {
fill: #eee; fill: #eee;
} }

View File

@ -102,9 +102,11 @@ function getPolePoints(object, headOffsetX) {
if(isDwarf) return null; if(isDwarf) return null;
const isOverhead = object.signal_elements.isOverhead(); const isOverhead = object.signal_elements.isOverhead();
const isMechanical = object.signal_elements.isMechanical();
const polePoints = {}; const polePoints = {};
polePoints.zigzag = headOffsetX !== 0 ? 0.4 : 0; polePoints.zigzag = headOffsetX !== 0 ? 0.4 : 0;
if(isMechanical) polePoints.zigzag += 3.5;
polePoints.bars = polePoints.zigzag; polePoints.bars = polePoints.zigzag;
switch(object.signal_elements.bar) { switch(object.signal_elements.bar) {
@ -121,7 +123,9 @@ function getPolePoints(object, headOffsetX) {
const signsHeight = Object.keys(object.signal_elements.signs).map(key => (DefinedSignalSigns[key]?.height || 1.0) + 0.2).reduce((a, b) => a + b, 0) || 0; const signsHeight = Object.keys(object.signal_elements.signs).map(key => (DefinedSignalSigns[key]?.height || 1.0) + 0.2).reduce((a, b) => a + b, 0) || 0;
polePoints.signs = polePoints.bars + signsHeight; polePoints.signs = polePoints.bars + signsHeight;
polePoints.end = isOverhead ? polePoints.signs : Math.max(polePoints.signs + 0.8, 2.2); polePoints.end = polePoints.signs;
if(isMechanical) polePoints.end = Math.max(polePoints.end + 0.8, 6.0);
else if(!isOverhead) polePoints.end = Math.max(polePoints.signs + 0.8, 2.2);
return polePoints; return polePoints;
} }
@ -186,6 +190,10 @@ function getUnit(key, unitType, x, y) {
} }
function getHead(object, headOffsetY, headOffsetX) { function getHead(object, headOffsetY, headOffsetX) {
if(object.signal_elements.isMechanical()) {
return getHeadMech(object, headOffsetY);
}
if(object.signal_elements.type === SignalElementsEnums.Type.TOP) { if(object.signal_elements.type === SignalElementsEnums.Type.TOP) {
return getHeadTOP(object, headOffsetY); return getHeadTOP(object, headOffsetY);
} }
@ -219,6 +227,67 @@ function getHeadTOP(object, headOffsetY) {
</> </>
} }
function getHomeMechSignalArm(y, rot) {
return <g transform={`translate(0 ${y}) rotate(${rot}) translate(-0.576, -1.89)`}>
<ReactSVG
src={`${process.env.PUBLIC_URL}/assets/mech_signals/arm.svg`}
wrapper='svg'
beforeInjection={(svg) => {
svg.setAttribute('width', '1mm');
svg.setAttribute('height', '1mm');
}}
/>;
</g>;
}
function getCustomMechHead(y, fileName) {
return <g transform={`translate(-1.89, ${y -1.89})`}>
<ReactSVG
src={`${process.env.PUBLIC_URL}/assets/mech_signals/${fileName}`}
wrapper='svg'
beforeInjection={(svg) => {
svg.setAttribute('width', '1mm');
svg.setAttribute('height', '1mm');
}}
/>;
</g>;
}
function getHeadMech(object, headOffsetY) {
const mechType = object.signal_elements.mechType;
switch(mechType) {
case SignalElementsEnums.MechType.HOME_SINGLE:
return <g className="signal-head-mech">
{ getHomeMechSignalArm(headOffsetY, 0) }
</g>
case SignalElementsEnums.MechType.HOME_DOUBLE:
return <g className="signal-head-mech">
{ getHomeMechSignalArm(headOffsetY, 0) }
{ getHomeMechSignalArm(headOffsetY + 3.5, -90) }
</g>
case SignalElementsEnums.MechType.SHUNTING:
return <g className="signal-head-mech">
{ getCustomMechHead(headOffsetY, 'shunting_head.svg') }
</g>
case SignalElementsEnums.MechType.DISTANT_SINGLE:
return <g className="signal-head-mech">
{ getCustomMechHead(headOffsetY, 'distant_head.svg') }
</g>
case SignalElementsEnums.MechType.DISTANT_DOUBLE:
return <g className="signal-head-mech">
{ getCustomMechHead(headOffsetY, 'distant_head.svg') }
{ getCustomMechHead(headOffsetY + 3.5, 'distant_arm.svg') }
</g>
case SignalElementsEnums.MechType.STOP:
return <g className="signal-head-mech">
{ getCustomMechHead(headOffsetY, 'stop_head.svg') }
</g>
default:
return null;
}
}
function getBar(object, headOffsetX, y, isYellow, key = 0) { function getBar(object, headOffsetX, y, isYellow, key = 0) {
const yellowOff = isYellow ? 0.2 : 0; const yellowOff = isYellow ? 0.2 : 0;