2023-07-11 17:09:49 +08:00
|
|
|
import {
|
|
|
|
DisplayObject,
|
|
|
|
FederatedMouseEvent,
|
|
|
|
FederatedPointerEvent,
|
|
|
|
IHitArea,
|
|
|
|
IPointData,
|
|
|
|
Point,
|
|
|
|
} from 'pixi.js';
|
2023-07-07 17:15:53 +08:00
|
|
|
import {
|
|
|
|
GraphicDrawAssistant,
|
|
|
|
GraphicIdGenerator,
|
|
|
|
GraphicInteractionPlugin,
|
|
|
|
JlDrawApp,
|
|
|
|
JlGraphic,
|
|
|
|
linePoint,
|
2023-07-11 17:09:49 +08:00
|
|
|
splitLineEvenly,
|
2023-07-07 17:15:53 +08:00
|
|
|
} from 'src/jl-graphic';
|
|
|
|
|
|
|
|
import {
|
|
|
|
IAxleCountingSectionData,
|
|
|
|
AxleCountingSection,
|
|
|
|
AxleCountingSectionTemplate,
|
|
|
|
AxleCountingSectionConsts,
|
2023-07-11 15:35:35 +08:00
|
|
|
ITurnoutPosRefData,
|
2023-07-07 17:15:53 +08:00
|
|
|
} from './AxleCountingSection';
|
|
|
|
import { AxleCounting } from '../axleCounting/AxleCounting';
|
|
|
|
import { Turnout } from '../turnout/Turnout';
|
|
|
|
import { createRelatedRefProto } from '../CommonGraphics';
|
2023-07-11 17:09:49 +08:00
|
|
|
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';
|
2023-07-07 17:15:53 +08:00
|
|
|
|
2023-07-10 13:37:13 +08:00
|
|
|
function hasCommonElements(arr1: string[], arr2: string[]) {
|
2023-07-07 17:15:53 +08:00
|
|
|
for (let i = 0; i < arr1.length; i++) {
|
|
|
|
if (arr2.includes(arr1[i])) {
|
2023-07-10 13:37:13 +08:00
|
|
|
return arr1[i];
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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);
|
2023-07-11 17:09:49 +08:00
|
|
|
AxleCountingSectionInteraction.init(app, this);
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2023-07-11 15:35:35 +08:00
|
|
|
draw(
|
|
|
|
graphics: AxleCounting[],
|
|
|
|
commonElement: JlGraphic[],
|
2023-07-11 17:42:04 +08:00
|
|
|
map: Map<string, number>,
|
2023-07-11 15:35:35 +08:00
|
|
|
turoutPos?: number
|
|
|
|
) {
|
2023-07-11 17:42:04 +08:00
|
|
|
if (
|
|
|
|
map.has(`${graphics[0].id}+${graphics[1].id}`) ||
|
|
|
|
map.has(`${graphics[1].id}+${graphics[0].id}`)
|
|
|
|
)
|
|
|
|
return;
|
2023-07-07 17:15:53 +08:00
|
|
|
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);
|
2023-07-11 15:35:35 +08:00
|
|
|
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,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2023-07-07 17:15:53 +08:00
|
|
|
axleCountingSection.datas.paRef = paRef;
|
|
|
|
axleCountingSection.datas.pbRef = pbRef;
|
2023-07-11 15:35:35 +08:00
|
|
|
axleCountingSection.datas.turnoutPosRef = turnoutPosData;
|
2023-07-07 17:15:53 +08:00
|
|
|
this.storeGraphic(axleCountingSection);
|
|
|
|
axleCountingSection.loadRelations();
|
|
|
|
}
|
|
|
|
|
|
|
|
oneGenerates() {
|
2023-07-11 17:42:04 +08:00
|
|
|
const map = new Map();
|
2023-07-10 15:03:47 +08:00
|
|
|
const axleCountingSections =
|
2023-07-07 17:25:51 +08:00
|
|
|
this.app.queryStore.queryByType<AxleCountingSection>(
|
|
|
|
AxleCountingSection.Type
|
|
|
|
);
|
2023-07-11 17:42:04 +08:00
|
|
|
axleCountingSections.forEach((axleCountingSection) => {
|
|
|
|
map.set(
|
|
|
|
`${axleCountingSection.datas.paRef?.id}+${axleCountingSection.datas.pbRef?.id}`,
|
|
|
|
1
|
|
|
|
);
|
|
|
|
});
|
2023-07-07 17:15:53 +08:00
|
|
|
const axleCountings = this.app.queryStore.queryByType<AxleCounting>(
|
|
|
|
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
|
|
|
|
);
|
2023-07-10 13:37:13 +08:00
|
|
|
const commonElementId = hasCommonElements(refDeviceTarget, refDevice);
|
|
|
|
if (commonElementId) {
|
|
|
|
const commonElement = this.app.queryStore.queryById(commonElementId);
|
|
|
|
let draw = true;
|
2023-07-11 15:35:35 +08:00
|
|
|
let turoutPos = 0;
|
|
|
|
//道岔BC端处的计轴不构成计轴区段
|
2023-07-10 13:37:13 +08:00
|
|
|
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;
|
|
|
|
}
|
2023-07-11 15:35:35 +08:00
|
|
|
if (targetPort == 2 || port == 2) {
|
|
|
|
turoutPos = 1;
|
|
|
|
}
|
2023-07-10 13:37:13 +08:00
|
|
|
}
|
|
|
|
if (draw) {
|
2023-07-11 15:35:35 +08:00
|
|
|
this.draw(
|
|
|
|
[axleCounting, axleCountings[i]],
|
|
|
|
[commonElement],
|
2023-07-11 17:42:04 +08:00
|
|
|
map,
|
2023-07-11 15:35:35 +08:00
|
|
|
turoutPos
|
|
|
|
);
|
2023-07-10 13:37:13 +08:00
|
|
|
}
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
|
|
|
if (hasSamePosition(axleCounting, axleCountings[i])) {
|
|
|
|
hasfourTurnout.push([axleCounting, axleCountings[i]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2023-07-11 15:35:35 +08:00
|
|
|
//补4个道岔处的BB连接处的计轴区段
|
|
|
|
const fourAxleCounting: {
|
|
|
|
axleCounting: AxleCounting;
|
|
|
|
refTurout: Turnout;
|
|
|
|
}[] = [];
|
2023-07-07 17:15:53 +08:00
|
|
|
hasfourTurnout.forEach((axleCountings) => {
|
2023-07-10 10:04:53 +08:00
|
|
|
axleCountings.forEach((axleCounting) => {
|
|
|
|
//计轴关联的道岔
|
|
|
|
const axleCountingRelations =
|
|
|
|
axleCounting.relationManage.getRelationsOfGraphicAndOtherType(
|
|
|
|
axleCounting,
|
|
|
|
Turnout.Type
|
|
|
|
);
|
|
|
|
axleCountingRelations.forEach((relation) => {
|
|
|
|
const refTurnout = relation.getOtherGraphic<Turnout>(axleCounting);
|
|
|
|
//道岔关联的计轴
|
|
|
|
const turnoutRelations =
|
|
|
|
refTurnout.relationManage.getRelationsOfGraphicAndOtherType(
|
|
|
|
refTurnout,
|
|
|
|
AxleCounting.Type
|
|
|
|
);
|
|
|
|
turnoutRelations.forEach((relation) => {
|
|
|
|
const refAxleCounting =
|
|
|
|
relation.getOtherGraphic<AxleCounting>(refTurnout);
|
|
|
|
if (
|
|
|
|
refAxleCounting.id !== axleCountings[0].id &&
|
|
|
|
refAxleCounting.id !== axleCountings[1].id
|
|
|
|
) {
|
2023-07-11 15:35:35 +08:00
|
|
|
fourAxleCounting.push({
|
|
|
|
axleCounting: refAxleCounting,
|
|
|
|
refTurout: refTurnout,
|
|
|
|
});
|
2023-07-10 10:04:53 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2023-07-07 17:15:53 +08:00
|
|
|
});
|
|
|
|
});
|
2023-07-10 10:04:53 +08:00
|
|
|
for (let x = 0; x < fourAxleCounting.length; x += 4) {
|
|
|
|
const AxleCountings = fourAxleCounting.slice(x, x + 4);
|
|
|
|
for (let y = 0; y < 4; y++) {
|
2023-07-11 15:35:35 +08:00
|
|
|
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],
|
2023-07-11 17:42:04 +08:00
|
|
|
[fourAxleCounting[x].refTurout, AxleCountings[y].refTurout],
|
|
|
|
map
|
2023-07-11 15:35:35 +08:00
|
|
|
);
|
2023-07-10 10:04:53 +08:00
|
|
|
break;
|
|
|
|
}
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
2023-07-10 10:04:53 +08:00
|
|
|
for (let y = 0; y < 4; y++) {
|
2023-07-11 15:35:35 +08:00
|
|
|
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,
|
|
|
|
],
|
2023-07-11 17:42:04 +08:00
|
|
|
[fourAxleCounting[x + 1].refTurout, AxleCountings[y].refTurout],
|
|
|
|
map
|
2023-07-11 15:35:35 +08:00
|
|
|
);
|
2023-07-10 10:04:53 +08:00
|
|
|
break;
|
|
|
|
}
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
2023-07-10 10:04:53 +08:00
|
|
|
}
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-11 17:09:49 +08:00
|
|
|
export const splitSectionConfig: MenuItemOptions = {
|
|
|
|
name: '拆分计轴区段',
|
|
|
|
};
|
|
|
|
const SectionEditMenu: ContextMenu = ContextMenu.init({
|
|
|
|
name: '区段编辑菜单',
|
|
|
|
groups: [
|
|
|
|
{
|
|
|
|
items: [splitSectionConfig],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
2023-07-07 17:15:53 +08:00
|
|
|
export class AxleCountingSectionInteraction extends GraphicInteractionPlugin<AxleCountingSection> {
|
|
|
|
static Name = 'AxleCountingSection_transform';
|
2023-07-11 17:09:49 +08:00
|
|
|
drawAssistant: AxleCountingSectionDraw;
|
|
|
|
constructor(app: JlDrawApp, da: AxleCountingSectionDraw) {
|
2023-07-07 17:15:53 +08:00
|
|
|
super(AxleCountingSectionInteraction.Name, app);
|
2023-07-11 17:09:49 +08:00
|
|
|
this.drawAssistant = da;
|
|
|
|
app.registerMenu(SectionEditMenu);
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
2023-07-11 17:09:49 +08:00
|
|
|
static init(app: JlDrawApp, da: AxleCountingSectionDraw) {
|
|
|
|
return new AxleCountingSectionInteraction(app, da);
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
|
|
|
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;
|
2023-07-11 17:09:49 +08:00
|
|
|
g.on('_rightclick', this.onContextMenu, this);
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
|
|
|
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;
|
2023-07-11 17:09:49 +08:00
|
|
|
g.off('_rightclick', this.onContextMenu, this);
|
|
|
|
}
|
|
|
|
onContextMenu(e: FederatedMouseEvent) {
|
|
|
|
const target = e.target as DisplayObject;
|
|
|
|
const axleCountingSection = target.getGraphic() as AxleCountingSection;
|
|
|
|
this.app.updateSelected(axleCountingSection);
|
|
|
|
|
|
|
|
splitSectionConfig.handler = () => {
|
|
|
|
Dialog.create({
|
|
|
|
title: '拆分逻辑区段',
|
|
|
|
message: '请选择生成数量和方向',
|
|
|
|
component: SectionSplitDialog,
|
|
|
|
cancel: true,
|
|
|
|
persistent: true,
|
|
|
|
}).onOk((data: { num: number; dir: 'ltr' | 'rtl' }) => {
|
|
|
|
const logicSections = this.app.queryStore.queryByType<LogicSection>(
|
|
|
|
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
|
|
|
|
);
|
|
|
|
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)
|
|
|
|
) {
|
|
|
|
}
|
2023-07-12 14:04:45 +08:00
|
|
|
points.forEach((ps) => {
|
2023-07-11 17:09:49 +08:00
|
|
|
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);
|
2023-07-07 17:15:53 +08:00
|
|
|
}
|
|
|
|
}
|