import { FederatedPointerEvent, IHitArea, IPointData, Point } from 'pixi.js'; import { GraphicDrawAssistant, GraphicIdGenerator, GraphicInteractionPlugin, JlDrawApp, JlGraphic, linePoint, } from 'src/jl-graphic'; import { IAxleCountingSectionData, AxleCountingSection, AxleCountingSectionTemplate, AxleCountingSectionConsts, ITurnoutPosRefData, } from './AxleCountingSection'; import { AxleCounting } from '../axleCounting/AxleCounting'; 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'; function hasCommonElements(arr1: string[], arr2: string[]) { for (let i = 0; i < arr1.length; i++) { if (arr2.includes(arr1[i])) { return arr1[i]; } } return false; } function hasSamePosition(point1: IPointData, point2: IPointData): boolean { if ( Math.abs(point1.x - point2.x) < 20 && Math.abs(point1.y - point2.y) < 20 ) { return true; } return false; } export interface IAxleCountingSectionDrawOptions { newData: () => IAxleCountingSectionData; } export class AxleCountingSectionDraw extends GraphicDrawAssistant< AxleCountingSectionTemplate, IAxleCountingSectionData > { codeGraph: AxleCountingSection; constructor(app: JlDrawApp, template: AxleCountingSectionTemplate) { super(app, template, 'sym_o_circle', '不展示'); this.codeGraph = this.graphicTemplate.new(); this.container.addChild(this.codeGraph); AxleCountingSectionInteraction.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: IAxleCountingSectionData): boolean { data.transform = this.container.saveTransform(); return true; } 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 = [ graphics[0].position, graphics[1].position, ]; 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 map = new Map(); const axleCountingSections = this.app.queryStore.queryByType( AxleCountingSection.Type ); axleCountingSections.forEach((axleCountingSection) => { map.set( `${axleCountingSection.datas.paRef?.id}+${axleCountingSection.datas.pbRef?.id}`, 1 ); }); const axleCountings = this.app.queryStore.queryByType( AxleCounting.Type ); const hasfourTurnout: AxleCounting[][] = []; axleCountings.forEach((axleCounting) => { const refDeviceTarget = axleCounting.datas.axleCountingRef.map( (ref) => ref.id ); for (let i = 0; i < axleCountings.length - 1; i++) { if (axleCountings[i].id == axleCounting.id) return; const refDevice = axleCountings[i].datas.axleCountingRef.map( (ref) => ref.id ); 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]]); } } }); //补4个道岔处的BB连接处的计轴区段 const fourAxleCounting: { axleCounting: AxleCounting; refTurout: Turnout; }[] = []; hasfourTurnout.forEach((axleCountings) => { 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, }); } }); }); }); }); 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; } } 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; } } } } } class AxleCountingSectionGraphicHitArea implements IHitArea { axleCountingSection: AxleCountingSection; constructor(axleCountingSection: AxleCountingSection) { this.axleCountingSection = axleCountingSection; } contains(x: number, y: number): boolean { for (let i = 1; i < this.axleCountingSection.datas.points.length; i++) { const p1 = this.axleCountingSection.datas.points[i - 1]; const p2 = this.axleCountingSection.datas.points[i]; if (linePoint(p1, p2, { x, y }, AxleCountingSectionConsts.lineWidth)) { return true; } } return false; } } 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) { super(AxleCountingSectionInteraction.Name, app); app.registerMenu(SectionEditMenu); } static init(app: JlDrawApp) { return new AxleCountingSectionInteraction(app); } filter(...grahpics: JlGraphic[]): AxleCountingSection[] | undefined { return grahpics .filter((g) => g.type === AxleCountingSection.Type) .map((g) => g as AxleCountingSection); } bind(g: AxleCountingSection): 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 AxleCountingSectionGraphicHitArea(g); g.labelGraphic.eventMode = 'static'; g.labelGraphic.cursor = 'pointer'; g.labelGraphic.selectable = true; g.labelGraphic.draggable = true; } unbind(g: AxleCountingSection): 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; } }