diff --git a/src/packages/EsbButton/ThEsbButton.ts b/src/packages/EsbButton/ThEsbButton.ts new file mode 100644 index 0000000..c3b263e --- /dev/null +++ b/src/packages/EsbButton/ThEsbButton.ts @@ -0,0 +1,111 @@ +import { Graphics } from 'pixi.js'; +import { + GraphicData, + GraphicState, + JlGraphic, + VectorText, +} from 'jl-graphic'; + +export interface IEsbButtonData extends GraphicData { + get code(): string; + set code(v: string); + get flip(): boolean; + set flip(v: boolean); +} + +export interface IEsbButtonState extends GraphicState { + id: number; + get down(): boolean; + set down(v: boolean); +} + +const esbButtonConsts = { + codeFontSize: 12, + codeColor: 0xffffff, + bodyLineColor: 0xffffff, + bodyLineWidth: 4, + bodyRectLineColor: 0xffffff, + bodyRectLineWidth: 2, + bodyRectWidth: 20, + bodyRectHeight: 20, + bodyCircleRadius: 5, + bodyCircleColor: 0xffffff, + bodyColor: 0x000000, + pressedColor: 0xff0000, +}; +export class EsbButton extends JlGraphic { + static Type = 'esbButton'; + codeGraph: VectorText = new VectorText(''); + circleBody: Graphics = new Graphics(); + rectBody: Graphics = new Graphics(); + lineBody: Graphics = new Graphics(); + + constructor() { + super(EsbButton.Type); + this.addChild(this.codeGraph); + this.addChild(this.rectBody); + this.addChild(this.lineBody); + this.addChild(this.circleBody); + this.codeGraph.name = 'esb_code'; + } + get datas(): IEsbButtonData { + return this.getDatas(); + } + get state(): IEsbButtonState { + return this.getStates(); + } + doRepaint(): void { + const codeGraph = this.codeGraph; + codeGraph.text = this.datas.code; + codeGraph.style.fill = esbButtonConsts.codeColor; + codeGraph.setVectorFontSize(esbButtonConsts.codeFontSize); + codeGraph.anchor.set(0.5); + const codeTransform = this.datas?.childTransforms?.find( + (item) => item.name === 'esb_code' + ); + if (codeTransform) { + const position = codeTransform?.transform.position; + const rotation = codeTransform?.transform?.rotation; + codeGraph.position.set(position?.x, position?.y); + codeGraph.rotation = rotation || 0; + } else { + codeGraph.position.set(-30, 0); + } + this.circleBody.clear(); + this.circleBody.beginFill( + this.state.down + ? esbButtonConsts.pressedColor + : esbButtonConsts.bodyCircleColor, + 1 + ); + this.circleBody.drawCircle(0, 0, esbButtonConsts.bodyCircleRadius); + this.circleBody.endFill(); + this.rectBody.clear(); + this.rectBody.beginFill(esbButtonConsts.bodyColor, 0); + this.rectBody.lineStyle( + esbButtonConsts.bodyRectLineWidth, + this.state.down + ? esbButtonConsts.pressedColor + : esbButtonConsts.bodyRectLineColor + ); + this.rectBody.drawRect( + -esbButtonConsts.bodyRectWidth / 2, + -esbButtonConsts.bodyRectHeight / 2, + esbButtonConsts.bodyRectWidth, + esbButtonConsts.bodyRectHeight + ); + this.rectBody.endFill(); + this.lineBody.clear(); + const lineY = this.datas.flip + ? esbButtonConsts.bodyRectHeight / 2 + : -esbButtonConsts.bodyRectHeight / 2; + this.lineBody.lineStyle( + esbButtonConsts.bodyLineWidth, + this.state.down + ? esbButtonConsts.pressedColor + : esbButtonConsts.bodyLineColor + ); + this.lineBody.moveTo(-esbButtonConsts.bodyRectWidth / 2, lineY); + this.lineBody.lineTo(esbButtonConsts.bodyRectWidth / 2, lineY); + } +} diff --git a/src/packages/EsbButton/ZdwxEsbButton.ts b/src/packages/EsbButton/ZdwxEsbButton.ts new file mode 100644 index 0000000..5e1b7f5 --- /dev/null +++ b/src/packages/EsbButton/ZdwxEsbButton.ts @@ -0,0 +1,87 @@ +import { Graphics } from 'pixi.js'; +import { + GraphicData, + GraphicState, + JlGraphic, + VectorText, +} from 'jl-graphic'; + +export interface IZdwxEsbData extends GraphicData { + get code(): string; + set code(v: string); + get flip(): boolean; + set flip(v: boolean); +} + +export interface IZdwxEsbState extends GraphicState { + id: number; + get down(): boolean; + set down(v: boolean); +} + +export const zdwxEsbConsts = { + codeFontSize: 12, + codeColor: 0xffffff, + bodyLineColor: 0xff0000, + lineWidth: 2, + bodyRectLineColor: 0xff0000, + bodyRectLineWidth: 1, + bodyRectWidth: 20, + bodyRectHeight: 20, + bodyCircleRadius: 4, + bodyColor: 0xff0000, + rectOffset: -10, +}; +export class ZdwxEsb extends JlGraphic { + static Type = 'esbButton'; + codeGraph: VectorText = new VectorText(''); + circleBody: Graphics = new Graphics(); + + constructor() { + super(ZdwxEsb.Type); + this.addChild(this.codeGraph); + this.addChild(this.circleBody); + this.codeGraph.name = 'zdwx_esb_code'; + } + get datas(): IZdwxEsbData { + return this.getDatas(); + } + get state(): IZdwxEsbState { + return this.getStates(); + } + doRepaint(): void { + const codeGraph = this.codeGraph; + codeGraph.text = this.datas.code; + codeGraph.style.fill = zdwxEsbConsts.codeColor; + codeGraph.setVectorFontSize(zdwxEsbConsts.codeFontSize); + codeGraph.anchor.set(0.5); + const codeTransform = this.datas?.childTransforms?.find( + (item) => item.name === 'zdwx_esb_code' + ); + if (codeTransform) { + const position = codeTransform?.transform.position; + const rotation = codeTransform?.transform?.rotation; + codeGraph.position.set(position?.x, position?.y); + codeGraph.rotation = rotation || 0; + } else { + codeGraph.position.set(-30, 0); + } + this.circleBody.clear(); + this.circleBody.lineStyle(zdwxEsbConsts.lineWidth, zdwxEsbConsts.bodyColor); + if (this.datas.flip) { + this.circleBody.arc(0, 0, zdwxEsbConsts.bodyCircleRadius, 0, Math.PI); + this.circleBody.moveTo(0, 0); + this.circleBody.lineTo(0, -6); + } else { + this.circleBody.arc(0, 0, zdwxEsbConsts.bodyCircleRadius, Math.PI, 0); + this.circleBody.moveTo(0, 0); + this.circleBody.lineTo(0, 6); + } + this.circleBody.drawRect( + zdwxEsbConsts.rectOffset, + zdwxEsbConsts.rectOffset, + zdwxEsbConsts.bodyRectWidth, + zdwxEsbConsts.bodyRectHeight + ); + } +} diff --git a/src/packages/GatedBox/GatedBox.ts b/src/packages/GatedBox/GatedBox.ts new file mode 100644 index 0000000..b58f7cb --- /dev/null +++ b/src/packages/GatedBox/GatedBox.ts @@ -0,0 +1,95 @@ +import { Graphics } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + VectorText, +} from 'jl-graphic'; + +export interface IGatedBox extends GraphicData { + get code(): string; + set code(v: string); + get flip(): boolean; + set flip(v: boolean); + get refScreenDoor(): number; + set refScreenDoor(v: number); + get refGatedBoxMapCode(): string; + set refGatedBoxMapCode(v: string); + clone(): IGatedBox; + copyFrom(data: IGatedBox): void; + eq(other: IGatedBox): boolean; +} + +const gatedBoxConsts = { + codeFontSize: 12, + codeColor: 0xffffff, + bodyLineColor: 0xffffff, + bodyLineWidth: 4, + bodyRectLineColor: 0xffffff, + bodyRectLineWidth: 2, + bodyRectWidth: 20, + bodyRectHeight: 20, + bodyColor: 0x000000, +}; +export class GatedBox extends JlGraphic { + static Type = 'gatedBox'; + codeGraph: VectorText = new VectorText(''); + rectBody: Graphics = new Graphics(); + lineBody: Graphics = new Graphics(); + textGraph: VectorText = new VectorText('M'); + + constructor() { + super(GatedBox.Type); + this.addChild(this.codeGraph); + this.addChild(this.rectBody); + this.addChild(this.lineBody); + this.addChild(this.textGraph); + this.codeGraph.name = 'gated_box_code'; + } + get datas(): IGatedBox { + return this.getDatas(); + } + doRepaint(): void { + const codeGraph = this.codeGraph; + codeGraph.text = this.datas.code; + codeGraph.style.fill = gatedBoxConsts.codeColor; + codeGraph.setVectorFontSize(gatedBoxConsts.codeFontSize); + const codeTransform = this.datas?.childTransforms?.find( + (item) => item.name === 'gated_box_code' + ); + if (codeTransform) { + const position = codeTransform?.transform.position; + const rotation = codeTransform?.transform?.rotation; + codeGraph.position.set(position?.x, position?.y); + codeGraph.rotation = rotation || 0; + } else { + codeGraph.position.set(20, 0); + } + codeGraph.anchor.set(0.5); + this.textGraph.style.fill = gatedBoxConsts.codeColor; + this.textGraph.setVectorFontSize(gatedBoxConsts.codeFontSize); + this.textGraph.anchor.set(0.5); + this.rectBody.clear(); + this.rectBody.beginFill(gatedBoxConsts.bodyColor, 0); + this.rectBody.lineStyle( + gatedBoxConsts.bodyRectLineWidth, + gatedBoxConsts.bodyRectLineColor + ); + this.rectBody.drawRect( + -gatedBoxConsts.bodyRectWidth / 2, + -gatedBoxConsts.bodyRectHeight / 2, + gatedBoxConsts.bodyRectWidth, + gatedBoxConsts.bodyRectHeight + ); + this.rectBody.endFill(); + this.lineBody.clear(); + const lineY = this.datas.flip + ? gatedBoxConsts.bodyRectHeight / 2 + : -gatedBoxConsts.bodyRectHeight / 2; + this.lineBody.lineStyle( + gatedBoxConsts.bodyLineWidth, + gatedBoxConsts.bodyLineColor + ); + this.lineBody.moveTo(-gatedBoxConsts.bodyRectWidth / 2, lineY); + this.lineBody.lineTo(gatedBoxConsts.bodyRectWidth / 2, lineY); + } +} diff --git a/src/packages/Signal/Lamp.ts b/src/packages/Signal/Lamp.ts deleted file mode 100644 index 9191f3f..0000000 --- a/src/packages/Signal/Lamp.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { Container } from '@pixi/display'; -import { Graphics } from 'pixi.js'; - -const lampConsts = { - lampRadius: 8, - logicModeLineWidth: 2, - logicModeDistance: 5, - logicModeColor: '0x000000', - lampLineWidth: 1, - lampLineColor: '0x3149c3', - lampBadColor: '0xFF0000', - badStart: 10, - badEnd: 15, -}; - -export class Lamp extends Container { - circleLamp: Graphics = new Graphics(); - logicMode: Graphics = new Graphics(); - lampBad: Graphics = new Graphics(); - radiusX = 0; - radiusY = 0; - - constructor() { - super(); - this.addChild(this.circleLamp); - this.addChild(this.logicMode); - this.addChild(this.lampBad); - } - paint(radiusX: number, radiusY: number) { - this.radiusX = radiusX; - this.radiusY = radiusY; - this.createLamp(); - } - createLampBad() { - this.lampBad.clear(); - this.lampBad.lineStyle(lampConsts.lampLineWidth, lampConsts.lampBadColor); - this.lampBad.moveTo(this.radiusX + lampConsts.badStart, this.radiusY); - this.lampBad.lineTo(this.radiusX + lampConsts.badEnd, this.radiusY); - this.lampBad.moveTo(this.radiusX - lampConsts.badStart, this.radiusY); - this.lampBad.lineTo(this.radiusX - lampConsts.badEnd, this.radiusY); - this.lampBad.moveTo(this.radiusX, this.radiusY + lampConsts.badStart); - this.lampBad.lineTo(this.radiusX, this.radiusY + lampConsts.badEnd); - this.lampBad.moveTo(this.radiusX, this.radiusY - lampConsts.badStart); - this.lampBad.lineTo(this.radiusX, this.radiusY - lampConsts.badEnd); - const xieStart = Math.sin(Math.PI / 4) * lampConsts.badStart; - const xieEnd = Math.sin(Math.PI / 4) * lampConsts.badEnd; - this.lampBad.moveTo(this.radiusX + xieStart, this.radiusY + xieStart); - this.lampBad.lineTo(this.radiusX + xieEnd, this.radiusY + xieEnd); - this.lampBad.moveTo(this.radiusX + xieStart, this.radiusY - xieStart); - this.lampBad.lineTo(this.radiusX + xieEnd, this.radiusY - xieEnd); - - this.lampBad.moveTo(this.radiusX - xieStart, this.radiusY - xieStart); - this.lampBad.lineTo(this.radiusX - xieEnd, this.radiusY - xieEnd); - this.lampBad.moveTo(this.radiusX - xieStart, this.radiusY + xieStart); - this.lampBad.lineTo(this.radiusX - xieEnd, this.radiusY + xieEnd); - } - createLamp(color?: string) { - this.circleLamp.clear(); - this.circleLamp.lineStyle( - lampConsts.lampLineWidth, - lampConsts.lampLineColor - ); - if (!color) { - this.circleLamp.beginFill('0XFFFFFF', 0); - } else { - this.circleLamp.beginFill(color, 1); - } - this.circleLamp.drawCircle( - this.radiusX, - this.radiusY, - lampConsts.lampRadius - ); - this.circleLamp.endFill(); - } - createLogicMode() { - this.logicMode - .clear() - .lineStyle(lampConsts.logicModeLineWidth, lampConsts.logicModeColor) - .moveTo( - this.radiusX - lampConsts.logicModeDistance, - this.radiusY + lampConsts.logicModeDistance - ) - .lineTo( - this.radiusX + lampConsts.logicModeDistance, - this.radiusY - lampConsts.logicModeDistance - ) - .moveTo( - this.radiusX - lampConsts.logicModeDistance, - this.radiusY - lampConsts.logicModeDistance - ) - .lineTo( - this.radiusX + lampConsts.logicModeDistance, - this.radiusY + lampConsts.logicModeDistance - ); - } - logicModeClear() { - this.logicMode.clear(); - } - lampClear() { - this.circleLamp.clear(); - } -} diff --git a/src/packages/Signal/bjRtss/LampMainBody.ts b/src/packages/Signal/bjRtss/LampMainBody.ts new file mode 100644 index 0000000..c285ee8 --- /dev/null +++ b/src/packages/Signal/bjRtss/LampMainBody.ts @@ -0,0 +1,110 @@ +import { Graphics, Point, Container } from 'pixi.js'; +import { + calculateMirrorPoint, + GraphicAnimation, +} from 'jl-graphic'; +import { Lamp } from '../common/Lamp'; +import { SignalColorEnum, signalConsts, Model } from './Signal'; + +export class LampMainBody extends Container { + static Type = 'LampMainBody'; + lampNum = 1; + lampPost: Graphics = new Graphics(); + lamps: Lamp[] = []; + mirror = false; + + paint(mt: Model, mirror: boolean) { + this.mirror = mirror; + if ( + mt === Model.HL || + mt === Model.AB + ) { + this.lampNum = 2; + } else { + this.lampNum = 3; + } + this.removeChildren(0); + this.lampPost = new Graphics(); + let lpp = new Point(signalConsts.levelLampPostLength, 0); + if (mirror) { + lpp = calculateMirrorPoint(new Point(0, 0), lpp); + } + this.lampPost + .lineStyle(signalConsts.postLineWidth, SignalColorEnum.lampPostColor) + .moveTo(0, -signalConsts.verticalLampPostLength / 2) + .lineTo(0, signalConsts.verticalLampPostLength / 2) + .moveTo(0, 0) + .lineTo(lpp.x, lpp.y); + this.addChild(this.lampPost); + + this.lamps = []; + for (let i = 0; i < this.lampNum; i++) { + const lamp = new Lamp(false); + this.addChild(lamp); + const radiusX = + (1 + i * 2) * signalConsts.lampRadius + + signalConsts.levelLampPostLength; + let lrp = new Point(radiusX, 0); + if (mirror) { + lrp = calculateMirrorPoint(new Point(0, 0), lrp); + } + lamp.paint(lrp.x, lrp.y); + this.lamps.push(lamp); + } + } + setStateBlueShow() { + this.lamps.forEach(lamp =>{ + lamp.createLamp(SignalColorEnum.blueLamp); + }) + } + + setStateLogic() { + this.lamps.forEach(lamp => { + lamp.createLogicMode(); + }) + } + + setStateH() { + this.lamps[0].createLamp(SignalColorEnum.redLamp); + this.lamps.forEach((lamp, index) => { + if (index !== 0) { + lamp.createLamp(SignalColorEnum.closeLamp); + } + }); + } + setStateL() { + this.lamps[1].createLamp(SignalColorEnum.greenLamp); + this.lamps.forEach((lamp, index) => { + if(index !==1) { + lamp.createLamp(SignalColorEnum.closeLamp); + } + }); + } + setStateU() { + this.lamps[2].createLamp(SignalColorEnum.yellowLamp); + this.lamps.forEach((lamp, index) => { + if (index !== 2) { + lamp.createLamp(SignalColorEnum.closeLamp); + } + }) + } + setStateHu() { + this.lamps[0].createLamp(SignalColorEnum.redLamp); + this.lamps[1].createLamp(SignalColorEnum.closeLamp); + this.lamps[2].createLamp(SignalColorEnum.yellowLamp); + } + setStateA() { + this.lamps[0].createLamp(SignalColorEnum.blueLamp); + this.lamps[1].createLamp(SignalColorEnum.closeLamp); + } + setStateB() { + this.lamps[0].createLamp(SignalColorEnum.whiteLamp); + this.lamps[1].createLamp(SignalColorEnum.closeLamp); + } + setStateOff() { + this.lamps.forEach((lamp) => + lamp.createLamp(SignalColorEnum.closeLamp) + ); + } +} + diff --git a/src/packages/Signal/bjRtss/Signal.ts b/src/packages/Signal/bjRtss/Signal.ts new file mode 100644 index 0000000..fc83b8e --- /dev/null +++ b/src/packages/Signal/bjRtss/Signal.ts @@ -0,0 +1,317 @@ +import { Graphics, Point } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + GraphicRelationParam, + GraphicState, + JlGraphicTemplate +} from 'jl-graphic'; +import { LampMainBody } from './LampMainBody'; +// import { +// drawArrow, +// } from '../common/CommonGraphics'; +import { SignalCode } from '../common/SignalCode'; + +/** 信号机类型 */ +export enum Model { + HL = 0, // 红绿灯 + HLU_FU = 1, // 红绿黄,封黄灯,无引导 + HLU_DU_YY = 2, // 红绿黄,不封灯,有单黄,带引导 + HLU_YY = 3, // 红绿黄,不封灯,无单黄,带引导 + HLU_FL_DU_YY = 4, // 红绿黄,封绿灯,有单黄,带引导 + HLU_DU = 5, // 红绿黄,不封灯,有单黄,无引导 + AB = 6, // 蓝白 + HBU_DU = 7, // 红白黄,不封灯,有单黄,无引导 +} + +export enum Direction { + LEFT = 0, + RIGHT = 1, +} + +export enum DeviceType { + Section = 0, + Turnout = 1, + TrainWindow = 2, + AxleCounting = 3, + SectionLink = 4, + signal = 5, + station = 6, + ScreenDoor = 7, + SignalFaultAlarm = 8, + Breakers = 9, + PowerScreen = 10 +} + +export enum Aspect { + Non = 0, + OFF = 1, + L = 2, + H = 3, + U = 4, + HU = 5, + B = 6, + A = 7 +} + +export enum DevicePort { + A = 0, + B = 1, + C = 2 +} + +export interface KilometerSystem { + get coordinateSystem(): string; + set coordinateSystem(v: string); + get kilometer(): number; + set kilometer(v: number); + get direction(): Direction; + set direction(v: Direction); +} + +export interface IRelatedRefData { + deviceType: DeviceType; //关联的设备类型 + id: number; //关联的设备ID + devicePort: DevicePort; //关联的设备端口 +} + + +export interface ISignalData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get mirror(): boolean; + set mirror(v: boolean); + get kilometerSystem(): KilometerSystem; + set kilometerSystem(v: KilometerSystem); + get refDev(): IRelatedRefData; + set refDev(v: IRelatedRefData); + get centralizedStations(): number[]; + set centralizedStations(v: number[]); + get mt(): Model; + set mt(v: Model); + get direction(): Direction; + set direction(v: Direction); + clone(): ISignalData; + copyFrom(data: ISignalData): void; + eq(other: ISignalData): boolean; +} + +export interface ISignalState extends GraphicState { + id?: string; + get aspect(): number; + set aspect(v: number); +} + +export enum SignalColorEnum { + humanControlColor = '0xffff00', + fleetModeColor = '0x00ff00', + blockedColor = '0XFF0000', + defaultCodeColor = '0XFFFFFF', + lampPostColor = '0xFFFFFF', + redLamp = '0XFF0000', + greenLamp = '0X00FF00', + yellowLamp = '0XFFFF00', + whiteLamp = '0XFFFFFF', + blueLamp = '0X0033FF', + closeLamp = '0X000000', + logicModeColor = '0x000000', + lampLineColor = '0x3149c3', +} + +export const signalConsts = { + fleetModeLength: 24, + fleetModeRadius: 8, + fleetModeLineWidth: 6, + humanControlRadius: 8, + codeOffset: 20, + codeFontSize: 11, + blockedLineWidth: 1, + verticalLampPostLength: 16, + levelLampPostLength: 4, + postLineWidth: 3, + lampRadius: 8, + logicModeLineWidth: 2, + logicModeDistance: 5, + lampLineWidth: 1, +}; +export class Signal extends JlGraphic { + static Type = 'signal'; + signalCode: SignalCode = new SignalCode(); + humanControl: Graphics = new Graphics(); + fleetMode: Graphics = new Graphics(); + lampMainBody: LampMainBody = new LampMainBody(); + blockedMode: Graphics = new Graphics(); + + constructor() { + super(Signal.Type); + // this.addChild(this.humanControl); + // this.addChild(this.fleetMode); + this.addChild(this.lampMainBody); + this.addChild(this.signalCode); + } + + get datas(): ISignalData { + return this.getDatas(); + } + + get mirror(): boolean { + return this.datas.mirror; + } + set mirror(v: boolean) { + const old = this.datas.clone(); + old.mirror = v; + this.updateData(old); + } + + get states(): ISignalState { + return this.getStates(); + } + + paint(): void { + const mirror = this.datas.mirror; + this.lampMainBody.paint(this.datas.mt, mirror); + this.signalCode.paint(this.datas); + const codeTransform = this.datas?.childTransforms?.find( + (item) => item.name === 'signalCode' + ); + if (codeTransform) { + const position = codeTransform?.transform.position; + const rotation = codeTransform?.transform?.rotation; + this.signalCode.position.set(position?.x, position?.y); + this.signalCode.rotation = rotation || 0; + } else { + this.signalCode.position.set(0, signalConsts.codeOffset); + } + } + + doRepaint(): void { + this.paint(); + } + + chagneState() { + switch (this.states.aspect) { + case Aspect.OFF: + this.setStateOff(); + case Aspect.H: + this.setStateH(); + break; + case Aspect.L: + this.setStateL(); + break; + case Aspect.U: + this.setStateU(); + break; + case Aspect.HU: + this.setStateHu(); + break; + case Aspect.A: + this.setStateA(); + break; + case Aspect.B: + this.setStateB(); + break; + } + } + + /** 设置状态自动进路 */ + // setStateFleetMode(): void { + // const mirror = this.datas.mirror; + // this.fleetMode.beginFill(SignalColorEnum.fleetModeColor, 1); + // let lmp = new Point( + // this.lampMainBody.width + signalConsts.fleetModeLength, + // 0 + // ); + // if (mirror) { + // lmp = calculateMirrorPoint(new Point(0, 0), lmp); + // } + // drawArrow( + // this.fleetMode, + // lmp.x, + // 0, + // signalConsts.fleetModeLength, + // signalConsts.fleetModeRadius, + // signalConsts.fleetModeLineWidth, + // mirror + // ); + // this.fleetMode.endFill(); + // } + /** 设置状态人工控 */ + // setStateHumanControl(): void { + // const mirror = this.datas.mirror; + // this.humanControl.beginFill(SignalColorEnum.humanControlColor, 1); + // if (this.humanControl.drawRegularPolygon) { + // let hmp = new Point(-signalConsts.humanControlRadius, 0); + // if (mirror) { + // hmp = calculateMirrorPoint(new Point(0, 0), hmp); + // } + // this.humanControl.drawRegularPolygon( + // hmp.x, + // hmp.y, + // signalConsts.humanControlRadius, + // 3, + // (Math.PI / 2) * (mirror ? -1 : 1) + // ); + // } + // this.humanControl.endFill(); + // } + /** 设置状态封锁 */ + // setStateBlocked() { + // this.signalCode.createBlockedMode(); + // } + /** 设置状态红灯 */ + setStateH() { + this.lampMainBody.setStateH(); + } + /** 设置状态绿灯 */ + setStateL() { + this.lampMainBody.setStateL(); + } + /** 设置状态黄灯 */ + setStateU() { + this.lampMainBody.setStateU(); + } + /** 设置状态红黄灯 */ + setStateHu() { + this.lampMainBody.setStateHu(); + } + /** 设置状态白灯 */ + setStateA() { + this.lampMainBody.setStateA(); + } + /** 设置状态蓝灯 */ + setStateB() { + this.lampMainBody.setStateB(); + } + /** 设置状态灯位关闭 */ + setStateOff() { + this.lampMainBody.setStateOff(); + } + + buildRelation() { + // .... + } + + loadRelations() { + if (this.datas.refDev) { + this.relationManage.addRelation( + new GraphicRelationParam(this, ''), + new GraphicRelationParam( + this.queryStore.queryById(this.datas.refDev.id), + this.datas.refDev.devicePort + ) + ); + } + } +} + +export class SignalTemplate extends JlGraphicTemplate { + constructor(dataTemplate: ISignalData, stateTemplate: ISignalState) { + super(Signal.Type, { dataTemplate, stateTemplate }); + } + new(): Signal { + const g = new Signal(); + g.loadData(this.datas); + g.loadState(this.states); + return g; + } +} diff --git a/src/packages/Signal/bjRtss/SignalDrawAssistant.ts b/src/packages/Signal/bjRtss/SignalDrawAssistant.ts new file mode 100644 index 0000000..b4871c2 --- /dev/null +++ b/src/packages/Signal/bjRtss/SignalDrawAssistant.ts @@ -0,0 +1,181 @@ +import { DisplayObject, FederatedPointerEvent, IHitArea, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + IDrawApp, + JlGraphic, +} from 'jl-graphic'; + +import { ISignalData, Signal, SignalTemplate } from './Signal'; + +export interface ISignalDrawOptions { + newData: () => ISignalData; +} + +export class SignalDraw extends GraphicDrawAssistant< + SignalTemplate, + ISignalData +> { + _signal: Signal | null = null; + + constructor(app: IDrawApp, template: SignalTemplate) { + super( + app, + template, + 'svguse: ../../drawIcon.svg#icon-signal', + '信号机Signal' + ); + + SignalInteraction.init(app); + } + + public get signal(): Signal { + if (!this._signal) { + this._signal = this.graphicTemplate.new(); + this._signal.loadData(this.graphicTemplate.datas); + this.container.addChild(this._signal); + } + return this._signal; + } + + onLeftUp(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.signal.paint(); + this.container.position.set(p.x, p.y); + } + prepareData(data: ISignalData): boolean { + data.transform = this.container.saveTransform(); + return true; + } +} + +export class SignalGraphicHitArea implements IHitArea { + signal: Signal; + constructor(signal: Signal) { + this.signal = signal; + } + contains(x: number, y: number): boolean { + const bound = this.signal.getLocalBounds(); + const maxX = bound.x + bound.width; + const minX = bound.x; + const maxY = bound.y + bound.height; + const minY = bound.y; + return maxX >= x && x >= minX && maxY >= y && y >= minY; + } +} + +/** + * 构建吸附线 + * @param signal + */ +function buildAbsorbablePositions(signal: Signal): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const signals = signal.queryStore.queryByType(Signal.Type); + const canvas = signal.getCanvas(); + signals.forEach((item) => { + if (item.id === signal.id) { + return; + } + const ala = new AbsorbableLine( + new Point(item.x, 0), + new Point(item.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, item.y), + new Point(canvas.width, item.y) + ); + aps.push(ala); + aps.push(alb); + }); + + return aps; +} +/** + * 信号机名称构建吸附线 + * @param signal + */ +function buildCodeAbsorbablePositions(signal: Signal): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const signals = signal.queryStore.queryByType(Signal.Type); + const canvas = signal.getCanvas(); + signals.forEach((item) => { + if (item.id === signal.id) { + return; + } + const codePoint = item.signalCode.getPositionOnCanvas(); + const ala = new AbsorbableLine( + new Point(codePoint.x, 0), + new Point(codePoint.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, codePoint.y), + new Point(canvas.width, codePoint.y) + ); + aps.push(ala); + aps.push(alb); + }); + return aps; +} + +export class SignalInteraction extends GraphicInteractionPlugin { + static Name = 'signal_transform'; + constructor(app: IDrawApp) { + super(SignalInteraction.Name, app); + } + static init(app: IDrawApp) { + return new SignalInteraction(app); + } + filter(...grahpics: JlGraphic[]): Signal[] | undefined { + return grahpics + .filter((g) => g.type === Signal.Type) + .map((g) => g as Signal); + } + bind(g: Signal): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.lampMainBody.hitArea = new SignalGraphicHitArea(g); + g.on('transformstart', this.transformstart, this); + g.signalCode.on('transformstart', this.codetransformstart, this); + g.signalCode.draggable = true; + g.signalCode.selectable = true; + g.signalCode.rotatable = true; + g.signalCode.transformSave = true; + g.signalCode.eventMode = 'static'; + } + + unbind(g: Signal): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.off('transformstart', this.transformstart, this); + g.signalCode.off('transformstart', this.codetransformstart, this); + g.signalCode.draggable = false; + g.signalCode.selectable = false; + g.signalCode.rotatable = false; + g.signalCode.transformSave = false; + g.signalCode.eventMode = 'none'; + } + transformstart(e: GraphicTransformEvent) { + const target = e.target as DisplayObject; + const signal = target.getGraphic() as Signal; + signal.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(signal), + }); + } + codetransformstart(e: GraphicTransformEvent) { + const target = e.target as DisplayObject; + const signal = target.getGraphic() as Signal; + signal.getGraphicApp().setOptions({ + absorbablePositions: buildCodeAbsorbablePositions(signal), + }); + } +} diff --git a/src/packages/Signal/common/CommonGraphics.ts b/src/packages/Signal/common/CommonGraphics.ts new file mode 100644 index 0000000..56b97f4 --- /dev/null +++ b/src/packages/Signal/common/CommonGraphics.ts @@ -0,0 +1,71 @@ +import { Graphics } from 'pixi.js'; +import { calculateMirrorPoint } from 'jl-graphic'; +/** + * + * @param polygon + * @param x 箭头顶点x坐标 + * @param y 箭头顶点y坐标 + * @param length 箭头长度 + * @param radius 箭头三角半径 + * @param lineWidth 箭头线宽 + * @param mirror 是否镜像翻转 (基于箭头顶点) + */ +export function drawArrow( + polygon: Graphics, + x: number, + y: number, + length: number, + radius: number, + lineWidth: number, + mirror: boolean +) { + const trianglAcme = { x, y }; + let triangleP1 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y + Math.cos(Math.PI / 6) * radius, + }; + let triangleP2 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y - Math.cos(Math.PI / 6) * radius, + }; + let lineP1 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y + lineWidth / 2, + }; + let lineP2 = { + x: x - length, + y: y + lineWidth / 2, + }; + let lineP3 = { + x: x - length, + y: y - lineWidth / 2, + }; + let lineP4 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y - lineWidth / 2, + }; + if (mirror) { + triangleP1 = calculateMirrorPoint(trianglAcme, triangleP1); + triangleP2 = calculateMirrorPoint(trianglAcme, triangleP2); + lineP1 = calculateMirrorPoint(trianglAcme, lineP1); + lineP2 = calculateMirrorPoint(trianglAcme, lineP2); + lineP3 = calculateMirrorPoint(trianglAcme, lineP3); + lineP4 = calculateMirrorPoint(trianglAcme, lineP4); + } + polygon.drawPolygon( + trianglAcme.x, + trianglAcme.y, + triangleP1.x, + triangleP1.y, + lineP1.x, + lineP1.y, + lineP2.x, + lineP2.y, + lineP3.x, + lineP3.y, + lineP4.x, + lineP4.y, + triangleP2.x, + triangleP2.y + ); +} diff --git a/src/packages/Signal/common/Lamp.ts b/src/packages/Signal/common/Lamp.ts new file mode 100644 index 0000000..7473b3e --- /dev/null +++ b/src/packages/Signal/common/Lamp.ts @@ -0,0 +1,102 @@ +import { Container } from '@pixi/display'; +import { Graphics } from 'pixi.js'; +import { SignalColorEnum, signalConsts } from '../bjRtss/Signal'; + +const lampConsts = { + lampLineWidth: 1, + lampBadColor: '0xFF0000', + badStart: 10, + badEnd: 15, +}; + +export class Lamp extends Container { + circleLamp: Graphics = new Graphics(); + logicMode: Graphics = new Graphics(); + radiusX = 0; + radiusY = 0; + + constructor(hasLogic: boolean) { + super(); + this.addChild(this.circleLamp); + if(hasLogic) { + this.addChild(this.logicMode); + } + } + paint(radiusX: number, radiusY: number) { + this.radiusX = radiusX; + this.radiusY = radiusY; + this.createLamp(); + } + + createLampBad() { + this.circleLamp.lineStyle(lampConsts.lampLineWidth, lampConsts.lampBadColor); + this.circleLamp.moveTo(this.radiusX + lampConsts.badStart, this.radiusY); + this.circleLamp.lineTo(this.radiusX + lampConsts.badEnd, this.radiusY); + this.circleLamp.moveTo(this.radiusX - lampConsts.badStart, this.radiusY); + this.circleLamp.lineTo(this.radiusX - lampConsts.badEnd, this.radiusY); + this.circleLamp.moveTo(this.radiusX, this.radiusY + lampConsts.badStart); + this.circleLamp.lineTo(this.radiusX, this.radiusY + lampConsts.badEnd); + this.circleLamp.moveTo(this.radiusX, this.radiusY - lampConsts.badStart); + this.circleLamp.lineTo(this.radiusX, this.radiusY - lampConsts.badEnd); + const xieStart = Math.sin(Math.PI / 4) * lampConsts.badStart; + const xieEnd = Math.sin(Math.PI / 4) * lampConsts.badEnd; + this.circleLamp.moveTo(this.radiusX + xieStart, this.radiusY + xieStart); + this.circleLamp.lineTo(this.radiusX + xieEnd, this.radiusY + xieEnd); + this.circleLamp.moveTo(this.radiusX + xieStart, this.radiusY - xieStart); + this.circleLamp.lineTo(this.radiusX + xieEnd, this.radiusY - xieEnd); + + this.circleLamp.moveTo(this.radiusX - xieStart, this.radiusY - xieStart); + this.circleLamp.lineTo(this.radiusX - xieEnd, this.radiusY - xieEnd); + this.circleLamp.moveTo(this.radiusX - xieStart, this.radiusY + xieStart); + this.circleLamp.lineTo(this.radiusX - xieEnd, this.radiusY + xieEnd); + } + + createLamp(color?: string) { + this.circleLamp.clear(); + this.circleLamp.lineStyle( + signalConsts.lampLineWidth, + SignalColorEnum.lampLineColor + ); + if (!color) { + this.circleLamp.beginFill('0XFFFFFF', 0); + } else { + this.circleLamp.beginFill(color, 1); + } + this.circleLamp.drawCircle( + this.radiusX, + this.radiusY, + signalConsts.lampRadius + ); + this.circleLamp.endFill(); + } + createLogicMode() { + this.logicMode + .clear() + .lineStyle( + signalConsts.logicModeLineWidth, + SignalColorEnum.logicModeColor + ) + .moveTo( + this.radiusX - signalConsts.logicModeDistance, + this.radiusY + signalConsts.logicModeDistance + ) + .lineTo( + this.radiusX + signalConsts.logicModeDistance, + this.radiusY - signalConsts.logicModeDistance + ) + .moveTo( + this.radiusX - signalConsts.logicModeDistance, + this.radiusY - signalConsts.logicModeDistance + ) + .lineTo( + this.radiusX + signalConsts.logicModeDistance, + this.radiusY + signalConsts.logicModeDistance + ); + } + logicModeClear() { + this.logicMode.clear(); + } + lampClear() { + this.circleLamp.clear(); + } +} diff --git a/src/packages/Signal/SignalCode.ts b/src/packages/Signal/common/SignalCode.ts similarity index 97% rename from src/packages/Signal/SignalCode.ts rename to src/packages/Signal/common/SignalCode.ts index bd412c2..ab3f4ec 100644 --- a/src/packages/Signal/SignalCode.ts +++ b/src/packages/Signal/common/SignalCode.ts @@ -4,7 +4,7 @@ import { ISignalData, SignalColorEnum, signalConsts, -} from './Signal'; +} from '../bjRtss/Signal'; export class SignalCode extends Container { blockedMode: Graphics = new Graphics(); diff --git a/src/packages/Signal/LampMainBody.ts b/src/packages/Signal/th/LampMainBody.ts similarity index 97% rename from src/packages/Signal/LampMainBody.ts rename to src/packages/Signal/th/LampMainBody.ts index 664388f..d294a51 100644 --- a/src/packages/Signal/LampMainBody.ts +++ b/src/packages/Signal/th/LampMainBody.ts @@ -3,7 +3,7 @@ import { calculateMirrorPoint, GraphicAnimation, } from 'jl-graphic'; -import { Lamp } from './Lamp'; +import { Lamp } from '../common/Lamp'; import { SignalColorEnum, signalConsts, Model } from './Signal'; export class LampMainBody extends Container { @@ -43,7 +43,7 @@ export class LampMainBody extends Container { this.lamps = []; for (let i = 0; i < this.lampNum; i++) { - const lamp = new Lamp(); + const lamp = new Lamp(true); this.addChild(lamp); const radiusX = (1 + i * 2) * signalConsts.lampRadius + diff --git a/src/packages/Signal/Signal.ts b/src/packages/Signal/th/Signal.ts similarity index 97% rename from src/packages/Signal/Signal.ts rename to src/packages/Signal/th/Signal.ts index 1a2715d..ee224f0 100644 --- a/src/packages/Signal/Signal.ts +++ b/src/packages/Signal/th/Signal.ts @@ -1,8 +1,8 @@ import { GraphicData, calculateMirrorPoint, JlGraphic } from 'jl-graphic' import { Graphics, Point } from 'pixi.js'; -import { SignalCode } from './SignalCode'; +import { SignalCode } from '../common/SignalCode'; import { LampMainBody } from './LampMainBody'; - +/** 信号机类型 */ export enum Model { HL = 0, // 红绿灯 HLU_FU = 1, // 红绿黄,封黄灯,无引导 @@ -11,9 +11,9 @@ export enum Model { HLU_FL_DU_YY = 4, // 红绿黄,封绿灯,有单黄,带引导 HLU_DU = 5, // 红绿黄,不封灯,有单黄,无引导 AB = 6, // 蓝白 - HBU_DU = 7 // 红白黄,不封灯,有单黄,无引导 + HBU_DU = 7, // 红白黄,不封灯,有单黄,无引导 } - +/** 信号机颜色 */ export enum SignalColorEnum { humanControlColor = '0xffff00', fleetModeColor = '0x00ff00', @@ -29,7 +29,7 @@ export enum SignalColorEnum { logicModeColor = '0x000000', lampLineColor = '0x3149c3', } - +/** 信号机常量 */ export const signalConsts = { fleetModeLength: 24, fleetModeRadius: 8, @@ -46,7 +46,7 @@ export const signalConsts = { logicModeDistance: 5, lampLineWidth: 1, }; - +/** 动画 */ const anmiationNameConst = { signaRedFlash: 'signal_red_flash', signalGreenFlash: 'signal_green_flash', @@ -77,6 +77,7 @@ export class Signal extends JlGraphic { this.addChild(this.fleetMode); this.addChild(this.lampMainBody); this.addChild(this.signalCode); + this.signalCode.name = 'signalCode'; } diff --git a/src/packages/SpksSwitch/SpksSwitch.ts b/src/packages/SpksSwitch/SpksSwitch.ts new file mode 100644 index 0000000..d0b3f3f --- /dev/null +++ b/src/packages/SpksSwitch/SpksSwitch.ts @@ -0,0 +1,85 @@ +import { Graphics } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + VectorText, +} from 'jl-graphic'; + +export interface ISpksSwitchData extends GraphicData{ + code: string; + flip: boolean; +} + +const spksSwitchConsts = { + codeFontSize: 12, + codeColor: 0xffffff, + bodyLineColor: 0xffffff, + bodyLineWidth: 4, + bodyRectLineColor: 0xffffff, + bodyRectLineWidth: 2, + bodyRectWidth: 20, + bodyRectHeight: 20, + bodyColor: 0x000000, +}; +export class SpksSwitch extends JlGraphic { + static Type = 'spksSwitch'; + datas: ISpksSwitchData; + codeGraph: VectorText = new VectorText(''); + rectBody: Graphics = new Graphics(); + lineBody: Graphics = new Graphics(); + textGraph: VectorText = new VectorText('S'); + + constructor(datas: ISpksSwitchData) { + super(SpksSwitch.Type); + this.datas = datas; + this.addChild(this.codeGraph); + this.addChild(this.rectBody); + this.addChild(this.lineBody); + this.addChild(this.textGraph); + this.textGraph.name = 'spks_switch_code'; + } + doRepaint(): void { + const codeGraph = this.codeGraph; + codeGraph.text = this.datas.code; + codeGraph.style.fill = spksSwitchConsts.codeColor; + codeGraph.setVectorFontSize(spksSwitchConsts.codeFontSize); + const codeTransform = this.datas?.childTransforms?.find( + (item) => item.name === 'spks_switch_code' + ); + if (codeTransform) { + const position = codeTransform?.transform.position; + const rotation = codeTransform?.transform?.rotation; + codeGraph.position.set(position?.x, position?.y); + codeGraph.rotation = rotation || 0; + } else { + codeGraph.position.set(20, 0); + } + codeGraph.anchor.set(0.5); + this.textGraph.style.fill = spksSwitchConsts.codeColor; + this.textGraph.setVectorFontSize(spksSwitchConsts.codeFontSize); + this.textGraph.anchor.set(0.5); + this.rectBody.clear(); + this.rectBody.beginFill(spksSwitchConsts.bodyColor, 0); + this.rectBody.lineStyle( + spksSwitchConsts.bodyRectLineWidth, + spksSwitchConsts.bodyRectLineColor + ); + this.rectBody.drawRect( + -spksSwitchConsts.bodyRectWidth / 2, + -spksSwitchConsts.bodyRectHeight / 2, + spksSwitchConsts.bodyRectWidth, + spksSwitchConsts.bodyRectHeight + ); + this.rectBody.endFill(); + this.lineBody.clear(); + const lineY = this.datas.flip + ? spksSwitchConsts.bodyRectHeight / 2 + : -spksSwitchConsts.bodyRectHeight / 2; + this.lineBody.lineStyle( + spksSwitchConsts.bodyLineWidth, + spksSwitchConsts.bodyLineColor + ); + this.lineBody.moveTo(-spksSwitchConsts.bodyRectWidth / 2, lineY); + this.lineBody.lineTo(spksSwitchConsts.bodyRectWidth / 2, lineY); + } +}