Added extended signal rednerering

+Added basic SignalExtendedRenderer. It doesnt support TOPs, signs and overhead signals yet
+Added SignalElementsEnums.HeadPosition.NO_POLE (used by dwarf signals) and .OVERHEAD
*Empty extended signals signs entries are no more being stored in the array
This commit is contained in:
izawartka 2025-06-26 22:24:43 +02:00
parent 2c42291139
commit 20c0cb092d
7 changed files with 147 additions and 17 deletions

View File

@ -49,6 +49,10 @@
stroke: #eee;
}
.map svg g.extended-signal-icon g {
stroke: #eee;
}
.map svg g.route g {
fill: #eee;
}

View File

@ -1,5 +1,5 @@
import { ReactSVG } from 'react-svg'
import AngleHelper from '../../../helpers/angleHelper';
import SignalElementsEnums from '../../../model/signal-elements/enums';
export default function SignalExtendedRenderer(props) {
const { object } = props;
@ -11,19 +11,11 @@ export default function SignalExtendedRenderer(props) {
const anchor = upsideDown ? "start" : "end";
return (
<g className="signal" transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}>
<g className="signal-icon" transform={`translate(-1.89, -9.1476)`}>
<ReactSVG
src={`${process.env.PUBLIC_URL}/assets/signal-test-new.svg`}
wrapper='svg'
beforeInjection={(svg) => {
svg.setAttribute('width', '1mm');
svg.setAttribute('height', '3.3mm');
}}
/>
<g className="extended-signal" transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}>
<g className="extended-signal-icon">
<SignalIcon object={object} />
</g>
<g transform={`translate(0, 4) rotate(${upsideDownRot})`}>
<g transform={`translate(0, 1.5) rotate(${upsideDownRot})`}>
<text x="0" y="0" textAnchor={anchor} dominantBaseline="middle">
{object.getPrintableSignalName()}
</text>
@ -31,3 +23,135 @@ export default function SignalExtendedRenderer(props) {
</g>
);
}
function SignalIcon(props) {
const { object } = props;
const halfBaseWidth = getHalfBaseWidth(object);
const headOff = getHeadOffset(object);
const poleLength = getPoleLength(object);
return (
<g strokeWidth={0.2} strokeLinecap="round" strokeLinejoin="round">
{ getBase(halfBaseWidth) }
{ getPole(poleLength, headOff) }
{ getHead(object, poleLength, headOff) }
</g>
);
}
function getHalfBaseWidth(object) {
const isDwarf = object.signal_elements.type === SignalElementsEnums.Type.DWARF;
const isDoubleDwarf = object.signal_elements.type === SignalElementsEnums.Type.DWARF_DOUBLE;
const isOverhead = object.signal_elements.headPosition === SignalElementsEnums.HeadPosition.OVERHEAD;
if(isOverhead) return 0;
if(isDwarf) return 0.6;
if(isDoubleDwarf) return 1.2;
return 0.4536;
}
function getBase(halfBaseWidth) {
if(halfBaseWidth === 0) return null;
return <path d={`M ${-halfBaseWidth} 0 L ${halfBaseWidth} 0`} />;
}
function getHeadOffset(object) {
const headPos = object.signal_elements.headPosition;
switch (headPos) {
case SignalElementsEnums.HeadPosition.STANDARD:
case SignalElementsEnums.HeadPosition.NO_POLE:
case SignalElementsEnums.HeadPosition.OVERHEAD:
default:
return 0;
case SignalElementsEnums.HeadPosition.LEFT:
return -0.4536;
case SignalElementsEnums.HeadPosition.RIGHT:
return 0.4536;
}
}
function getPoleLength(object) {
const headPos = object.signal_elements.headPosition;
if(headPos === SignalElementsEnums.HeadPosition.NO_POLE) return 0;
return 2;
}
function getPole(poleLength, headOff) {
if(!poleLength) return null;
if(headOff) {
return <path d={`M 0 0 L 0 -${poleLength - .5} L ${headOff} -${poleLength -.5} L ${headOff} -${poleLength}`} />;
}
return <path d={`M 0 0 L 0 -${poleLength}`} />;
}
function getUnit(key, unitType, x, y) {
const r = 0.6;
const c = 0.4;
const baseCircle = <circle cx={x} cy={y} r={r} />;
switch(unitType) {
case SignalElementsEnums.UnitType.RED:
return <g key={key}>
{baseCircle}
<line x1={x - r} y1={y} x2={x + r} y2={y} />
</g>
case SignalElementsEnums.UnitType.YELLOW_LOWER:
case SignalElementsEnums.UnitType.YELLOW_UPPER:
case SignalElementsEnums.UnitType.DWARF_YELLOW_S13:
return <g key={key}>
{baseCircle}
<line x1={x - c} y1={y - c} x2={x + c} y2={y + c} />
</g>
case SignalElementsEnums.UnitType.GREEN:
case SignalElementsEnums.UnitType.OLD_GREEN:
return <g key={key}>
{baseCircle}
<line x1={x} y1={y + r} x2={x} y2={y - r} />
</g>
case SignalElementsEnums.UnitType.BLUE:
return <g key={key}>
{baseCircle}
<line x1={x - c} y1={y - c} x2={x + c} y2={y + c} />
<line x1={x + c} y1={y - c} x2={x - c} y2={y + c} />
</g>
case SignalElementsEnums.UnitType.WHITE:
return <g key={key}>
{baseCircle}
</g>
case SignalElementsEnums.UnitType.DWARF_W24:
return <g key={key}>
{baseCircle}
<line x1={x - 0.3} y1={y - 0.3} x2={x + 0.3} y2={y + 0.3} />
</g>
default:
return <g key={key}>
{baseCircle}
<line x1={x - 0.2} y1={y - 0.5} x2={x + 0.5} y2={y + 0.2} />
<line x1={x - 0.5} y1={y - 0.2} x2={x + 0.2} y2={y + 0.5} />
</g>
}
}
function getHead(object, poleLength, headOff) {
// TODO: overhead signals
const isDoubleDwarf = object.signal_elements.type === SignalElementsEnums.Type.DWARF_DOUBLE;
const unitsCount = object.signal_elements.units.length;
const units = [];
const r = 0.6;
for(let i = 0; i < unitsCount; i++) {
const unitType = object.signal_elements.units[i];
const cx = isDoubleDwarf ? (i > 2 ? r : -r) : headOff;
const cy = -poleLength - r - i * r * 2 + (isDoubleDwarf && i > 2 ? 6 * r : 0);
units.push(getUnit(i, unitType, cx, cy));
}
return units;
}

View File

@ -7,7 +7,7 @@ export default function SignalRenderer(props) {
const { object } = props;
const { extendedSignals } = useContext(SettingsContext);
if (extendedSignals) {
if (extendedSignals && object.signal_elements) {
return <MemoizedSignalExtendedRenderer object={object} />;
} else {
return <MemoizedSignalStandardRenderer object={object} />;

View File

@ -11,6 +11,8 @@ const SignalElementsEnums = {
STANDARD: 1,
RIGHT: 2,
LEFT: 3,
NO_POLE: 4,
OVERHEAD: 5,
},
UnitType: {
UNKNOWN: 0,

View File

@ -99,7 +99,7 @@ export default class SignalElementsParserCommon {
const index = start + i * step;
if (index >= entries.length) break;
signs[i] = entries[index]?.trim();
signs.push(entries[index]?.trim());
}
return signs;

View File

@ -18,7 +18,7 @@ export default class SignalElementsParserEhaEriDwarfPs {
return new SignalElements(
isDouble ? SignalElementsEnums.Type.DWARF_DOUBLE : SignalElementsEnums.Type.DWARF,
SignalElementsEnums.HeadPosition.STANDARD,
SignalElementsEnums.HeadPosition.NO_POLE,
[mainUnits, secondaryUnits].flat(),
SignalElementsEnums.BarType.NONE,
SignalElementsParserCommon.getSigns(entries, 15, 1, 1)

View File

@ -15,7 +15,7 @@ export default class SignalElementsParserEhaEriDwarf {
return new SignalElements(
SignalElementsEnums.Type.DWARF,
SignalElementsEnums.HeadPosition.STANDARD,
SignalElementsEnums.HeadPosition.NO_POLE,
SignalElementsParserCommon.getUnits(entries, 2, 3, 2),
SignalElementsEnums.BarType.NONE,
[]