diff --git a/src/components/draw-app/DrawProperties.vue b/src/components/draw-app/DrawProperties.vue index 788d6ee..17fb7bb 100644 --- a/src/components/draw-app/DrawProperties.vue +++ b/src/components/draw-app/DrawProperties.vue @@ -77,6 +77,10 @@ drawStore.selectedGraphicType === AxleCountingSection.Type " > + + @@ -104,6 +108,7 @@ import StationProperty from './properties/StationProperty.vue'; import TrainWindowProperty from './properties/TrainWindowProperty.vue'; import AxleCountingProperty from './properties/AxleCountingProperty.vue'; import AxleCountingSectionProperty from './properties/AxleCountingSectionProperty.vue'; +import LogicSectionProperty from './properties/LogicSectionProperty.vue'; import SignalProperty from './properties/SignalProperty.vue'; import TurnoutProperty from './properties/TurnoutProperty.vue'; import SectionProperty from './properties/SectionProperty.vue'; @@ -121,6 +126,7 @@ import { Section } from 'src/graphics/section/Section'; import { TrainWindow } from 'src/graphics/trainWindow/TrainWindow'; import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting'; import { AxleCountingSection } from 'src/graphics/axleCountingSection/AxleCountingSection'; +import { LogicSection } from 'src/graphics/logicSection/LogicSection'; import { Separator } from 'src/graphics/separator/Separator'; import { SectionLink } from 'src/graphics/sectionLink/SectionLink'; diff --git a/src/components/draw-app/properties/AxleCountingProperty.vue b/src/components/draw-app/properties/AxleCountingProperty.vue index c503ea4..22244b8 100644 --- a/src/components/draw-app/properties/AxleCountingProperty.vue +++ b/src/components/draw-app/properties/AxleCountingProperty.vue @@ -6,6 +6,15 @@ v-model="axleCountingModel.id" label="id" hint="" + /> + + - - 关联的计轴
+ {{ item }} + +
+
+
+ + + + 关联道岔的位置关系 +
+ { +const axleCountingRelations = computed(() => { const axleCountingSection = drawStore.selectedGraphic as AxleCountingSection; const sectionRelations = axleCountingSection?.relationManage.getRelationsOfGraphicAndOtherType( @@ -112,7 +118,22 @@ const sectionRelations = computed(() => { (relation) => `${ relation.getOtherGraphic(axleCountingSection).datas.code - }(${relation.getOtherRelationParam(axleCountingSection).param})` + }` + ); + return Array.from(new Set(ref)); +}); + +const turnoutRelations = computed(() => { + const axleCountingSection = drawStore.selectedGraphic as AxleCountingSection; + const refTurnoutAndPos: { turnout: Turnout; pos: number }[] = []; + axleCountingSection?.datas.turnoutPosRef.forEach((ref) => { + const refTurout = axleCountingSection.queryStore.queryById( + ref.id + ) as Turnout; + refTurnoutAndPos.push({ turnout: refTurout, pos: ref.position }); + }); + const ref = refTurnoutAndPos.map( + (ref) => `${ref.turnout.datas.code}:${turoutPos[ref.pos]}` ); return Array.from(new Set(ref)); }); diff --git a/src/components/draw-app/properties/LogicSectionProperty.vue b/src/components/draw-app/properties/LogicSectionProperty.vue new file mode 100644 index 0000000..8c51724 --- /dev/null +++ b/src/components/draw-app/properties/LogicSectionProperty.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/drawApp/graphics/AxleCountingInteraction.ts b/src/drawApp/graphics/AxleCountingInteraction.ts index ed80bfd..64adf28 100644 --- a/src/drawApp/graphics/AxleCountingInteraction.ts +++ b/src/drawApp/graphics/AxleCountingInteraction.ts @@ -44,6 +44,12 @@ export class AxleCountingData set axleCountingRef(points: graphicData.RelatedRef[]) { this.data.axleCountingRef = points; } + get indexNumber(): number { + return this.data.indexNumber; + } + set indexNumber(v: number) { + this.data.indexNumber = v; + } clone(): AxleCountingData { return new AxleCountingData(this.data.cloneMessage()); } diff --git a/src/drawApp/graphics/AxleCountingSectionInteraction.ts b/src/drawApp/graphics/AxleCountingSectionInteraction.ts index 72d3770..053c76d 100644 --- a/src/drawApp/graphics/AxleCountingSectionInteraction.ts +++ b/src/drawApp/graphics/AxleCountingSectionInteraction.ts @@ -3,6 +3,7 @@ import { GraphicDataBase } from './GraphicDataBase'; import { IAxleCountingSectionData, AxleCountingSection, + ITurnoutPosRefData, } from 'src/graphics/axleCountingSection/AxleCountingSection'; import { graphicData } from 'src/protos/stationLayoutGraphics'; import { IPointData } from 'pixi.js'; @@ -51,6 +52,18 @@ export class AxleCountingSectionData set pbRef(ref: graphicData.RelatedRef) { this.data.pbRef = ref; } + get turnoutPosRef(): ITurnoutPosRefData[] { + return this.data.turnoutPos; + } + set turnoutPosRef(points: ITurnoutPosRefData[]) { + this.data.turnoutPos = points.map((p) => new graphicData.TurnoutPosRef(p)); + } + get indexNumber(): number { + return this.data.indexNumber; + } + set indexNumber(v: number) { + this.data.indexNumber = v; + } clone(): AxleCountingSectionData { return new AxleCountingSectionData(this.data.cloneMessage()); } diff --git a/src/drawApp/graphics/LogicSectionInteraction.ts b/src/drawApp/graphics/LogicSectionInteraction.ts new file mode 100644 index 0000000..a8bef9f --- /dev/null +++ b/src/drawApp/graphics/LogicSectionInteraction.ts @@ -0,0 +1,63 @@ +import * as pb_1 from 'google-protobuf'; +import { GraphicDataBase } from './GraphicDataBase'; +import { + ILogicSectionData, + LogicSection, +} from 'src/graphics/logicSection/LogicSection'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { IPointData } from 'pixi.js'; + +export class LogicSectionData + extends GraphicDataBase + implements ILogicSectionData +{ + constructor(data?: graphicData.LogicSection) { + let logicSection; + if (!data) { + logicSection = new graphicData.AxleCountingSection({ + common: GraphicDataBase.defaultCommonInfo(LogicSection.Type), + }); + } else { + logicSection = data; + } + super(logicSection); + } + public get data(): graphicData.LogicSection { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get points(): IPointData[] { + return this.data.points; + } + set points(points: IPointData[]) { + this.data.points = points.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + } + get axleSectionId(): string { + return this.data.axleSectionId; + } + set axleSectionId(v: string) { + this.data.axleSectionId = v; + } + get indexNumber(): number { + return this.data.indexNumber; + } + set indexNumber(v: number) { + this.data.indexNumber = v; + } + clone(): LogicSectionData { + return new LogicSectionData(this.data.cloneMessage()); + } + copyFrom(data: LogicSectionData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: LogicSectionData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/TrainInteraction.ts b/src/drawApp/graphics/TrainInteraction.ts index 95d7f42..687e8bc 100644 --- a/src/drawApp/graphics/TrainInteraction.ts +++ b/src/drawApp/graphics/TrainInteraction.ts @@ -47,18 +47,22 @@ export class TrainData extends GraphicDataBase implements ITrainData { } export class TrainState extends GraphicStateBase implements ITrainState { - constructor(proto?: StateTrain) { + constructor(proto?: train.TrainInfo) { let states; if (proto) { states = proto; } else { - states = new StateTrain(); + states = new train.TrainInfo(); } super(states, Train.Type); } - get states(): StateTrain { - return this.getState(); + get code(): string { + return this.states.trainIndex; + } + + get states(): train.TrainInfo { + return this.getState(); } get lineId(): number { @@ -94,11 +98,11 @@ export class TrainState extends GraphicStateBase implements ITrainState { set devName(v: string) { this.states.devName = v; } - get id(): string { - return this.states.id; + get trainIndex(): string { + return this.states.trainIndex; } - set id(v: string) { - this.states.id = v; + set trainIndex(v: string) { + this.states.trainIndex = v; } get groupId(): string { return this.states.groupId; @@ -169,12 +173,6 @@ export class TrainState extends GraphicStateBase implements ITrainState { set speed(v: number) { this.states.speed = v; } - get show(): boolean { - return this.states.show; - } - set show(v: boolean) { - this.states.show = v; - } get type(): boolean { return this.states.type; } @@ -193,27 +191,48 @@ export class TrainState extends GraphicStateBase implements ITrainState { set rate(v: number) { this.states.rate = v; } + get remove(): train.TrainRemove { + return this.states.remove; + } + set remove(v: train.TrainRemove) { + this.states.remove = v; + } + get block(): train.TrainBlock { + return this.states.block; + } + set block(v: train.TrainBlock) { + this.states.block = v; + } + get record(): train.TrainRecord { + return this.states.record; + } + set record(v: train.TrainRecord) { + this.states.record = v; + } clone(): TrainState { return new TrainState(this.states.cloneMessage()); } -} - -class StateTrain extends train.TrainInfo { - id: string; - constructor(data?: train.TrainInfo) { - super(data); - if (data?.trainIndex) { - this.id = data?.trainIndex; - } else { - this.id = ''; - } + copyFrom(data: GraphicStateBase): void { + pb_1.Message.copyInto(data._state, this._state); + } + eq(data: GraphicStateBase): boolean { + return pb_1.Message.equals(this._state, data._state); } } const negativeDirectionConfig: MenuItemOptions = { name: '反方向运行', }; +const runStopConfig: MenuItemOptions = { + name: '前进/停止', +}; +const diriveModelConfig: MenuItemOptions = { + name: '驾驶模式', +}; +const accuracyConfig: MenuItemOptions = { + name: '正常/早点/晚点', +}; const HoldTrainConfig: MenuItemOptions = { name: '扣车', }; @@ -229,6 +248,9 @@ const TrainOperateMenu: ContextMenu = ContextMenu.init({ { items: [ negativeDirectionConfig, + runStopConfig, + diriveModelConfig, + accuracyConfig, HoldTrainConfig, openDoorConfig, editGroupConfig, @@ -275,20 +297,73 @@ export class TrainOperateInteraction extends GraphicInteractionPlugin { mode.ipModeTrainDirUp = false; mode.ipModeTrainDirDown = true; } - train.chagneDirection(); + train.doRepaint(); + }; + runStopConfig.handler = () => { + train.states.mode.ipModeTrainStoped = + !train.states.mode.ipModeTrainStoped; + train.doRepaint(); + }; + diriveModelConfig.handler = () => { + const arr: Array = [ + 'ipModeTrainDriveModeAm', + 'ipModeTrainDriveModeCm', + 'ipModeTrainDriveBlockAm', + 'ipModeTrainDriveBlockCm', + 'ipModeTrainDriveModeRmf', + ]; + let findIndex = arr.findIndex((key) => { + return train.states.mode[key]; + }); + if (findIndex == arr.length - 1) { + findIndex = -1; + } + arr.forEach((key) => { + (train.states.mode[key] as boolean) = false; + }); + (train.states.mode[arr[findIndex + 1]] as boolean) = true; + train.doRepaint(); }; HoldTrainConfig.handler = () => { train.states.mode.ipModeTrainHolded = !train.states.mode.ipModeTrainHolded; - train.chagneState(); + train.doRepaint(); + }; + accuracyConfig.handler = () => { + const arr: Array = [ + 'ipModeTrainTypeSchedule', + 'ipModeTrainSchdEarly', + 'ipModeTrainSchdLate', + ]; + let findIndex = -1; + arr.forEach((key, index) => { + if (train.states.mode[key]) { + findIndex = index; + } + }); + arr.forEach((key, index) => { + if (index != 0) { + (train.states.mode[key] as boolean) = false; + } + }); + if (findIndex != arr.length - 1) { + train.states.mode.ipModeTrainTypeSchedule = true; + } + if (findIndex == arr.length - 1) { + train.states.mode.ipModeTrainTypeSchedule = false; + } else { + (train.states.mode[arr[findIndex + 1]] as boolean) = true; + } + train.doRepaint(); }; openDoorConfig.handler = () => { train.states.mode.ipModeTrainDoorOpen = !train.states.mode.ipModeTrainDoorOpen; - train.chagneState(); + train.doRepaint(); }; editGroupConfig.handler = () => { - train.states.trainId = '022'; + train.states.trainId = '02'; + train.states.destinationId = 123; train.doRepaint(); }; TrainOperateMenu.open(e.global); diff --git a/src/drawApp/index.ts b/src/drawApp/index.ts index 04db814..6a3576c 100644 --- a/src/drawApp/index.ts +++ b/src/drawApp/index.ts @@ -71,6 +71,12 @@ import { } from 'src/graphics/sectionLink/SectionLink'; import { SectionLinkDraw } from 'src/graphics/sectionLink/SectionLinkDrawAssistant'; import { SectionLinkData } from './graphics/SectionLinkInteraction'; +import { LogicSectionDraw } from 'src/graphics/logicSection/LogicSectionDrawAssistant'; +import { + LogicSection, + LogicSectionTemplate, +} from 'src/graphics/logicSection/LogicSection'; +import { LogicSectionData } from './graphics/LogicSectionInteraction'; // export function fromStoragePoint(p: graphicData.Point): Point { // return new Point(p.x, p.y); @@ -111,14 +117,17 @@ const RedoOptions: MenuItemOptions = { const SelectAllOptions: MenuItemOptions = { name: '全选', }; -const oneLayerOptions: MenuItemOptions = { - name: '图层一', +const AllOptions: MenuItemOptions = { + name: '全部图层', }; -const twoLayerOptions: MenuItemOptions = { - name: '图层二', +const linkOptions: MenuItemOptions = { + name: '图层-Link', }; -const threeLayerOptions: MenuItemOptions = { - name: '图层三', +const axleCountingSectionOptions: MenuItemOptions = { + name: '图层-计轴区段', +}; +const LogicSectionOptions: MenuItemOptions = { + name: '图层-逻辑区段', }; const layerOptions: MenuItemOptions = { @@ -126,7 +135,12 @@ const layerOptions: MenuItemOptions = { subMenu: [ { name: '图层菜单', - items: [oneLayerOptions, twoLayerOptions, threeLayerOptions], + items: [ + AllOptions, + linkOptions, + axleCountingSectionOptions, + LogicSectionOptions, + ], }, ], }; @@ -178,6 +192,7 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { | SeparatorDraw | SectionLinkDraw | AxleCountingSectionDraw + | LogicSectionDraw )[] = []; if (draftType === 'Line') { drawAssistants = [ @@ -211,6 +226,10 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { app, new AxleCountingSectionTemplate(new AxleCountingSectionData()) ), + new LogicSectionDraw( + app, + new LogicSectionTemplate(new LogicSectionData()) + ), ]; DrawSignalInteraction.init(app); } @@ -223,17 +242,23 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { if (app._drawing) return; UndoOptions.disabled = !app.opRecord.hasUndo; RedoOptions.disabled = !app.opRecord.hasRedo; - const axleCountings = app.queryStore.queryByType( - AxleCounting.Type - ); - const trainWindows = app.queryStore.queryByType( - TrainWindow.Type + const axleCountingSections = + app.queryStore.queryByType(AxleCountingSection.Type); + const logicSections = app.queryStore.queryByType( + LogicSection.Type ); const sections = app.queryStore.queryByType
(Section.Type); const sectionLinks = app.queryStore.queryByType( SectionLink.Type ); const turnouts = app.queryStore.queryByType(Turnout.Type); + const disvisibleGraphics = [ + ...sections, + ...turnouts, + ...sectionLinks, + ...axleCountingSections, + ...logicSections, + ]; UndoOptions.handler = () => { app.opRecord.undo(); }; @@ -243,31 +268,33 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp { SelectAllOptions.handler = () => { app.selectAllGraphics(); }; - oneLayerOptions.handler = () => { - axleCountings.forEach((axleCounting) => { - axleCounting.visible = false; - }); - sections.forEach((section) => { - section.visible = false; - }); - sectionLinks.forEach((sectionLink) => { - sectionLink.visible = true; - }); - turnouts.forEach((turnout) => { - turnout.visible = false; + AllOptions.handler = () => { + disvisibleGraphics.forEach((g) => { + g.visible = true; }); }; - twoLayerOptions.handler = () => { - trainWindows.forEach((trainWindow) => { - trainWindow.visible = false; + linkOptions.handler = () => { + disvisibleGraphics.forEach((g) => { + g.visible = false; + }); + sectionLinks.forEach((axleCountingSection) => { + axleCountingSection.visible = true; }); }; - threeLayerOptions.handler = () => { - axleCountings.forEach((axleCounting) => { - axleCounting.visible = true; + axleCountingSectionOptions.handler = () => { + disvisibleGraphics.forEach((g) => { + g.visible = false; }); - trainWindows.forEach((trainWindow) => { - trainWindow.visible = true; + axleCountingSections.forEach((axleCountingSection) => { + axleCountingSection.visible = true; + }); + }; + LogicSectionOptions.handler = () => { + disvisibleGraphics.forEach((g) => { + g.visible = false; + }); + logicSections.forEach((logicSection) => { + logicSection.visible = true; }); }; DefaultCanvasMenu.open(e.global); @@ -352,6 +379,9 @@ export function saveDrawDatas(app: JlDrawApp) { storage.axleCountingSections.push( (axleCountingSectionData as AxleCountingSectionData).data ); + } else if (LogicSection.Type === g.type) { + const logicSectionData = (g as LogicSection).saveData(); + storage.logicSections.push((logicSectionData as LogicSectionData).data); } }); const base64 = fromUint8Array(storage.serialize()); @@ -416,8 +446,30 @@ export async function loadDrawDatas(app: GraphicApp) { storage.axleCountingSections.forEach((axleCountingSection) => { datas.push(new AxleCountingSectionData(axleCountingSection)); }); - app.loadGraphic(datas); + storage.logicSections.forEach((logicSection) => { + datas.push(new LogicSectionData(logicSection)); + }); + await app.loadGraphic(datas); } else { app.loadGraphic([]); } + //隐藏计轴区段--Link + const axleCountingSections = app.queryStore.queryByType( + AxleCountingSection.Type + ); + axleCountingSections.forEach((axleCountingSection) => { + axleCountingSection.visible = false; + }); + const sectionLinks = app.queryStore.queryByType( + SectionLink.Type + ); + sectionLinks.forEach((sectionLink) => { + sectionLink.visible = false; + }); + const logicSections = app.queryStore.queryByType( + LogicSection.Type + ); + logicSections.forEach((logicSection) => { + logicSection.visible = false; + }); } diff --git a/src/graphics/axleCounting/AxleCounting.ts b/src/graphics/axleCounting/AxleCounting.ts index 5538fb9..1334812 100644 --- a/src/graphics/axleCounting/AxleCounting.ts +++ b/src/graphics/axleCounting/AxleCounting.ts @@ -16,6 +16,8 @@ export interface IAxleCountingData extends GraphicData { set kilometerSystem(v: KilometerSystem); get axleCountingRef(): IRelatedRefData[]; //关联的设备 set axleCountingRef(ref: IRelatedRefData[]); + get indexNumber(): number; // 索引编号 + set indexNumber(v: number); clone(): IAxleCountingData; copyFrom(data: IAxleCountingData): void; eq(other: IAxleCountingData): boolean; diff --git a/src/graphics/axleCounting/AxleCountingDrawAssistant.ts b/src/graphics/axleCounting/AxleCountingDrawAssistant.ts index 3c62ab5..7ac26b5 100644 --- a/src/graphics/axleCounting/AxleCountingDrawAssistant.ts +++ b/src/graphics/axleCounting/AxleCountingDrawAssistant.ts @@ -14,7 +14,6 @@ import { IAxleCountingData, AxleCounting, AxleCountingTemplate, - AxleCountingConsts, } from './AxleCounting'; import { Section, SectionPort, SectionType } from '../section/Section'; import { Turnout, TurnoutPort } from '../turnout/Turnout'; @@ -119,7 +118,7 @@ export class AxleCountingDraw extends GraphicDrawAssistant< } axleCounting.id = GraphicIdGenerator.next(); axleCounting.datas.axleCountingRef = [refData2, refData1]; - axleCounting.datas.code = `${graphic.datas.code}-${port}+${refGraphic.datas.code}-${refPort}`; + axleCounting.datas.code = `${graphic.datas.code}-${port}\\${refGraphic.datas.code}-${refPort}`; this.storeGraphic(axleCounting); axleCounting.loadRelations(); } diff --git a/src/graphics/axleCountingSection/AxleCountingSection.ts b/src/graphics/axleCountingSection/AxleCountingSection.ts index 3c445b8..3918ce5 100644 --- a/src/graphics/axleCountingSection/AxleCountingSection.ts +++ b/src/graphics/axleCountingSection/AxleCountingSection.ts @@ -9,15 +9,26 @@ import { import { IRelatedRefData, protoPort2Data } from '../CommonGraphics'; import { SectionPort } from '../section/Section'; +export interface ITurnoutPosRefData { + get id(): string; //道岔的ID + set id(v: string); + get position(): number; //道岔的正反为,0是正位,1是反位 + set position(v: number); +} + export interface IAxleCountingSectionData extends GraphicData { get code(): string; // 编号 set code(v: string); get points(): IPointData[]; // 线坐标点 set points(points: IPointData[]); - get paRef(): IRelatedRefData | undefined; + get paRef(): IRelatedRefData | undefined; //区段A端关联的设备 set paRef(ref: IRelatedRefData | undefined); - get pbRef(): IRelatedRefData | undefined; + get pbRef(): IRelatedRefData | undefined; //区段B端关联的设备 set pbRef(ref: IRelatedRefData | undefined); + get turnoutPosRef(): ITurnoutPosRefData[]; //关联道岔的定反位--0是定位,1是反位 + set turnoutPosRef(ref: ITurnoutPosRefData[]); + get indexNumber(): number; // 索引编号 + set indexNumber(v: number); clone(): IAxleCountingSectionData; copyFrom(data: IAxleCountingSectionData): void; eq(other: IAxleCountingSectionData): boolean; @@ -105,6 +116,17 @@ export class AxleCountingSection extends JlGraphic { ) ); } + if (this.datas?.turnoutPosRef.length) { + this.datas.turnoutPosRef.forEach((ref) => { + this.relationManage.addRelation( + this, + new GraphicRelationParam( + this.queryStore.queryById(ref.id), + ref.position + ) + ); + }); + } } } diff --git a/src/graphics/axleCountingSection/AxleCountingSectionAssistant.ts b/src/graphics/axleCountingSection/AxleCountingSectionAssistant.ts index a0da3ce..6d9e64e 100644 --- a/src/graphics/axleCountingSection/AxleCountingSectionAssistant.ts +++ b/src/graphics/axleCountingSection/AxleCountingSectionAssistant.ts @@ -1,19 +1,19 @@ import { + DisplayObject, + FederatedMouseEvent, FederatedPointerEvent, IHitArea, - IPoint, IPointData, Point, } from 'pixi.js'; import { - AbsorbableLine, - AbsorbablePosition, GraphicDrawAssistant, GraphicIdGenerator, GraphicInteractionPlugin, JlDrawApp, JlGraphic, linePoint, + splitLineEvenly, } from 'src/jl-graphic'; import { @@ -21,16 +21,23 @@ import { AxleCountingSection, AxleCountingSectionTemplate, AxleCountingSectionConsts, + ITurnoutPosRefData, } from './AxleCountingSection'; import { AxleCounting } from '../axleCounting/AxleCounting'; -import { Section } from '../section/Section'; import { Turnout } from '../turnout/Turnout'; import { createRelatedRefProto } from '../CommonGraphics'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { Dialog } from 'quasar'; +import { LogicSection } from '../logicSection/LogicSection'; +import { LogicSectionData } from 'src/drawApp/graphics/LogicSectionInteraction'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import SectionSplitDialog from 'src/components/draw-app/dialogs/SectionSplitDialog.vue'; -function hasCommonElements(arr1: string[], arr2: string[]): boolean { +function hasCommonElements(arr1: string[], arr2: string[]) { for (let i = 0; i < arr1.length; i++) { if (arr2.includes(arr1[i])) { - return true; + return arr1[i]; } } return false; @@ -59,7 +66,7 @@ export class AxleCountingSectionDraw extends GraphicDrawAssistant< super(app, template, 'sym_o_circle', '不展示'); this.codeGraph = this.graphicTemplate.new(); this.container.addChild(this.codeGraph); - AxleCountingSectionInteraction.init(app); + AxleCountingSectionInteraction.init(app, this); } bind(): void { @@ -83,13 +90,17 @@ export class AxleCountingSectionDraw extends GraphicDrawAssistant< data.transform = this.container.saveTransform(); return true; } - draw(graphics: AxleCounting[]) { - /* const paRefPs = this.app.queryStore.queryById( - graphics[0].datas.axleCountingRef[0].id - ); - const RepbRefPs = this.app.queryStore.queryById( - graphics[1].datas.axleCountingRef[0].id - ); */ + draw( + graphics: AxleCounting[], + commonElement: JlGraphic[], + map: Map, + turoutPos?: number + ) { + if ( + map.has(`${graphics[0].id}+${graphics[1].id}`) || + map.has(`${graphics[1].id}+${graphics[0].id}`) + ) + return; const axleCountingSection = new AxleCountingSection(); axleCountingSection.loadData(this.graphicTemplate.datas); axleCountingSection.datas.points = [ @@ -99,18 +110,48 @@ export class AxleCountingSectionDraw extends GraphicDrawAssistant< axleCountingSection.id = GraphicIdGenerator.next(); const paRef = createRelatedRefProto(graphics[0].type, graphics[0].id); const pbRef = createRelatedRefProto(graphics[1].type, graphics[1].id); + const turnoutPosData: ITurnoutPosRefData[] = []; + if (commonElement[0].type == 'Turnout') { + commonElement.forEach((Turnout) => { + if (commonElement.length > 1) { + turnoutPosData.push({ + id: Turnout.id, + position: 0, + }); + } else { + if (turoutPos == 0) { + turnoutPosData.push({ + id: Turnout.id, + position: 0, + }); + } else { + turnoutPosData.push({ + id: Turnout.id, + position: 1, + }); + } + } + }); + } axleCountingSection.datas.paRef = paRef; axleCountingSection.datas.pbRef = pbRef; + axleCountingSection.datas.turnoutPosRef = turnoutPosData; this.storeGraphic(axleCountingSection); axleCountingSection.loadRelations(); } oneGenerates() { - const axleCountingSectionAll = + const map = new Map(); + const axleCountingSections = this.app.queryStore.queryByType( AxleCountingSection.Type ); - this.app.deleteGraphics(...axleCountingSectionAll); + axleCountingSections.forEach((axleCountingSection) => { + map.set( + `${axleCountingSection.datas.paRef?.id}+${axleCountingSection.datas.pbRef?.id}`, + 1 + ); + }); const axleCountings = this.app.queryStore.queryByType( AxleCounting.Type ); @@ -124,80 +165,128 @@ export class AxleCountingSectionDraw extends GraphicDrawAssistant< const refDevice = axleCountings[i].datas.axleCountingRef.map( (ref) => ref.id ); - if (hasCommonElements(refDeviceTarget, refDevice)) { - this.draw([axleCounting, axleCountings[i]]); + const commonElementId = hasCommonElements(refDeviceTarget, refDevice); + if (commonElementId) { + const commonElement = this.app.queryStore.queryById(commonElementId); + let draw = true; + let turoutPos = 0; + //道岔BC端处的计轴不构成计轴区段 + if (commonElement.type == 'Turnout') { + let targetPort, port; + axleCounting.datas.axleCountingRef.forEach((ref) => { + if (ref.id == commonElementId) { + targetPort = ref.devicePort; + } + }); + axleCountings[i].datas.axleCountingRef.forEach((ref) => { + if (ref.id == commonElementId) { + port = ref.devicePort; + } + }); + if ( + (targetPort == 1 && port == 2) || + (targetPort == 2 && port == 1) + ) { + draw = false; + } + if (targetPort == 2 || port == 2) { + turoutPos = 1; + } + } + if (draw) { + this.draw( + [axleCounting, axleCountings[i]], + [commonElement], + map, + turoutPos + ); + } } if (hasSamePosition(axleCounting, axleCountings[i])) { hasfourTurnout.push([axleCounting, axleCountings[i]]); } } }); - const fourTurnout: Turnout[] = []; + //补4个道岔处的BB连接处的计轴区段 + const fourAxleCounting: { + axleCounting: AxleCounting; + refTurout: Turnout; + }[] = []; hasfourTurnout.forEach((axleCountings) => { - const axleCountingRelations = - axleCountings[0].relationManage.getRelationsOfGraphicAndOtherType( - axleCountings[0], - Turnout.Type - ); - axleCountingRelations.forEach((relation) => { - const refDevice = relation.getOtherGraphic
(axleCountings[0]); - fourTurnout; + axleCountings.forEach((axleCounting) => { + //计轴关联的道岔 + const axleCountingRelations = + axleCounting.relationManage.getRelationsOfGraphicAndOtherType( + axleCounting, + Turnout.Type + ); + axleCountingRelations.forEach((relation) => { + const refTurnout = relation.getOtherGraphic(axleCounting); + //道岔关联的计轴 + const turnoutRelations = + refTurnout.relationManage.getRelationsOfGraphicAndOtherType( + refTurnout, + AxleCounting.Type + ); + turnoutRelations.forEach((relation) => { + const refAxleCounting = + relation.getOtherGraphic(refTurnout); + if ( + refAxleCounting.id !== axleCountings[0].id && + refAxleCounting.id !== axleCountings[1].id + ) { + fourAxleCounting.push({ + axleCounting: refAxleCounting, + refTurout: refTurnout, + }); + } + }); + }); }); }); - - /* axleCountings.sort((a, b) => a.x - b.x); - const downAxleCountings = axleCountings.filter((point) => { - return point.y > 350; - }); - for (let i = 0; i < downAxleCountings.length - 1; i++) { - const firstRef = downAxleCountings[i].datas.axleCountingRef.map( - (ref) => ref.id - ); - const nextRef = downAxleCountings[i + 1].datas.axleCountingRef.map( - (ref) => ref.id - ); - let nextNextRef: string[] = []; - if (i + 2 < downAxleCountings.length) { - nextNextRef = downAxleCountings[i + 2].datas.axleCountingRef.map( - (ref) => ref.id - ); + for (let x = 0; x < fourAxleCounting.length; x += 4) { + const AxleCountings = fourAxleCounting.slice(x, x + 4); + for (let y = 0; y < 4; y++) { + if ( + fourAxleCounting[x].axleCounting.id == + AxleCountings[y].axleCounting.id + ) + continue; + if ( + fourAxleCounting[x].axleCounting.y == AxleCountings[y].axleCounting.y + ) { + this.draw( + [fourAxleCounting[x].axleCounting, AxleCountings[y].axleCounting], + [fourAxleCounting[x].refTurout, AxleCountings[y].refTurout], + map + ); + break; + } } - if (hasCommonElements(firstRef, nextRef)) { - this.draw([downAxleCountings[i], downAxleCountings[i + 1]]); - } else if ( - hasSamePosition( - downAxleCountings[i + 1].position, - downAxleCountings[i + 2].position - ) && - hasCommonElements(firstRef, nextNextRef) - ) { - this.draw([downAxleCountings[i], downAxleCountings[i + 2]]); - i += 2; + for (let y = 0; y < 4; y++) { + if ( + fourAxleCounting[x + 1].axleCounting.id == + AxleCountings[y].axleCounting.id + ) + continue; + if ( + fourAxleCounting[x + 1].axleCounting.y == + AxleCountings[y].axleCounting.y + ) { + this.draw( + [ + fourAxleCounting[x + 1].axleCounting, + AxleCountings[y].axleCounting, + ], + [fourAxleCounting[x + 1].refTurout, AxleCountings[y].refTurout], + map + ); + break; + } } - } */ + } } } - -function buildAbsorbablePositions( - axleCountingSection: AxleCountingSection -): AbsorbablePosition[] { - const aps: AbsorbablePosition[] = []; - const axleCountingSections = - axleCountingSection.queryStore.queryByType( - AxleCountingSection.Type - ); - const { width } = axleCountingSection.getGraphicApp().canvas; - axleCountingSections.forEach((other) => { - if (other.id == axleCountingSection.id) { - return; - } - const ps = other.datas.transform.position; - const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y }); - aps.push(xs); - }); - return aps; -} - class AxleCountingSectionGraphicHitArea implements IHitArea { axleCountingSection: AxleCountingSection; constructor(axleCountingSection: AxleCountingSection) { @@ -215,13 +304,28 @@ class AxleCountingSectionGraphicHitArea implements IHitArea { } } +export const splitSectionConfig: MenuItemOptions = { + name: '拆分计轴区段', +}; +const SectionEditMenu: ContextMenu = ContextMenu.init({ + name: '区段编辑菜单', + groups: [ + { + items: [splitSectionConfig], + }, + ], +}); + export class AxleCountingSectionInteraction extends GraphicInteractionPlugin { static Name = 'AxleCountingSection_transform'; - constructor(app: JlDrawApp) { + drawAssistant: AxleCountingSectionDraw; + constructor(app: JlDrawApp, da: AxleCountingSectionDraw) { super(AxleCountingSectionInteraction.Name, app); + this.drawAssistant = da; + app.registerMenu(SectionEditMenu); } - static init(app: JlDrawApp) { - return new AxleCountingSectionInteraction(app); + static init(app: JlDrawApp, da: AxleCountingSectionDraw) { + return new AxleCountingSectionInteraction(app, da); } filter(...grahpics: JlGraphic[]): AxleCountingSection[] | undefined { return grahpics @@ -240,7 +344,7 @@ export class AxleCountingSectionInteraction extends GraphicInteractionPlugin { + Dialog.create({ + title: '拆分逻辑区段', + message: '请选择生成数量和方向', + component: SectionSplitDialog, + cancel: true, + persistent: true, + }).onOk((data: { num: number; dir: 'ltr' | 'rtl' }) => { + const logicSections = this.app.queryStore.queryByType( + LogicSection.Type + ); + logicSections.forEach((logicSection) => { + if (logicSection.datas.axleSectionId == axleCountingSection.id) { + this.app.deleteGraphics(logicSection); + } + }); + const { num, dir } = data; + const axleCountingSectionData = axleCountingSection.datas; + const points = splitLineEvenly( + axleCountingSection.localToCanvasPoint( + axleCountingSectionData.points[0] + ), + axleCountingSection.localToCanvasPoint( + axleCountingSectionData.points[ + axleCountingSectionData.points.length - 1 + ] + ), + num + ); + // let codeAppend = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.slice(0, num); + if ( + (dir === 'ltr' && + axleCountingSectionData.points[0].x > + axleCountingSectionData.points[ + axleCountingSectionData.points.length - 1 + ].x) || + (dir === 'rtl' && + axleCountingSectionData.points[0].x < + axleCountingSectionData.points[ + axleCountingSectionData.points.length - 1 + ].x) + ) { + // codeAppend = codeAppend.split('').reverse().join(''); + } + points.forEach((ps, i) => { + const data = new LogicSectionData(); + data.id = GraphicIdGenerator.next(); + data.axleSectionId = axleCountingSection.id; + // data.code = `${codeAppend.charAt(i % 26)}`; + data.points = ps.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + const g = new LogicSection(); + g.loadData(data); + this.drawAssistant.storeGraphic(g); + }); + }); + }; + SectionEditMenu.open(e.global); } } diff --git a/src/graphics/logicSection/LogicSection.ts b/src/graphics/logicSection/LogicSection.ts new file mode 100644 index 0000000..2001de4 --- /dev/null +++ b/src/graphics/logicSection/LogicSection.ts @@ -0,0 +1,110 @@ +import { Graphics, IPointData } from 'pixi.js'; +import { + GraphicData, + GraphicRelationParam, + JlGraphic, + JlGraphicTemplate, + VectorText, +} from 'src/jl-graphic'; + +export interface ILogicSectionData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get points(): IPointData[]; // 线坐标点 + set points(points: IPointData[]); + get axleSectionId(): string; // 计轴区段ID + set axleSectionId(v: string); + get indexNumber(): number; // 索引编号 + set indexNumber(v: number); + clone(): ILogicSectionData; + copyFrom(data: ILogicSectionData): void; + eq(other: ILogicSectionData): boolean; +} + +export const LogicSectionConsts = { + lineColor: '0xff0000', + lineWidth: 2, +}; + +export class LogicSection extends JlGraphic { + static Type = 'LogicSection'; + lineGraphic: Graphics; + labelGraphic: VectorText; + constructor() { + super(LogicSection.Type); + this.lineGraphic = new Graphics(); + this.labelGraphic = new VectorText(); + this.labelGraphic.setVectorFontSize(14); + this.labelGraphic.anchor.set(0.5); + this.labelGraphic.style.fill = '#0f0'; + this.labelGraphic.transformSave = true; + this.labelGraphic.name = 'label'; + this.transformSave = true; + this.addChild(this.lineGraphic); + this.addChild(this.labelGraphic); + } + + get datas(): ILogicSectionData { + return this.getDatas(); + } + doRepaint(): void { + if (this.datas.points.length < 2) { + throw new Error('LogicSection坐标数据异常'); + } + this.lineGraphic.clear(); + this.lineGraphic.lineStyle( + LogicSectionConsts.lineWidth, + LogicSectionConsts.lineColor + ); + this.datas.points.forEach((p, i) => { + if (i !== 0) { + this.lineGraphic.lineTo(p.x, p.y); + } else { + this.lineGraphic.moveTo(p.x, p.y); + } + }); + this.labelGraphic.text = this.datas.code; + const labelPosition = this.datas.childTransforms?.find( + (t) => t.name === this.labelGraphic.name + )?.transform.position; + if (labelPosition) { + this.labelGraphic.position.set(labelPosition.x, labelPosition.y); + } else { + this.labelGraphic.position.set( + this.datas.points[0].x, + this.datas.points[0].y + 20 + ); + } + } + get linePoints(): IPointData[] { + return this.datas.points; + } + set linePoints(points: IPointData[]) { + const old = this.datas.clone(); + old.points = points; + this.updateData(old); + } + loadRelations() { + if (this.datas?.axleSectionId) { + const axleSection = this.queryStore.queryById(this.datas.axleSectionId); + axleSection && + this.relationManage.addRelation( + new GraphicRelationParam(this), + new GraphicRelationParam(axleSection) + ); + } + } +} + +export class LogicSectionTemplate extends JlGraphicTemplate { + constructor(dataTemplate: ILogicSectionData) { + super(LogicSection.Type, { + dataTemplate, + }); + } + new(): LogicSection { + const logicSection = new LogicSection(); + logicSection.loadData(this.datas); + return logicSection; + } +} diff --git a/src/graphics/logicSection/LogicSectionDrawAssistant.ts b/src/graphics/logicSection/LogicSectionDrawAssistant.ts new file mode 100644 index 0000000..b7b1492 --- /dev/null +++ b/src/graphics/logicSection/LogicSectionDrawAssistant.ts @@ -0,0 +1,163 @@ +import { FederatedPointerEvent, IHitArea, Point } from 'pixi.js'; +import { + GraphicDrawAssistant, + GraphicIdGenerator, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, + linePoint, +} from 'src/jl-graphic'; + +import { + ILogicSectionData, + LogicSection, + LogicSectionTemplate, + LogicSectionConsts, +} from './LogicSection'; +import { Turnout } from '../turnout/Turnout'; +import { LogicSectionData } from 'src/drawApp/graphics/LogicSectionInteraction'; +import { AxleCountingSection } from '../axleCountingSection/AxleCountingSection'; + +export interface ILogicSectionDrawOptions { + newData: () => ILogicSectionData; +} + +export class LogicSectionDraw extends GraphicDrawAssistant< + LogicSectionTemplate, + ILogicSectionData +> { + codeGraph: LogicSection; + constructor(app: JlDrawApp, template: LogicSectionTemplate) { + super(app, template, 'sym_o_circle', '不展示'); + this.codeGraph = this.graphicTemplate.new(); + this.container.addChild(this.codeGraph); + LogicSectionInteraction.init(app); + } + + bind(): void { + super.bind(); + this.codeGraph.loadData(this.graphicTemplate.datas); + this.codeGraph.doRepaint(); + } + + clearCache(): void { + //this.codeGraph.destroy(); + } + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + prepareData(data: ILogicSectionData): boolean { + data.transform = this.container.saveTransform(); + return true; + } + draw(data: ILogicSectionData) { + const logicSection = new LogicSection(); + logicSection.loadData(data); + logicSection.id = GraphicIdGenerator.next(); + this.storeGraphic(logicSection); + logicSection.loadRelations(); + } + + oneGenerates() { + const map = new Map(); + const logicSections = this.app.queryStore.queryByType( + LogicSection.Type + ); + // this.app.deleteGraphics(...logicSections); + // return; + logicSections.forEach((logicSection) => { + map.set(`${logicSection.datas.axleSectionId}`, 1); + }); + const axleCountingSections = + this.app.queryStore.queryByType( + AxleCountingSection.Type + ); + axleCountingSections.forEach((axleCountingSection) => { + const turnoutPosRef = axleCountingSection.datas.turnoutPosRef; + if (turnoutPosRef.length > 0) { + turnoutPosRef.forEach((turnout) => { + if (turnout.position == 1 && !map.has(`${turnout.id}`)) { + map.set(`${turnout.id}`, 1); + const t = this.app.queryStore.queryById(turnout.id) as Turnout; + const data = new LogicSectionData(); + data.points = [ + t.position, + ...t.localToCanvasPoints(...t.datas.pointC), + ]; + data.axleSectionId = axleCountingSection.id; + this.draw(data); + } + }); + } + if (!map.has(`${axleCountingSection.id}`)) { + map.set(`${axleCountingSection.id}`, 1); + const data = new LogicSectionData(); + data.points = axleCountingSection.datas.points; + data.axleSectionId = axleCountingSection.id; + this.draw(data); + } + }); + } +} +class LogicSectionGraphicHitArea implements IHitArea { + logicSection: LogicSection; + constructor(logicSection: LogicSection) { + this.logicSection = logicSection; + } + contains(x: number, y: number): boolean { + for (let i = 1; i < this.logicSection.datas.points.length; i++) { + const p1 = this.logicSection.datas.points[i - 1]; + const p2 = this.logicSection.datas.points[i]; + if (linePoint(p1, p2, { x, y }, LogicSectionConsts.lineWidth)) { + return true; + } + } + return false; + } +} + +export class LogicSectionInteraction extends GraphicInteractionPlugin { + static Name = 'LogicSection_transform'; + constructor(app: JlDrawApp) { + super(LogicSectionInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new LogicSectionInteraction(app); + } + filter(...grahpics: JlGraphic[]): LogicSection[] | undefined { + return grahpics + .filter((g) => g.type === LogicSection.Type) + .map((g) => g as LogicSection); + } + bind(g: LogicSection): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.transformSave = true; + g.lineGraphic.eventMode = 'static'; + g.lineGraphic.cursor = 'pointer'; + g.lineGraphic.hitArea = new LogicSectionGraphicHitArea(g); + g.labelGraphic.eventMode = 'static'; + g.labelGraphic.cursor = 'pointer'; + g.labelGraphic.selectable = true; + g.labelGraphic.draggable = true; + } + unbind(g: LogicSection): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.lineGraphic.eventMode = 'none'; + g.lineGraphic.draggable = false; + g.lineGraphic.selectable = false; + g.lineGraphic.transformSave = false; + g.labelGraphic.eventMode = 'none'; + g.labelGraphic.draggable = false; + g.labelGraphic.selectable = false; + g.labelGraphic.transformSave = false; + } +} diff --git a/src/graphics/sectionLink/SectionLink.ts b/src/graphics/sectionLink/SectionLink.ts index 5be55ea..f085f74 100644 --- a/src/graphics/sectionLink/SectionLink.ts +++ b/src/graphics/sectionLink/SectionLink.ts @@ -5,6 +5,8 @@ import { JlGraphicTemplate, VectorText, IChildTransform, + getNormalVector, + movePointAlongNormal, } from 'src/jl-graphic'; import { ILineGraphic } from 'src/jl-graphic/plugins/GraphicEditPlugin'; @@ -23,12 +25,15 @@ export interface ISectionLinkData extends GraphicData { export const SectionLinkConsts = { lineColor: 0x5578b6, lineWidth: 5, + divisionColor: 0xff0000, + divisionWidth: 2, }; export class SectionLink extends JlGraphic implements ILineGraphic { static Type = 'SectionLink'; lineGraphic: Graphics; labelGraphic: VectorText; + divisionGraphic: Graphics = new Graphics(); constructor() { super(SectionLink.Type); @@ -42,6 +47,7 @@ export class SectionLink extends JlGraphic implements ILineGraphic { this.transformSave = true; this.addChild(this.lineGraphic); this.addChild(this.labelGraphic); + this.addChild(this.divisionGraphic); } doRepaint() { @@ -61,6 +67,36 @@ export class SectionLink extends JlGraphic implements ILineGraphic { this.lineGraphic.moveTo(p.x, p.y); } }); + const normalVector = getNormalVector( + this.datas.points[0], + this.datas.points[1] + ); + this.divisionGraphic.clear(); + this.divisionGraphic.lineStyle( + SectionLinkConsts.divisionWidth, + SectionLinkConsts.divisionColor + ); + const nextP = movePointAlongNormal(this.datas.points[0], normalVector, 5); + const nextP1 = movePointAlongNormal(this.datas.points[0], normalVector, -5); + this.divisionGraphic.moveTo(nextP1.x, nextP1.y); + this.divisionGraphic.lineTo(nextP.x, nextP.y); + const normalVector2 = getNormalVector( + this.datas.points[this.datas.points.length - 2], + this.datas.points[this.datas.points.length - 1] + ); + + const nextP2 = movePointAlongNormal( + this.datas.points[this.datas.points.length - 1], + normalVector2, + 5 + ); + const nextP3 = movePointAlongNormal( + this.datas.points[this.datas.points.length - 1], + normalVector2, + -5 + ); + this.divisionGraphic.moveTo(nextP3.x, nextP3.y); + this.divisionGraphic.lineTo(nextP2.x, nextP2.y); this.labelGraphic.text = this.datas.code; const labelPosition = this.datas?.childTransforms?.find( (item: IChildTransform) => item.name === this.labelGraphic.name diff --git a/src/graphics/sectionLink/SectionLinkDrawAssistant.ts b/src/graphics/sectionLink/SectionLinkDrawAssistant.ts index 8856825..626b759 100644 --- a/src/graphics/sectionLink/SectionLinkDrawAssistant.ts +++ b/src/graphics/sectionLink/SectionLinkDrawAssistant.ts @@ -23,6 +23,8 @@ import { } from 'pixi.js'; import { Section } from '../section/Section'; import { Turnout } from '../turnout/Turnout'; +import { AxleCounting } from '../axleCounting/AxleCounting'; +import { IRelatedRefData } from '../CommonGraphics'; export class SectionLinkDraw extends GraphicDrawAssistant< SectionLinkTemplate, @@ -65,51 +67,148 @@ export class SectionLinkDraw extends GraphicDrawAssistant< data.points = this.points; return true; } - oneGenerates() { - // localToCanvasPoints - const sectionList = this.app.queryStore.queryByType
(Section.Type); - const turnoutList = this.app.queryStore.queryByType(Turnout.Type); - console.log(sectionList.length, turnoutList.length); - sectionList.forEach((section: Section) => { - const sectionLink = new SectionLink(); - sectionLink.loadData(this.graphicTemplate.datas); - sectionLink.id = GraphicIdGenerator.next(); - const points: IPointData[] = []; - section.datas.points.forEach((p) => { - points.push(section.localToCanvasPoint(p)); - }); - sectionLink.datas.points = points; - this.storeGraphic(sectionLink); + generateBySection(section: Section) { + const sectionLink = new SectionLink(); + sectionLink.loadData(this.graphicTemplate.datas); + sectionLink.id = GraphicIdGenerator.next(); + const points: IPointData[] = []; + section.datas.points.forEach((p) => { + points.push(section.localToCanvasPoint(p)); }); - turnoutList.forEach((turnout: Turnout) => { - const sectionLinkA = new SectionLink(); - const sectionLinkB = new SectionLink(); - const sectionLinkC = new SectionLink(); - sectionLinkA.loadData(this.graphicTemplate.datas); - sectionLinkB.loadData(this.graphicTemplate.datas); - sectionLinkC.loadData(this.graphicTemplate.datas); - const forkP = new Point(turnout.position.x, turnout.position.y); - const pointA = [forkP]; - const pointB = [forkP]; - const pointC = [forkP]; + sectionLink.datas.points = points; + this.storeGraphic(sectionLink); + } + generateByTurnoutAxle(turnout: Turnout, port: number) { + const sectionLink = new SectionLink(); + sectionLink.loadData(this.graphicTemplate.datas); + sectionLink.id = GraphicIdGenerator.next(); + const forkP = new Point(turnout.position.x, turnout.position.y); + const points: IPointData[] = [forkP]; + if (port === 0) { turnout.datas.pointA.forEach((p) => { - pointA.push(turnout.localToCanvasPoint(p)); + points.push(turnout.localToCanvasPoint(p)); }); + } else if (port === 1) { turnout.datas.pointB.forEach((p) => { - pointB.push(turnout.localToCanvasPoint(p)); + points.push(turnout.localToCanvasPoint(p)); }); + } else if (port === 2) { turnout.datas.pointC.forEach((p) => { - pointC.push(turnout.localToCanvasPoint(p)); + points.push(turnout.localToCanvasPoint(p)); }); - sectionLinkA.id = GraphicIdGenerator.next(); - sectionLinkB.id = GraphicIdGenerator.next(); - sectionLinkC.id = GraphicIdGenerator.next(); - sectionLinkA.datas.points = pointA; - sectionLinkB.datas.points = pointB; - sectionLinkC.datas.points = pointC; - this.storeGraphic(sectionLinkA); - this.storeGraphic(sectionLinkB); - this.storeGraphic(sectionLinkC); + } + sectionLink.datas.points = points; + this.storeGraphic(sectionLink); + } + generateByTurnout(turnout: Turnout, port: number, pRef: IRelatedRefData) { + const refg = this.app.queryStore.queryById(pRef.id) as Turnout; + const sectionLink = new SectionLink(); + sectionLink.loadData(this.graphicTemplate.datas); + sectionLink.id = GraphicIdGenerator.next(); + const forkP1 = new Point(refg.position.x, refg.position.y); + const forkP2 = new Point(turnout.position.x, turnout.position.y); + const points: IPointData[] = [forkP1]; + if (pRef.devicePort === 0) { + refg.datas.pointA.forEach((p) => { + points.push(refg.localToCanvasPoint(p)); + }); + } else if (pRef.devicePort === 1) { + refg.datas.pointB.forEach((p) => { + points.push(refg.localToCanvasPoint(p)); + }); + } else if (pRef.devicePort === 2) { + refg.datas.pointC.forEach((p) => { + points.push(refg.localToCanvasPoint(p)); + }); + } + let dataPoint: IPointData[] = []; + if (port === 0) { + dataPoint = turnout.datas.pointA; + } else if (port === 1) { + dataPoint = turnout.datas.pointB; + } else if (port === 2) { + dataPoint = turnout.datas.pointC; + } + const pLength = dataPoint.length; + for (let i = 1; i < pLength + 1; i++) { + points.push(turnout.localToCanvasPoint(dataPoint[pLength - i])); + } + points.push(forkP2); + sectionLink.datas.points = points; + this.storeGraphic(sectionLink); + } + oneGenerates() { + const axleCountingList = this.app.queryStore.queryByType( + AxleCounting.Type + ); + const turnoutList = this.app.queryStore.queryByType(Turnout.Type); + const generated = new Map(); + axleCountingList.forEach((axleCounting) => { + axleCounting.datas.axleCountingRef.forEach((device) => { + const g = this.app.queryStore.queryById(device.id); + if (g.type === Section.Type && !generated.get(device.id)) { + const g1 = axleCountingList.find((axleCounting) => { + const s = axleCounting.datas.axleCountingRef.find( + (ref) => ref.id === device.id + ); + return s; + }); + if (g1) { + this.generateBySection(g as Section); + generated.set(g.id, ['A', 'B']); + } + } else if (g.type === Turnout.Type) { + this.generateByTurnoutAxle(g as Turnout, device.devicePort); + if (generated.get(g.id)) { + const pList = generated.get(g.id); + pList.push(device.devicePort); + generated.set(g.id, pList); + } else { + generated.set(g.id, [device.devicePort]); + } + } + }); + }); + turnoutList.forEach((turnout) => { + const pList = generated.get(turnout.id); + if (!pList) { + return; + } + let pRef = null; + if ( + !pList.includes(0) && + turnout.datas.paRef && + turnout.datas.paRef.deviceType === 1 + ) { + pRef = turnout.datas.paRef; + this.generateByTurnout(turnout, 0, pRef); + } + if ( + !pList.includes(1) && + turnout.datas.pbRef && + turnout.datas.pbRef.deviceType === 1 + ) { + pRef = turnout.datas.pbRef; + this.generateByTurnout(turnout, 1, pRef); + } + if ( + !pList.includes(2) && + turnout.datas.pcRef && + turnout.datas.pcRef.deviceType === 1 + ) { + pRef = turnout.datas.pcRef; + this.generateByTurnout(turnout, 2, pRef); + } + generated.set(turnout.id, [0, 1, 2]); + if (pRef) { + if (generated.get(pRef.id)) { + const pListn = generated.get(pRef.id); + pListn.push(pRef.devicePort); + generated.set(pRef.id, pListn); + } else { + generated.set(pRef.id, [pRef.devicePort]); + } + } }); } clearCache(): void { @@ -153,31 +252,8 @@ export class SectionLinkEditPlugin extends GraphicInteractionPlugin g.lineGraphic.eventMode = 'static'; g.lineGraphic.cursor = 'pointer'; g.lineGraphic.hitArea = new SectionLinkGraphicHitArea(g); - // g.transformSave = true; - // g.labelGraphic.eventMode = 'static'; - // g.labelGraphic.cursor = 'pointer'; - // g.labelGraphic.selectable = true; - // g.labelGraphic.draggable = true; - // g.on('selected', this.onSelected, this); - // g.on('unselected', this.onUnselected, this); - // g.on('_rightclick', this.onContextMenu, this); } unbind(g: SectionLink): void { - // g.off('selected', this.onSelected, this); - // g.off('unselected', this.onUnselected, this); - // g.off('_rightclick', this.onContextMenu, this); + // console.log } - - // onContextMenu(e: FederatedMouseEvent) { - // const target = e.target as DisplayObject; - // const section = target.getGraphic() as SectionLink; - // this.app.updateSelected(section); - // } - - // onSelected(g: DisplayObject): void { - // const sectionLink = g as SectionLink; - // } - // onUnselected(g: DisplayObject): void { - // const sectionLink = g as SectionLink; - // } } diff --git a/src/graphics/separator/Separator.ts b/src/graphics/separator/Separator.ts index 032ee1e..7890ddd 100644 --- a/src/graphics/separator/Separator.ts +++ b/src/graphics/separator/Separator.ts @@ -19,9 +19,9 @@ export enum separatorTypeEnum { } export const SeparatorConsts = { - height: 15, + height: 12, lineWidth: 2, - lineColor: '0x617799', + lineColor: '0xFFFFFF', circleColor: '0xEF0200', radius: 5, }; diff --git a/src/graphics/train/Train.ts b/src/graphics/train/Train.ts index 7e20031..d432abf 100644 --- a/src/graphics/train/Train.ts +++ b/src/graphics/train/Train.ts @@ -1,6 +1,7 @@ import { Color, Graphics, Container, Point } from 'pixi.js'; import { GraphicData, + GraphicIdGenerator, GraphicState, JlGraphic, JlGraphicTemplate, @@ -29,8 +30,8 @@ export interface ITrainState extends GraphicState { set devType(v: state.DeviceType); get devName(): string; // 所在设备名称 set devName(v: string); - get id(): string; // 设备唯一 - set id(v: string); + get trainIndex(): string; // 设备唯一,与trainIndex相同 + set trainIndex(v: string); get groupId(): string; // 列车车组号 set groupId(v: string); get trainId(): string; // 列车表号 @@ -53,14 +54,18 @@ export interface ITrainState extends GraphicState { set departTime(v: number); get speed(): number; // 速度 set speed(v: number); - get show(): boolean; // 是否显示 - set show(v: boolean); get type(): boolean; // 车次号变化状态 set type(v: boolean); get routeId(): number; // 运行路径号 set routeId(v: number); get rate(): number; // 满载率 set rate(v: number); + get remove(): train.TrainRemove; + set remove(v: train.TrainRemove); + get block(): train.TrainBlock; + set block(v: train.TrainBlock); + get record(): train.TrainRecord; + set record(v: train.TrainRecord); } interface bodyWH { @@ -71,36 +76,36 @@ interface bodyWH { // 列车颜色 export enum TrainColorEnum { headColor = '0xFFCE4D', // 箭头颜色 - bodyColor = '0xA388B1', // 背景色 + bodyColor = '0x1F3D99', // 背景色 + ITCbodyColor = '0x737373', // 点式背景色 codeColor = '0xffffff', // 车号颜色 - borderColor = '0xA3E198', // 边框的颜色 + borderColor = '0xffffff', // 边框的颜色 directionColor = '0x00FF00', // 方向箭头颜色 } -enum diriveModelColorEnum { // 驾驶模式对应颜色 - AM = '0x00FF00', // ATO自动驾驶 +enum DiriveModelColorEnum { // 驾驶模式对应颜色 + AM = '0xFF8000', // ATO自动驾驶 SM = '0xFFFF00', // ATP 监控下的人工驾驶模式 - RM = '0xFFC837', // 限制人工驾驶模式 - NRM = '0xA0522D', // 非限制人工驾驶模式 + RM = '0xC2C2C2', // 限制人工驾驶模式 + NRM = '0xFF0000', // 非限制人工驾驶模式 red = '0xF80103', // 红色表示通信中断 } -enum AAColorEnum { // 识别号AA颜色 - accuracy = '0xffffff', // 准点 - early = '0x00FF00', // 早点 - late = '0xA0522D', // 晚点 -} enum typeColorEnum { // 识别号BBB颜色 + accuracy = '0x11EF3D', // 准点 + early = '0x82F6FF', // 早点 + late = '0xE00D02', // 晚点 schedule = '0xffffff', // 计划车 - head = '0xE9FC01', // 头码车 - manual = '0xE9FC01', // 人工车 - special = '0xE9FC01', // 特殊车 + head = '0xffffff', // 头码车 + manual = '0xffffff', // 人工车 + special = '0xFFFF73', // 特殊车 } enum statusTextColor { - H = '0xFFFF00', // H扣车 - S = '0x6260F3', // S跳停 - D = '0x00FF00', // D开门 - A = '0xFF0000', // A报警 + 扣 = '0xFFFF00', // H扣车 + 跳 = '0x00CCFF', // S跳停 + 门 = '0x00FF00', // D开门 + 警 = '0xDA0000', // A报警 + '>>' = '0xFFFF00', // 列车重叠,点击可切换列车 } export const trainConsts = { @@ -110,10 +115,10 @@ export const trainConsts = { borderWidth: 1, codeFontSize: 22, textFontSize: 16, // 状态字母大小 - textMarginY: 10, // 状态字母与列车距离 - statusTextList: ['H', 'S', 'D', 'A'], + textMarginY: 5, // 状态字母与列车距离 + statusTextList: ['扣', '跳', '门', '警', '>>'], marginX: 2, // 图形x轴边距 - pauseW: 2, // 停止框宽度 + pauseW: 4, // 停止框宽度 }; export class TrainHead extends Container { @@ -132,10 +137,10 @@ export class TrainHead extends Container { } doRepaint(states: ITrainState, bodyWH?: bodyWH) { let direction = ''; - if (states.mode?.ipModeTrainDirUp) { + if (states.mode?.ipModeTrainDirDown) { direction = 'left'; } - if (states.mode?.ipModeTrainDirDown) { + if (states.mode?.ipModeTrainDirUp) { direction = 'right'; } this.clear(); @@ -180,21 +185,33 @@ export class TrainHead extends Container { }); pausePoint = pP; } - const arrow = this.arrow; - arrow.beginFill(TrainColorEnum.headColor, 1); - arrow.drawPolygon(arrowPoint); - arrow.endFill(); - this.pause.lineStyle(pauseW, TrainColorEnum.headColor, 1); + let aColor = DiriveModelColorEnum.AM; + let pColor = DiriveModelColorEnum.AM; + if ( + states.mode?.ipModeTrainDriveModeCm || + states.mode?.ipModeTrainDriveBlockCm + ) { + aColor = DiriveModelColorEnum.SM; + pColor = DiriveModelColorEnum.SM; + } else if ( + states.mode?.ipModeTrainDriveModeRmf || + states.mode?.ipModeTrainDriveModeRmr + ) { + aColor = DiriveModelColorEnum.RM; + pColor = DiriveModelColorEnum.RM; + } + this.pause.lineStyle(pauseW, pColor, 1); this.pause.moveTo(pausePoint[0], pausePoint[1]); this.pause.lineTo(pausePoint[2], pausePoint[3]); - } - stop() { - this.pause.visible = true; - this.arrow.visible = false; - } - run() { - this.pause.visible = false; - this.arrow.visible = true; + const arrow = this.arrow; + arrow.beginFill(aColor, 1); + arrow.drawPolygon(arrowPoint); + arrow.endFill(); + if (states.mode?.ipModeTrainStoped) { + this.arrow.visible = false; + } else { + this.arrow.visible = true; + } } } @@ -228,28 +245,33 @@ export class TrainBody extends Container { const codeAGraph = this.codeAGraph; const codeBGraph = this.codeBGraph; const codeRact = this.codeRact; - let codeA = states?.trainId; - let fillAColor = AAColorEnum.accuracy; - if (states.mode?.ipModeTrainTypeSchedule) { - if (states?.otpTime > 0) { - fillAColor = AAColorEnum.late; - } else if (states?.otpTime < 0) { - fillAColor = AAColorEnum.early; - } - } + const codeA = states?.groupId; + let codeB = states?.destinationId ? states?.destinationId + '' : ''; + const fillAColor = typeColorEnum.schedule; let fillBColor = typeColorEnum.schedule; - if (states.mode?.ipModeTrainTypeHead) { - codeA = states?.destinationId + ''; - fillBColor = typeColorEnum.head; + if (states.mode?.ipModeTrainTypeSchedule) { + fillBColor = typeColorEnum.accuracy; + if (states.mode?.ipModeTrainSchdLate) { + fillBColor = typeColorEnum.late; + } else if (states.mode?.ipModeTrainSchdEarly) { + fillBColor = typeColorEnum.early; + } + } else if (states.mode?.ipModeTrainTypeHead) { + codeB = states?.destinationId ? states?.destinationId + '' : ''; } else if (states.mode?.ipModeTrainTypeManual) { - codeA = 'MM'; - fillBColor = typeColorEnum.manual; + codeB = '---'; } else if (states.mode?.ipModeTrainTypeSpecial) { - codeA = ''; + codeB = 'MM'; + } + let bgColor = TrainColorEnum.ITCbodyColor; + if ( + states.mode?.ipModeTrainDriveModeAm || + states.mode?.ipModeTrainDriveModeCm + ) { + bgColor = TrainColorEnum.bodyColor; } - const codeB = states?.globalId; codeAGraph.text = codeA || '01'; - codeBGraph.text = codeB || '2222'; + codeBGraph.text = codeB || '222'; codeAGraph.anchor.set(0.5); codeBGraph.anchor.set(0.5); const styleA = { @@ -273,7 +295,7 @@ export class TrainBody extends Container { trainConsts.borderWidth, new Color(TrainColorEnum.borderColor) ); - codeRact.beginFill(new Color(TrainColorEnum.bodyColor)); + codeRact.beginFill(new Color(bgColor)); codeRact.drawRect(-codeWidth / 2, -codeHeight / 2, codeWidth, codeHeight); codeRact.endFill(); } @@ -288,7 +310,7 @@ class StatusText extends Container { doRepaint(text: string, bodyWH: bodyWH): void { this.sText.text = text; this.sText.anchor.set(0.5); - const c = (statusTextColor as never)[text] || statusTextColor.D; + const c = (statusTextColor as never)[text] || statusTextColor.门; const style = { fill: c, fontSize: trainConsts.textFontSize, @@ -302,7 +324,7 @@ class StatusText extends Container { return item == text; }); if (index < 0) { - index = 1.5; // 中间 + index = (num - 1) / 2; // 中间 } const textMargin = (codeWidth - textHWidth * num) / (num - 1); this.sText.position.set( @@ -337,17 +359,34 @@ export class Train extends JlGraphic { return this.getStates(); } + get code(): string { + return this.states.code; + } + doRepaint(): void { this.trainbody.doRepaint(this.states); const bodyWH = this.trainbody.getBodyWH(); this.trainHead.doRepaint(this.states, bodyWH); - } - - stop() { - this.trainHead.stop(); - } - run() { - this.trainHead.run(); + if (this.states.mode?.ipModeTrainHolded) { + this.showStatus('扣'); + } else { + this.hideStatus('扣'); + } + if (this.states.mode?.ipModeTrainSkipstop) { + this.showStatus('跳'); + } else { + this.hideStatus('跳'); + } + if (this.states.mode?.ipModeTrainDoorOpen) { + this.showStatus('门'); + } else { + this.hideStatus('门'); + } + if (this.states.mode?.ipModeTrainRsAlarm) { + this.showStatus('警'); + } else { + this.hideStatus('警'); + } } showStatus(s: string) { @@ -370,22 +409,6 @@ export class Train extends JlGraphic { this.statusTextMap.delete(s); } } - chagneDirection(): void { - const bodyWH = this.trainbody.getBodyWH(); - this.trainHead.doRepaint(this.states, bodyWH); - } - chagneState(): void { - if (this.states.mode?.ipModeTrainHolded) { - this.showStatus('H'); - } else { - this.hideStatus('H'); - } - if (this.states.mode?.ipModeTrainDoorOpen) { - this.showStatus('D'); - } else { - this.hideStatus('D'); - } - } } export class TrainTemplate extends JlGraphicTemplate { @@ -394,7 +417,7 @@ export class TrainTemplate extends JlGraphicTemplate { } new(): Train { const train = new Train(); - train.loadData(this.datas); + train.id = GraphicIdGenerator.next(); train.loadState(this.states); return train; } diff --git a/src/layouts/DrawLayout.vue b/src/layouts/DrawLayout.vue index 858b042..5f4c132 100644 --- a/src/layouts/DrawLayout.vue +++ b/src/layouts/DrawLayout.vue @@ -37,6 +37,9 @@ > 一键生成计轴区段 + + 一键生成逻辑区段 + @@ -201,10 +204,13 @@ import { Separator } from 'src/graphics/separator/Separator'; import { SeparatorDraw } from 'src/graphics/separator/SeparatorDrawAssistant'; import { SectionLink } from 'src/graphics/sectionLink/SectionLink'; import { SectionLinkDraw } from 'src/graphics/sectionLink/SectionLinkDrawAssistant'; +import { store } from 'quasar/wrappers'; import { AxleCountingSection } from 'src/graphics/axleCountingSection/AxleCountingSection'; import { AxleCountingSectionDraw } from 'src/graphics/axleCountingSection/AxleCountingSectionAssistant'; import { SectionDraw } from 'src/graphics/section/SectionDrawAssistant'; import { Section } from 'src/graphics/section/Section'; +import { LogicSection } from 'src/graphics/logicSection/LogicSection'; +import { LogicSectionDraw } from 'src/graphics/logicSection/LogicSectionDrawAssistant'; const route = useRoute(); const router = useRouter(); @@ -354,8 +360,19 @@ function oneClickAxleCountingSection() { .getDrawAssistant(AxleCountingSection.Type) as AxleCountingSectionDraw; axleCountingSectionDraw.oneGenerates(); } +function oneClickLogicSection() { + //一键生成逻辑区段 + const logicSectionDraw = drawStore + .getDrawApp() + .getDrawAssistant(LogicSection.Type) as LogicSectionDraw; + logicSectionDraw.oneGenerates(); +} function oneClickLink() { drawStore.oneClickType = 'SectionLink'; + const linkList = drawStore + .getDrawApp() + .queryStore.queryByType(SectionLink.Type); + drawStore.getDrawApp().deleteGraphics(...linkList); const draw = drawStore .getDrawApp() .getDrawAssistant(SectionLink.Type);