import { FederatedPointerEvent, IHitArea, IPointData, Point } from 'pixi.js'; import { AbsorbableLine, AbsorbablePosition, GraphicDrawAssistant, GraphicIdGenerator, GraphicInteractionPlugin, JlDrawApp, JlGraphic, linePoint, } from 'src/jl-graphic'; import { IAxleCountingSectionData, AxleCountingSection, AxleCountingSectionTemplate, AxleCountingSectionConsts, } from './AxleCountingSection'; import { AxleCounting } from '../axleCounting/AxleCounting'; import { Turnout } from '../turnout/Turnout'; import { createRelatedRefProto } from '../CommonGraphics'; 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[]) { 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); axleCountingSection.datas.paRef = paRef; axleCountingSection.datas.pbRef = pbRef; this.storeGraphic(axleCountingSection); axleCountingSection.loadRelations(); } oneGenerates() { const axleCountingSectionAll = this.app.queryStore.queryByType( AxleCountingSection.Type ); this.app.deleteGraphics(...axleCountingSectionAll); 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; 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 (draw) { this.draw([axleCounting, axleCountings[i]]); } } if (hasSamePosition(axleCounting, axleCountings[i])) { hasfourTurnout.push([axleCounting, axleCountings[i]]); } } }); const fourAxleCounting: AxleCounting[] = []; 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(refAxleCounting); } }); }); }); }); 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].id == AxleCountings[y].id) continue; if (fourAxleCounting[x].y == AxleCountings[y].y) { this.draw([fourAxleCounting[x], AxleCountings[y]]); break; } } for (let y = 0; y < 4; y++) { if (fourAxleCounting[x + 1].id == AxleCountings[y].id) continue; if (fourAxleCounting[x + 1].y == AxleCountings[y].y) { this.draw([fourAxleCounting[x + 1], AxleCountings[y]]); 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) { 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 class AxleCountingSectionInteraction extends GraphicInteractionPlugin { static Name = 'AxleCountingSection_transform'; constructor(app: JlDrawApp) { super(AxleCountingSectionInteraction.Name, app); } 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; g.on('selected', this.onSelected, this); } 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; g.off('selected', this.onSelected, this); } onSelected(): void { const AxleCountingSection = this.app .selectedGraphics[0] as AxleCountingSection; this.app.setOptions({ absorbablePositions: buildAbsorbablePositions(AxleCountingSection), }); } }