This commit is contained in:
fan 2023-07-07 09:25:49 +08:00
commit 3ed7b25f57
14 changed files with 874 additions and 286 deletions

@ -1 +1 @@
Subproject commit 7e4eaed0cf06d68c75cb51c30329eff5fe4d1e3f
Subproject commit 1f302648b5a71a82b798b77fe238c5fc6e3081b4

View File

@ -110,6 +110,8 @@ module.exports = configure(function (/* ctx */) {
// components: [],
// directives: [],
autoImportComponentCase: 'combined',
// Quasar plugins
plugins: ['Notify', 'Dialog', 'Dark', 'AppFullscreen', 'Loading'],
},

View File

@ -0,0 +1,42 @@
<script setup lang="ts">
import { useDialogPluginComponent } from 'quasar';
import { ref } from 'vue';
const num = ref(3);
const dir = ref('ltr');
const dirOptions = [
{ label: '从左至右', value: 'ltr' },
{ label: '从右至左', value: 'rtl' },
];
defineEmits([...useDialogPluginComponent.emits]);
const { dialogRef, onDialogOK, onDialogCancel } = useDialogPluginComponent();
</script>
<template>
<QDialog ref="dialogRef">
<QCard>
<QCardSection> <div class="text-h6">区段拆分</div> </QCardSection>
<QCardSection> <div>请选择要拆分的数量和方向</div> </QCardSection>
<QCardSection class="q-pt-none">
<QInput type="number" dense outlined v-model="num" :min="2" :max="20" />
</QCardSection>
<QCardSection>
<QSelect v-model="dir" dense :options="dirOptions" emitValue mapOptions>
</QSelect>
</QCardSection>
<QCardActions align="right" class="text-primary">
<QBtn flat label="取消" @click="onDialogCancel" v-close-popup />
<QBtn
flat
label="确认"
@click="onDialogOK({ num: Number(num), dir })"
v-close-popup
/>
</QCardActions>
</QCard>
</QDialog>
</template>
<style scoped></style>

View File

@ -31,59 +31,20 @@
>
</template>
</q-field>
<q-input class="q-mt-lg" outlined v-model="splitNum" type="number">
<template #after>
<q-btn
:disable="sectionModel.data.sectionType !== SectionType.Physical"
color="primary"
@click="splitSection"
>拆分为逻辑区段</q-btn
>
</template>
</q-input>
</q-form>
</template>
<script setup lang="ts">
import { SectionData } from 'src/drawApp/graphics/SectionInteraction';
import { Section, SectionType } from 'src/graphics/section/Section';
import { Section } from 'src/graphics/section/Section';
import { Turnout } from 'src/graphics/turnout/Turnout';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { useDrawStore } from 'src/stores/draw-store';
import { computed, ref, shallowRef, toRaw, watchEffect } from 'vue';
import { computed, shallowRef, watchEffect } from 'vue';
const drawStore = useDrawStore();
const sectionModel = shallowRef(new SectionData());
const splitNum = ref(3);
function splitSection() {
const sectionData = toRaw(sectionModel.value);
const section = toRaw(drawStore.selectedGraphic as Section);
const app = drawStore.getDrawApp();
const points = section.getSplitPoints(splitNum.value);
const childIds: string[] = [];
points.forEach((ps, i) => {
const data = new SectionData();
data.points = ps.map((p) => new graphicData.Point({ x: p.x, y: p.y }));
data.id = app.drawAssistants
.find((as) => as.name === Section.name)!
.nextId();
data.code = `${sectionData.code}-${'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.charAt(
i % 26
)}`;
data.sectionType = SectionType.Logic;
const section = app.graphicTemplateMap.get(Section.name)!.new();
section?.loadData(data);
app.addGraphics(section);
childIds.push(data.id);
});
sectionData.children = childIds;
app.updateGraphicAndRecord(section, sectionData);
}
const sectionRelations = computed(() => {
const section = drawStore.selectedGraphic as Section;

View File

@ -234,6 +234,8 @@ const PlatformOperateMenu: ContextMenu = ContextMenu.init({
removeHoldrConfig,
skipStopConfig,
removeSkipStopConfig,
dockTimeConfig,
operatingLevelConfig,
],
},
],
@ -293,13 +295,13 @@ export class PlatformOperateInteraction extends GraphicInteractionPlugin<Platfor
const platform = target.getGraphic() as Platform;
this.app.updateSelected(platform);
holdConfig.handler = () => {
platform.states.upHold = true;
platform.states.upOccHold = true;
platform.states.emergstop = true;
platform.doRepaint();
};
removeHoldrConfig.handler = () => {
platform.states.upHold = false;
platform.states.upOccHold = false;
platform.states.emergstop = false;
platform.doRepaint();
};
skipStopConfig.handler = () => {
@ -310,6 +312,14 @@ export class PlatformOperateInteraction extends GraphicInteractionPlugin<Platfor
platform.states.upSkipstop = false;
platform.doRepaint();
};
dockTimeConfig.handler = () => {
platform.states.stopTime = 30;
platform.doRepaint();
};
operatingLevelConfig.handler = () => {
platform.states.nextSectionRunLevel = 2;
platform.doRepaint();
};
PlatformOperateMenu.open(e.global);
}

View File

@ -120,21 +120,28 @@ export class StationState extends GraphicStateBase implements IStationState {
}
}
const powerUnlockConfig: MenuItemOptions = {
name: '上电解锁',
const emergencyStationControlConfig: MenuItemOptions = {
name: '紧急站控',
};
const chainConfig: MenuItemOptions = {
name: '全站设置连锁自动触发',
const centralControlConfig: MenuItemOptions = {
name: '中控',
};
const removeChainConfig: MenuItemOptions = {
name: '全站取消连锁自动触发',
const stationControlConfig: MenuItemOptions = {
name: '站控',
};
const interlockControlConfig: MenuItemOptions = {
name: '联锁控',
};
const StationOperateMenu: ContextMenu = ContextMenu.init({
name: '车站操作菜单',
groups: [
{
items: [powerUnlockConfig, chainConfig, removeChainConfig],
items: [
emergencyStationControlConfig,
centralControlConfig,
stationControlConfig,
interlockControlConfig,
],
},
],
});
@ -170,16 +177,29 @@ export class StationOperateInteraction extends GraphicInteractionPlugin<Station>
const target = e.target as DisplayObject;
const station = target.getGraphic() as Station;
this.app.updateSelected(station);
powerUnlockConfig.handler = () => {
emergencyStationControlConfig.handler = () => {
station.states.ipRtuStusInEmergencyCtrl = true;
station.states.ipRtuStusInLocalCtrl = false;
station.states.ipRtuStusInCentralCtrl = false;
station.doRepaint();
};
stationControlConfig.handler = () => {
station.states.ipRtuStusInEmergencyCtrl = false;
station.states.ipRtuStusInCentralCtrl = false;
station.states.ipRtuStusInLocalCtrl = true;
station.doRepaint();
};
chainConfig.handler = () => {
station.states.ipRtuStusDown = true;
centralControlConfig.handler = () => {
station.states.ipRtuStusInEmergencyCtrl = false;
station.states.ipRtuStusInLocalCtrl = false;
station.states.ipRtuStusInCentralCtrl = true;
station.doRepaint();
};
removeChainConfig.handler = () => {
console.log(2222);
interlockControlConfig.handler = () => {
station.states.ipRtuStusInEmergencyCtrl = false;
station.states.ipRtuStusInLocalCtrl = false;
station.states.ipRtuStusInCentralCtrl = false;
station.doRepaint();
};
StationOperateMenu.open(e.global);
}

View File

@ -99,6 +99,25 @@ const RedoOptions: MenuItemOptions = {
const SelectAllOptions: MenuItemOptions = {
name: '全选',
};
const oneLayerOptions: MenuItemOptions = {
name: '图层一',
};
const twoLayerOptions: MenuItemOptions = {
name: '图层二',
};
const threeLayerOptions: MenuItemOptions = {
name: '图层三',
};
const layerOptions: MenuItemOptions = {
name: '图层',
subMenu: [
{
name: '图层菜单',
items: [oneLayerOptions, twoLayerOptions, threeLayerOptions],
},
],
};
export const DefaultCanvasMenu = new ContextMenu({
name: '绘制-画布菜单',
@ -109,6 +128,9 @@ export const DefaultCanvasMenu = new ContextMenu({
{
items: [SelectAllOptions],
},
{
items: [layerOptions],
},
],
});
@ -179,6 +201,12 @@ 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>(
AxleCounting.Type
);
const trainWindows = app.queryStore.queryByType<TrainWindow>(
TrainWindow.Type
);
UndoOptions.handler = () => {
app.opRecord.undo();
};
@ -188,6 +216,24 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
SelectAllOptions.handler = () => {
app.selectAllGraphics();
};
oneLayerOptions.handler = () => {
axleCountings.forEach((axleCounting) => {
axleCounting.visible = false;
});
};
twoLayerOptions.handler = () => {
trainWindows.forEach((trainWindow) => {
trainWindow.visible = false;
});
};
threeLayerOptions.handler = () => {
axleCountings.forEach((axleCounting) => {
axleCounting.visible = true;
});
trainWindows.forEach((trainWindow) => {
trainWindow.visible = true;
});
};
DefaultCanvasMenu.open(e.global);
});
app.addKeyboardListener(

View File

@ -19,8 +19,12 @@ import {
PlatformState,
} from './graphics/PlatformInteraction';
import { PlatformTemplate, Platform } from 'src/graphics/platform/Platform';
import { StationData, StationState } from './graphics/StationInteraction';
import { StationTemplate } from 'src/graphics/station/Station';
import {
StationData,
StationOperateInteraction,
StationState,
} from './graphics/StationInteraction';
import { Station, StationTemplate } from 'src/graphics/station/Station';
import { TurnoutData } from './graphics/TurnoutInteraction';
import { TurnoutTemplate } from 'src/graphics/turnout/Turnout';
import { SectionData } from './graphics/SectionInteraction';
@ -32,6 +36,16 @@ import { toUint8Array } from 'js-base64';
import { getWebsocketUrl } from 'src/configs/UrlManage';
import { getJwtToken } from 'src/configs/TokenManage';
import { state } from 'src/protos/ws_message';
import {
AxleCounting,
AxleCountingTemplate,
} from 'src/graphics/axleCounting/AxleCounting';
import { AxleCountingData } from './graphics/AxleCountingInteraction';
import {
TrainWindow,
TrainWindowTemplate,
} from 'src/graphics/trainWindow/TrainWindow';
import { TrainWindowData } from './graphics/TrainWindowInteraction';
let lineApp: GraphicApp | null = null;
let msgBroker: AppWsMsgBroker | null = null;
@ -59,6 +73,8 @@ export function initLineApp(dom: HTMLElement): GraphicApp {
new StationTemplate(new StationData(), new StationState()),
new TurnoutTemplate(new TurnoutData()),
new SectionTemplate(new SectionData()),
new AxleCountingTemplate(new AxleCountingData()),
new TrainWindowTemplate(new TrainWindowData()),
];
lineApp.registerGraphicTemplates(...graphicTemplate);
lineApp.setOptions({
@ -68,11 +84,16 @@ export function initLineApp(dom: HTMLElement): GraphicApp {
wheelZoom: true,
},
interactiveTypeOptions: {
interactiveGraphicTypeIncludes: [Signal.Type, Platform.Type],
interactiveGraphicTypeIncludes: [
Signal.Type,
Platform.Type,
Station.Type,
],
},
});
SignalOperateInteraction.init(lineApp);
PlatformOperateInteraction.init(lineApp);
StationOperateInteraction.init(lineApp);
return lineApp;
}
@ -113,8 +134,28 @@ export async function loadLineDatas(app: GraphicApp) {
storage.section.forEach((section) => {
datas.push(new SectionData(section));
});
storage.axleCountings.forEach((axleCounting) => {
datas.push(new AxleCountingData(axleCounting));
});
storage.trainWindows.forEach((trainWindow) => {
datas.push(new TrainWindowData(trainWindow));
});
await app.loadGraphic(datas);
//隐藏计轴--和车次窗
const axleCountings = app.queryStore.queryByType<AxleCounting>(
AxleCounting.Type
);
axleCountings.forEach((axleCounting) => {
axleCounting.visible = false;
});
const trainWindows = app.queryStore.queryByType<TrainWindow>(
TrainWindow.Type
);
trainWindows.forEach((trainWindow) => {
trainWindow.visible = false;
});
StompCli.new({
wsUrl: `${getWebsocketUrl()}`,
token: getJwtToken() as string,

View File

@ -1,10 +1,12 @@
import { Color, Container, Graphics, Rectangle } from 'pixi.js';
import { Color, Container, Graphics, Point, Rectangle } from 'pixi.js';
import {
GraphicAnimation,
GraphicData,
GraphicState,
JlGraphic,
JlGraphicTemplate,
VectorText,
calculateMirrorPoint,
getRectangleCenter,
} from 'src/jl-graphic';
@ -59,12 +61,14 @@ export enum PlatformColorEnum {
grey = '0x7F7F7F', //站台没有列车停站
yellow = '0xfbff00', //列车在站台停站
blue = '0xC0C0FE', //列车在站台跳停
white = '0xffffff',
lozengeRed = '0xff0000', //站台旁的菱形图标
whiteNumbers = '0xffffff', //站台旁白色数字
whiteCircle = '0xffffff', //H字符旁的圆圈
HCharYellow = '0xfbff00', //站台旁的H字符
HCharYellow = '0xfbff00', //站台旁的扣字
HCharWhite = '0xffffff',
HCharRed = '0xff0000',
SCharBlue = '0x00FFCC', ////站台旁的跳字
doorGreen = '0x00FF00', //屏蔽门的颜色
doorRed = '0xff0000',
doorBlue = '0x4048C4',
@ -78,7 +82,7 @@ const platformConsts = {
doorOpenSpacing: 15,
doorPlatformSpacing: 10,
besideSpacing: 10,
circleRadius: 1,
circleRadius: 9,
};
//子元素--矩形
@ -93,12 +97,12 @@ export class rectGraphic extends Container {
draw(state: IPlatformState): void {
const rectGraphic = this.rectGraphic;
rectGraphic.clear();
let fillColor = PlatformColorEnum.grey;
let fillColor = PlatformColorEnum.white;
if (state.trainberth) {
fillColor = PlatformColorEnum.yellow;
}
if (state.upSkipstop || state.downSkipstop) {
fillColor = PlatformColorEnum.blue;
fillColor = PlatformColorEnum.grey;
}
rectGraphic.lineStyle(platformConsts.lineWidth, new Color(fillColor));
rectGraphic.beginFill(fillColor, 1);
@ -152,14 +156,6 @@ export class doorGraphic extends Container {
doorCloseGraphic.lineStyle(platformConsts.lineWidth, new Color(lineColor));
doorCloseGraphic.moveTo(-platformConsts.doorOpenSpacing, 0);
doorCloseGraphic.lineTo(platformConsts.doorOpenSpacing, 0);
doorGraphic.position.set(
0,
-platformConsts.height / 2 - platformConsts.doorPlatformSpacing
);
doorCloseGraphic.position.set(
0,
-platformConsts.height / 2 - platformConsts.doorPlatformSpacing
);
}
clear(): void {
this.doorGraphic.clear();
@ -176,43 +172,49 @@ export class doorGraphic extends Container {
//子元素--字符
class codeGraph extends Container {
static Type = 'Code';
character: VectorText = new VectorText(''); //扣车H
hold: VectorText = new VectorText(''); //扣车
runLevel: VectorText = new VectorText(''); //运行等级
runTime: VectorText = new VectorText(''); //运行时间
stopTime: VectorText = new VectorText(''); //停站时间
skipStop: VectorText = new VectorText(''); //调停
circle: Graphics = new Graphics();
constructor() {
super();
this.addChild(this.character);
this.addChild(this.runTime);
this.addChild(this.circle);
this.addChild(this.hold);
this.addChild(this.runLevel);
this.addChild(this.stopTime);
this.character.setVectorFontSize(platformConsts.besideFontSize);
this.runTime.setVectorFontSize(platformConsts.besideFontSize);
this.addChild(this.runTime);
this.addChild(this.skipStop);
this.addChild(this.circle);
this.hold.setVectorFontSize(platformConsts.besideFontSize);
this.runLevel.setVectorFontSize(platformConsts.besideFontSize);
this.stopTime.setVectorFontSize(platformConsts.besideFontSize);
this.runTime.setVectorFontSize(platformConsts.besideFontSize);
this.skipStop.setVectorFontSize(platformConsts.besideFontSize);
}
draw(): void {
//扣车
const character = this.character;
character.text = 'H';
character.anchor.set(0.5);
character.position.set(
const hold = this.hold;
hold.text = '扣';
hold.anchor.set(0.5);
hold.position.set(
-platformConsts.width / 2 -
platformConsts.lineWidth / 2 -
(platformConsts.besideSpacing * 2) / 3,
(platformConsts.height * 3) / 4
-(platformConsts.height * 3) / 4
);
character.style.fill = PlatformColorEnum.whiteNumbers;
const circle = this.circle;
circle.clear();
circle.lineStyle(0.5, PlatformColorEnum.whiteCircle);
circle.drawCircle(0, 0, platformConsts.circleRadius);
circle.position.set(
hold.style.fill = PlatformColorEnum.HCharWhite;
//区间运行等级状态
const runLevel = this.runLevel;
runLevel.anchor.set(0.5);
runLevel.position.set(
-platformConsts.width / 2 -
platformConsts.lineWidth / 2 -
(platformConsts.besideSpacing * 4) / 3,
(platformConsts.height * 3) / 5
platformConsts.besideSpacing,
(-platformConsts.height * 4) / 5
);
//区间运行等级状态
runLevel.style.fill = PlatformColorEnum.yellow;
//区间运行时间
const runTime = this.runTime;
runTime.anchor.set(0.5);
runTime.position.set(
@ -226,19 +228,33 @@ class codeGraph extends Container {
const stopTime = this.stopTime;
stopTime.anchor.set(0.5);
stopTime.position.set(
platformConsts.width / 2 +
platformConsts.lineWidth / 2 +
-platformConsts.width / 2 -
platformConsts.lineWidth / 2 -
platformConsts.besideSpacing,
platformConsts.besideSpacing
0
);
stopTime.style.fill = PlatformColorEnum.whiteNumbers;
character.visible = false;
circle.visible = false;
runTime.visible = false;
//跳停
const skipStop = this.skipStop;
skipStop.text = '跳';
skipStop.anchor.set(0.5);
const ps = calculateMirrorPoint(new Point(0, 0), hold.position);
skipStop.position.set(ps.x + 4, ps.y);
skipStop.style.fill = PlatformColorEnum.SCharBlue;
const circle = this.circle;
circle.clear();
circle.lineStyle(1, PlatformColorEnum.SCharBlue);
circle.drawCircle(0, 0, platformConsts.circleRadius);
circle.position.copyFrom(skipStop.position);
hold.visible = false;
runLevel.visible = false;
stopTime.visible = false;
runTime.visible = false;
skipStop.visible = false;
circle.visible = false;
}
clear(): void {
this.character.destroy();
this.hold.destroy();
}
changeState(stateData: IPlatformState): void {
if (
@ -247,87 +263,117 @@ class codeGraph extends Container {
stateData.downHold ||
stateData.downOccHold
) {
this.character.text = 'H';
this.character.visible = true;
this.circle.visible = true;
this.hold.text = '扣';
this.hold.visible = true;
//上行扣车
if (stateData.upHold) {
this.character.style.fill = PlatformColorEnum.HCharYellow;
this.hold.style.fill = PlatformColorEnum.HCharYellow;
}
if (stateData.upOccHold) {
this.character.style.fill = PlatformColorEnum.HCharWhite;
this.hold.style.fill = PlatformColorEnum.HCharWhite;
}
if (stateData.upHold && stateData.upOccHold) {
this.character.style.fill = PlatformColorEnum.HCharRed;
this.hold.style.fill = PlatformColorEnum.HCharRed;
}
//下行扣车
if (stateData.downHold) {
this.character.style.fill = PlatformColorEnum.HCharYellow;
this.hold.style.fill = PlatformColorEnum.HCharYellow;
}
if (stateData.downOccHold) {
this.character.style.fill = PlatformColorEnum.HCharWhite;
this.hold.style.fill = PlatformColorEnum.HCharWhite;
}
if (stateData.downHold && stateData.downOccHold) {
this.character.style.fill = PlatformColorEnum.HCharRed;
}
//运行等级
if (stateData.nextSectionRunTime) {
this.runTime.visible = true;
this.runTime.text = stateData.nextSectionRunTime;
}
//停站时间
if (stateData.stopTime) {
this.stopTime.visible = true;
this.stopTime.text = stateData.stopTime;
this.hold.style.fill = PlatformColorEnum.HCharRed;
}
}
//运行等级
if (stateData.nextSectionRunLevel) {
this.runLevel.visible = true;
this.runLevel.text = stateData.nextSectionRunLevel;
}
//运行时间
if (stateData.nextSectionRunTime) {
this.runTime.visible = false;
this.runTime.text = stateData.nextSectionRunTime;
}
//停站时间
if (stateData.stopTime) {
this.stopTime.visible = true;
this.stopTime.text = stateData.stopTime;
}
//跳停
if (stateData.upSkipstop || stateData.downSkipstop) {
this.skipStop.visible = true;
this.circle.visible = true;
}
}
}
//子元素--站台旁菱形图标
class besideGraphic extends Container {
static Type = 'BesideGraphic';
besideGraphic: Graphics;
class emergClose extends JlGraphic {
static Type = 'emergClose';
lozenge: Graphics;
deltaTime = 0;
fillColor = PlatformColorEnum.lozengeRed;
constructor() {
super();
this.besideGraphic = new Graphics();
this.addChild(this.besideGraphic);
super(emergClose.Type);
this.lozenge = new Graphics();
this.addChild(this.lozenge);
}
draw(): void {
const besideGraphic = this.besideGraphic;
besideGraphic.clear();
besideGraphic.lineStyle(1, new Color(PlatformColorEnum.lozengeRed));
besideGraphic.beginFill(PlatformColorEnum.lozengeRed, 1);
besideGraphic.drawRect(
const lozenge = this.lozenge;
lozenge.clear();
lozenge.lineStyle(1, new Color(this.fillColor));
lozenge.beginFill(PlatformColorEnum.lozengeRed, 1);
lozenge.drawRect(
0,
0,
platformConsts.height / 4,
platformConsts.height / 4
);
besideGraphic.endFill();
lozenge.endFill();
const rect = new Rectangle(
0,
0,
platformConsts.height / 4,
platformConsts.height / 4
);
besideGraphic.pivot = getRectangleCenter(rect);
besideGraphic.rotation = Math.PI / 4;
besideGraphic.position.set(
0,
-platformConsts.height / 2 -
platformConsts.doorPlatformSpacing -
platformConsts.height / 3
);
besideGraphic.visible = false;
lozenge.pivot = getRectangleCenter(rect);
lozenge.rotation = Math.PI / 4;
lozenge.visible = false;
}
doRepaint() {
// this.draw()
}
clear(): void {
this.besideGraphic.clear();
this.lozenge.clear();
}
changeState(stateData: IPlatformState): void {
createFlashAnmiation(name: string): GraphicAnimation {
const flashAnmiation = GraphicAnimation.init({
name: name,
run: (dt: number) => {
this.deltaTime += dt;
if (this.deltaTime > 60) {
this.deltaTime = 0;
this.lozenge.visible = false;
} else if (this.deltaTime > 30) {
this.lozenge.visible = true;
}
},
});
return flashAnmiation;
}
changeState(id: string, stateData: IPlatformState): void {
let redFlash = this.animation(`${id}emergClose_red_flash`);
if (stateData.emergstop) {
this.besideGraphic.visible = true;
if (!redFlash) {
redFlash = this.createFlashAnmiation(`${id}emergClose_red_flash`);
this.addAnimation(redFlash);
}
redFlash.resume();
} else {
this.besideGraphic.visible = false;
if (redFlash) {
redFlash.pause();
}
}
}
}
@ -336,13 +382,13 @@ export class Platform extends JlGraphic {
static Type = 'Platform';
platformGraphic: rectGraphic = new rectGraphic();
doorGraphic: doorGraphic = new doorGraphic();
besideGraphic: besideGraphic = new besideGraphic();
emergClose: emergClose = new emergClose();
codeGraph: codeGraph = new codeGraph();
constructor() {
super(Platform.Type);
this.addChild(this.platformGraphic);
this.addChild(this.doorGraphic);
this.addChild(this.besideGraphic);
this.addChild(this.emergClose);
this.addChild(this.codeGraph);
}
@ -358,53 +404,36 @@ export class Platform extends JlGraphic {
this.doorGraphic.draw(this.states);
}
this.platformGraphic.draw(this.states);
this.besideGraphic.draw();
this.emergClose.draw();
this.codeGraph.draw();
this.doorGraphic.position.set(0, 0);
this.besideGraphic.position.set(0, 0);
this.doorGraphic.position.set(
0,
-platformConsts.height / 2 - platformConsts.doorPlatformSpacing
);
this.emergClose.position.set(
0,
-platformConsts.height / 2 -
platformConsts.doorPlatformSpacing -
platformConsts.height / 3
);
this.codeGraph.position.set(0, 0);
//站台方向
if (this.datas.direction == 'down') {
this.doorGraphic.position.set(
0,
platformConsts.height + platformConsts.doorPlatformSpacing * 2
);
this.besideGraphic.position.set(
0,
platformConsts.height +
platformConsts.doorPlatformSpacing * 2 +
(platformConsts.height * 2) / 3
);
this.codeGraph.children[0].position.set(
platformConsts.width / 2 +
platformConsts.lineWidth / 2 +
(platformConsts.besideSpacing * 2) / 3,
-(platformConsts.height * 3) / 4
);
this.codeGraph.children[1].position.set(
-platformConsts.width / 2 -
platformConsts.lineWidth / 2 -
platformConsts.besideSpacing,
platformConsts.besideSpacing
);
this.codeGraph.children[2].position.set(
platformConsts.width / 2 +
platformConsts.lineWidth / 2 +
(platformConsts.besideSpacing * 4) / 3,
(-platformConsts.height * 10) / 11
);
this.codeGraph.children[3].position.set(
-platformConsts.width / 2 -
platformConsts.lineWidth / 2 -
platformConsts.besideSpacing,
-platformConsts.besideSpacing
);
const psChange = [
this.doorGraphic,
this.emergClose,
...this.codeGraph.children,
];
psChange.forEach((g) => {
g.position.copyFrom(calculateMirrorPoint(new Point(0, 0), g.position));
});
}
this.changeState();
}
changeState(): void {
this.doorGraphic.changeState(this.states);
this.besideGraphic.changeState(this.states);
this.emergClose.changeState(this.id, this.states);
this.codeGraph.changeState(this.states);
}
}

View File

@ -8,14 +8,7 @@ import {
JlGraphic,
} from 'src/jl-graphic';
import {
IPlatformData,
Platform,
PlatformTemplate,
rectGraphic,
doorGraphic,
IPlatformState,
} from './Platform';
import { IPlatformData, Platform, PlatformTemplate } from './Platform';
export interface IPlatformDrawOptions {
newData: () => IPlatformData;
@ -25,9 +18,7 @@ export class PlatformDraw extends GraphicDrawAssistant<
PlatformTemplate,
IPlatformData
> {
platformGraphic: rectGraphic = new rectGraphic();
doorGraphic: doorGraphic = new doorGraphic();
platformGraphic: Platform;
constructor(app: JlDrawApp, template: PlatformTemplate) {
super(
app,
@ -35,20 +26,19 @@ export class PlatformDraw extends GraphicDrawAssistant<
'svguse:../../drawIcon.svg#icon-platform',
'站台Platform'
);
this.platformGraphic = this.graphicTemplate.new();
this.container.addChild(this.platformGraphic);
this.container.addChild(this.doorGraphic);
platformInteraction.init(app);
}
bind(): void {
super.bind();
this.platformGraphic.draw(this.graphicTemplate.states as IPlatformState);
this.doorGraphic.draw(this.graphicTemplate.states as IPlatformState);
this.platformGraphic.loadData(this.graphicTemplate.datas);
this.platformGraphic.doRepaint();
}
clearCache(): void {
this.platformGraphic.clear();
this.doorGraphic.clear();
//this.platformGraphic.clear();
}
onLeftDown(e: FederatedPointerEvent): void {
this.container.position.copyFrom(this.toCanvasCoordinates(e.global));

View File

@ -16,7 +16,7 @@ import {
protoPort2Data,
} from '../CommonGraphics';
import { Turnout } from '../turnout/Turnout';
import { SectionData } from 'src/drawApp/graphics/SectionInteraction';
import Vector2 from 'src/jl-graphic/math/Vector2';
export enum SectionType {
Physical = 0,
@ -134,13 +134,48 @@ export class Section extends JlGraphic implements ILineGraphic {
/** 获取拆分逻辑区段数据 */
getSplitPoints(count: number): IPointData[][] {
if (this.datas.points.length !== 2) {
throw Error('多段分割待实现');
let totalLen = 0;
const lengths: number[] = [];
for (let i = 1; i < this.datas.points.length; i++) {
const { x: x1, y: y1 } = this.datas.points[i - 1],
{ x: x2, y: y2 } = this.datas.points[i];
const len = new Vector2([x2 - x1, y2 - y1]).length();
totalLen += len;
lengths.push(len);
}
const counts = lengths.map((length) =>
Math.round((count * length) / totalLen)
);
if (counts.reduce((p, c) => p + c, 0) !== count) {
const intersection = counts.reduce((p, c) => p + c, 0) - count;
let maxCountIndex = 0,
maxCount = 0;
counts.forEach((c, i) => {
if (c > maxCount) {
maxCount = c;
maxCountIndex = i;
}
});
counts[maxCountIndex] + intersection;
}
return counts
.map((count, i) => {
return splitLineEvenly(
this.localToCanvasPoint(this.datas.points[i]),
this.localToCanvasPoint(this.datas.points[i + 1]),
count
);
})
.flat();
} else {
return splitLineEvenly(
this.localToCanvasPoint(this.datas.points[0]),
this.localToCanvasPoint(
this.datas.points[this.datas.points.length - 1]
),
count
);
}
return splitLineEvenly(
this.localToCanvasPoint(this.datas.points[0]),
this.localToCanvasPoint(this.datas.points[this.datas.points.length - 1]),
count
);
}
buildRelation() {

View File

@ -4,6 +4,7 @@ import {
GraphicApp,
GraphicDrawAssistant,
GraphicInteractionPlugin,
GraphicRelation,
GraphicTransform,
GraphicTransformEvent,
JlDrawApp,
@ -15,25 +16,37 @@ import {
ISectionData,
Section,
SectionConsts,
SectionPort,
SectionTemplate,
SectionType,
} from './Section';
import {
DisplayObject,
FederatedMouseEvent,
Graphics,
IHitArea,
IPointData,
Point,
} from 'pixi.js';
import {
IEditPointOptions,
ILineGraphic,
PolylineEditPlugin,
addWayPoint,
clearWayPoint,
getWaypointRangeIndex,
} from 'src/jl-graphic/plugins/GraphicEditPlugin';
import AbsorbablePoint, {
AbsorbableLine,
AbsorbablePosition,
} from 'src/jl-graphic/graphic/AbsorbablePosition';
import { Turnout } from '../turnout/Turnout';
import { Turnout, TurnoutPort } from '../turnout/Turnout';
import { MenuItemOptions } from 'src/jl-graphic/ui/Menu';
import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu';
import { Dialog } from 'quasar';
import { SectionData } from 'src/drawApp/graphics/SectionInteraction';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import SectionSplitDialog from 'src/components/draw-app/dialogs/SectionSplitDialog.vue';
export class SectionDraw extends GraphicDrawAssistant<
SectionTemplate,
@ -46,7 +59,7 @@ export class SectionDraw extends GraphicDrawAssistant<
super(app, template, 'sym_o_timeline', '区段Section');
this.container.addChild(this.graphic);
SectionPointEditPlugin.init(app);
SectionPointEditPlugin.init(app, this);
}
onLeftDown(e: FederatedMouseEvent): void {
@ -88,20 +101,21 @@ export class SectionDraw extends GraphicDrawAssistant<
prepareData(data: ISectionData): boolean {
data.points = this.points;
data.code = 'G000';
data.childTransforms?.push(
data.childTransforms = [
new ChildTransform(
'label',
new GraphicTransform(
{
x: data.points[1].x - data.points[0].x,
y: data.points[1].y - data.points[0].y + 20,
x: data.points[0].x + (data.points[1].x - data.points[0].x) / 2,
y:
data.points[0].y + (data.points[1].y - data.points[0].y) / 2 + 20,
},
{ x: 0, y: 0 },
0,
{ x: 0, y: 0 }
)
)
);
),
];
return true;
}
@ -191,9 +205,71 @@ class SectionPolylineEditPlugin extends PolylineEditPlugin {
this.updateEditedPointsPosition();
}
reset(): void {
super.reset();
this.initLabels();
setRelatedDrag() {
const len = this.editedPoints.length;
this.editedPoints.forEach((ep, i) => {
if (i === 0 || i === len - 1) {
let relations: GraphicRelation[];
if (i === 0) {
relations = this.graphic.relationManage
.getRelationsOfGraphic(this.graphic)
.filter(
(relation) =>
relation.getRelationParam(this.graphic).param === SectionPort.A
);
} else {
relations = this.graphic.relationManage
.getRelationsOfGraphic(this.graphic)
.filter(
(relation) =>
relation.getRelationParam(this.graphic).param === SectionPort.B
);
}
if (!relations.length) return;
const points: IPointData[] = [];
const otherGraphics = relations.map((relation) =>
relation.getOtherGraphic(this.graphic)
);
const otherPorts = relations.map(
(relation) => relation.getOtherRelationParam(this.graphic).param
);
otherGraphics.forEach((otherGraphic, i) => {
const otherPort = otherPorts[i];
if (otherGraphic instanceof Turnout) {
if (otherPort === TurnoutPort.A) {
points.push(
otherGraphic.datas.pointA[otherGraphic.datas.pointA.length - 1]
);
} else if (otherPort === TurnoutPort.B) {
points.push(
otherGraphic.datas.pointB[otherGraphic.datas.pointB.length - 1]
);
} else if (otherPort === TurnoutPort.C) {
points.push(
otherGraphic.datas.pointC[otherGraphic.datas.pointC.length - 1]
);
}
} else if (otherGraphic instanceof Section) {
if (otherPort === SectionPort.A) {
points.push(otherGraphic.datas.points[0]);
} else if (otherPort === SectionPort.B) {
points.push(
otherGraphic.datas.points[otherGraphic.datas.points.length - 1]
);
}
}
});
const transformingHandler = () => {
otherGraphics.forEach((otherGraphic, i) => {
const p = otherGraphic.canvasToLocalPoint(ep);
points[i].x = p.x;
points[i].y = p.y;
otherGraphic.repaint();
});
};
ep.on('transforming', transformingHandler);
}
});
}
updateEditedPointsPosition() {
@ -209,14 +285,39 @@ class SectionPolylineEditPlugin extends PolylineEditPlugin {
}
}
export const addWaypointConfig: MenuItemOptions = {
name: '添加路径点',
};
export const clearWaypointsConfig: MenuItemOptions = {
name: '清除所有路径点',
};
export const splitSectionConfig: MenuItemOptions = {
name: '拆分',
// disabled: true,
};
const SectionEditMenu: ContextMenu = ContextMenu.init({
name: '区段编辑菜单',
groups: [
{
items: [addWaypointConfig, clearWaypointsConfig],
},
{
items: [splitSectionConfig],
},
],
});
export class SectionPointEditPlugin extends GraphicInteractionPlugin<Section> {
static Name = 'SectionPointDrag';
drawAssistant: SectionDraw;
constructor(app: GraphicApp) {
constructor(app: GraphicApp, da: SectionDraw) {
super(SectionPointEditPlugin.Name, app);
this.drawAssistant = da;
app.registerMenu(SectionEditMenu);
}
static init(app: GraphicApp) {
return new SectionPointEditPlugin(app);
static init(app: GraphicApp, da: SectionDraw) {
return new SectionPointEditPlugin(app, da);
}
filter(...grahpics: JlGraphic[]): Section[] | undefined {
return grahpics.filter((g) => g.type == Section.Type) as Section[];
@ -232,14 +333,118 @@ export class SectionPointEditPlugin extends GraphicInteractionPlugin<Section> {
g.labelGraphic.draggable = true;
g.on('selected', this.onSelected, this);
g.on('unselected', this.onUnselected, this);
g.on('_rightclick', this.onContextMenu, this);
}
unbind(g: Section): void {
g.off('selected', this.onSelected, this);
g.off('unselected', this.onUnselected, this);
g.off('_rightclick', this.onContextMenu, this);
}
onContextMenu(e: FederatedMouseEvent) {
const target = e.target as DisplayObject;
const section = target.getGraphic() as Section;
this.app.updateSelected(section);
const p = section.screenToLocalPoint(e.global);
addWaypointConfig.handler = () => {
const linePoints = section.linePoints;
const { start, end } = getWaypointRangeIndex(
linePoints,
false,
p,
SectionConsts.lineWidth
);
addWayPoint(section, false, start, end, p);
};
clearWaypointsConfig.handler = () => {
clearWayPoint(section, false);
};
if (
section.datas.children &&
section.datas.sectionType === SectionType.Physical
) {
splitSectionConfig.disabled = false;
splitSectionConfig.handler = () => {
Dialog.create({
title: '拆分区段',
message: '请选择生成数量和方向',
component: SectionSplitDialog,
cancel: true,
persistent: true,
}).onOk((data: { num: number; dir: 'ltr' | 'rtl' }) => {
const { num, dir } = data;
const sectionData = section.datas;
const points = section.getSplitPoints(num);
const children: Section[] = [];
let codeAppend = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.slice(0, num);
if (
(dir === 'ltr' &&
sectionData.points[0].x >
sectionData.points[sectionData.points.length - 1].x) ||
(dir === 'rtl' &&
sectionData.points[0].x <
sectionData.points[sectionData.points.length - 1].x)
) {
codeAppend = codeAppend.split('').reverse().join('');
}
points.forEach((ps, i) => {
const data = new SectionData();
data.id = this.drawAssistant.nextId();
data.code = `${sectionData.code}-${codeAppend.charAt(i % 26)}`;
data.sectionType = SectionType.Logic;
data.points = ps.map(
(p) => new graphicData.Point({ x: p.x, y: p.y })
);
data.id = this.drawAssistant.nextId();
data.childTransforms = [
new ChildTransform(
'label',
new GraphicTransform(
{
x:
data.points[0].x +
(data.points[1].x - data.points[0].x) / 2,
y:
data.points[0].y +
(data.points[1].y - data.points[0].y) / 2 +
20,
},
{ x: 0, y: 0 },
0,
{ x: 0, y: 0 }
)
),
];
const g = this.drawAssistant.graphicTemplate.new();
g.loadData(data);
this.drawAssistant.storeGraphic(g);
children.push(g);
});
sectionData.children = children.map((g) => g.datas.id);
section.repaint();
section.buildRelation();
section.draggable = false;
children.forEach((c) => c.buildRelation());
this.app.updateSelected(...children);
});
};
} else {
splitSectionConfig.disabled = true;
}
SectionEditMenu.open(e.global);
}
onSelected(g: DisplayObject): void {
const section = g as Section;
if (
section.datas.children.length > 0 &&
section.datas.sectionType === SectionType.Physical
) {
return;
}
let lep = section.getAssistantAppend<SectionPolylineEditPlugin>(
SectionPolylineEditPlugin.Name
);
@ -248,6 +453,7 @@ export class SectionPointEditPlugin extends GraphicInteractionPlugin<Section> {
section.addAssistantAppend(lep);
}
lep.showAll();
lep.setRelatedDrag();
}
onUnselected(g: DisplayObject): void {
const section = g as Section;

View File

@ -1,4 +1,4 @@
import { Color, Container, Graphics } from 'pixi.js';
import { Color, Container, Graphics, Point } from 'pixi.js';
import {
GraphicData,
GraphicState,
@ -34,116 +34,245 @@ export interface IStationState extends GraphicState {
}
const stationConsts = {
interlockControl: '0xCC3399',
emergencyStationControl: '0xFF0000',
stationControl: '0xFFFF00',
centralControl: '0x08F80D',
radius: 3,
borderWidth: 1,
circleColorWhite: '0xFFFFFF',
circleColorGrey: '0x808080',
circleColorBlue: '0x08F80D',
circleColorYellow: '0xFFFA0C',
codeColor: '0xF48815',
codeFontSize: 22,
codeControlFontSize: 12,
codeControlFontSize: 10,
codeOffsetY: 30,
circleOffsetY: 20,
circleBetweenOffset: 40,
circleBetweenOffset: 50,
kilometerCodeColor: '0xFFFFFF',
kilometerCodeFontSize: 8,
kilometerCodeOffsetY: -25,
};
class constrolGraphic extends Container {
circleA: Graphics = new Graphics();
codeGraphA: VectorText = new VectorText(''); //控制名--站控
codeGraphA: VectorText = new VectorText(''); //控制名--紧急站控
circleB: Graphics = new Graphics();
codeGraphB: VectorText = new VectorText(''); //控制名--中控
arrow: Graphics = new Graphics();
inArrow: Graphics = new Graphics();
circleC: Graphics = new Graphics();
codeGraphC: VectorText = new VectorText(''); //控制名--站控
circleD: Graphics = new Graphics();
codeGraphD: VectorText = new VectorText(''); //控制名--联锁控
circleE: Graphics = new Graphics();
codeGraphE: VectorText = new VectorText(''); //控制名--按图折返
constructor() {
super();
this.addChild(this.circleA);
this.addChild(this.codeGraphA);
this.addChild(this.circleB);
this.addChild(this.codeGraphB);
this.addChild(this.arrow);
this.addChild(this.inArrow);
this.addChild(this.circleC);
this.addChild(this.codeGraphC);
this.addChild(this.circleD);
this.addChild(this.codeGraphD);
this.addChild(this.circleE);
this.addChild(this.codeGraphE);
this.codeGraphA.setVectorFontSize(stationConsts.codeFontSize);
this.codeGraphB.setVectorFontSize(stationConsts.codeFontSize);
this.codeGraphC.setVectorFontSize(stationConsts.codeFontSize);
this.codeGraphD.setVectorFontSize(stationConsts.codeFontSize);
this.codeGraphE.setVectorFontSize(stationConsts.codeFontSize);
}
draw(states: IStationState): void {
let StationControlFillColor = stationConsts.circleColorGrey;
let centralControlFillColor = stationConsts.circleColorBlue;
let inArrowFillColor = stationConsts.circleColorGrey;
if (states.ipRtuStusInLocalCtrl) {
StationControlFillColor = stationConsts.circleColorYellow;
centralControlFillColor = stationConsts.circleColorGrey;
if (!states.ipRtuStusDown) {
inArrowFillColor = stationConsts.circleColorBlue;
const graphics = [
{
circle: this.circleA,
codeGraph: this.codeGraphA,
codeText: '紧急站控',
circleFillColor: stationConsts.circleColorGrey,
codeGraphFillColor: stationConsts.circleColorWhite,
},
{
circle: this.circleB,
codeGraph: this.codeGraphB,
codeText: '中控',
circleFillColor: stationConsts.circleColorBlue,
codeGraphFillColor: stationConsts.circleColorBlue,
},
{
circle: this.circleC,
codeGraph: this.codeGraphC,
codeText: '站控',
circleFillColor: stationConsts.circleColorGrey,
codeGraphFillColor: stationConsts.circleColorWhite,
circlePs: new Point(0, stationConsts.circleOffsetY),
codeGraphPs: new Point(0, stationConsts.codeOffsetY),
},
{
circle: this.circleD,
codeGraph: this.codeGraphD,
codeText: '联锁控',
circleFillColor: stationConsts.circleColorGrey,
codeGraphFillColor: stationConsts.circleColorWhite,
},
{
circle: this.circleE,
codeGraph: this.codeGraphE,
codeText: '按图折返',
circleFillColor: stationConsts.circleColorYellow,
codeGraphFillColor: stationConsts.circleColorYellow,
},
];
if (
states.ipRtuStusInEmergencyCtrl ||
states.ipRtuStusInLocalCtrl ||
states.ipRtuStusInCentralCtrl
) {
graphics[1].circleFillColor = stationConsts.circleColorGrey;
graphics[1].codeGraphFillColor = stationConsts.circleColorWhite;
if (states.ipRtuStusInEmergencyCtrl) {
graphics[0].circleFillColor = stationConsts.emergencyStationControl;
graphics[0].codeGraphFillColor = stationConsts.emergencyStationControl;
} else if (states.ipRtuStusInCentralCtrl) {
graphics[1].circleFillColor = stationConsts.centralControl;
graphics[1].codeGraphFillColor = stationConsts.centralControl;
} else if (states.ipRtuStusInLocalCtrl) {
graphics[2].circleFillColor = stationConsts.stationControl;
graphics[2].codeGraphFillColor = stationConsts.stationControl;
}
}
this.drawCircleCode(
this.circleA,
this.codeGraphA,
'站控',
StationControlFillColor
);
this.circleA.position.set(
stationConsts.circleBetweenOffset / 2,
stationConsts.circleOffsetY
);
this.codeGraphA.position.set(
stationConsts.circleBetweenOffset / 2,
stationConsts.codeOffsetY
);
this.drawCircleCode(
this.circleB,
this.codeGraphB,
'中控',
centralControlFillColor
);
this.circleB.position.set(
-stationConsts.circleBetweenOffset / 2,
stationConsts.circleOffsetY
);
this.codeGraphB.position.set(
-stationConsts.circleBetweenOffset / 2,
stationConsts.codeOffsetY
);
const arrow = this.arrow;
arrow.clear();
arrow.lineStyle(stationConsts.borderWidth, new Color('0xFFFFFF'));
const points = [0, 0, 2, 2, 2, 1, 14, 1, 14, -1, 2, -1, 2, -2];
arrow.beginFill('0xFFFFFF');
arrow.drawPolygon(points);
arrow.endFill();
arrow.scale.set(1.1, 1.1);
arrow.position.set(-7, stationConsts.circleOffsetY);
const inArrow = this.inArrow;
inArrow.beginFill(inArrowFillColor);
inArrow.drawPolygon(points);
inArrow.endFill();
inArrow.position.set(-6.5, stationConsts.circleOffsetY);
const graphicsPs = [
{
circlePs: new Point(
-stationConsts.circleBetweenOffset * 2,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
-stationConsts.circleBetweenOffset * 2,
stationConsts.codeOffsetY
),
},
{
circlePs: new Point(
-stationConsts.circleBetweenOffset,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
-stationConsts.circleBetweenOffset,
stationConsts.codeOffsetY
),
},
{
circlePs: new Point(0, stationConsts.circleOffsetY),
codeGraphPs: new Point(0, stationConsts.codeOffsetY),
},
{
circlePs: new Point(
stationConsts.circleBetweenOffset,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
stationConsts.circleBetweenOffset,
stationConsts.codeOffsetY
),
},
{
circlePs: new Point(
stationConsts.circleBetweenOffset * 2,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
stationConsts.circleBetweenOffset * 2,
stationConsts.codeOffsetY
),
},
];
const graphicsPsChange = [
{
circlePs: new Point(
(-stationConsts.circleBetweenOffset * 3) / 2,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
(-stationConsts.circleBetweenOffset * 3) / 2,
stationConsts.codeOffsetY
),
},
{
circlePs: new Point(
-stationConsts.circleBetweenOffset / 2,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
-stationConsts.circleBetweenOffset / 2,
stationConsts.codeOffsetY
),
},
{
circlePs: new Point(
stationConsts.circleBetweenOffset / 2,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
stationConsts.circleBetweenOffset / 2,
stationConsts.codeOffsetY
),
},
{
circlePs: new Point(
(stationConsts.circleBetweenOffset * 3) / 2,
stationConsts.circleOffsetY
),
codeGraphPs: new Point(
(stationConsts.circleBetweenOffset * 3) / 2,
stationConsts.codeOffsetY
),
},
];
//graphics.pop();
graphics.forEach((g, i) => {
Object.assign(g, graphicsPs[i]);
//Object.assign(g, graphicsPsChange[i]);
this.drawCircleCode(
g.circle,
g.codeGraph,
g.codeText,
g.circleFillColor,
g.codeGraphFillColor
);
g.circle.position.copyFrom(g.circlePs as Point);
g.codeGraph.position.copyFrom(g.codeGraphPs as Point);
});
}
drawCircleCode(
circle: Graphics,
codeGraph: VectorText,
code: string,
fillcolor: string
circleFillColor: string,
codeGraphFillColor: string
): void {
circle.clear();
circle.lineStyle(stationConsts.borderWidth, new Color(fillcolor));
circle.beginFill(fillcolor, 1);
circle.lineStyle(stationConsts.borderWidth, new Color(circleFillColor));
circle.beginFill(circleFillColor, 1);
circle.drawCircle(0, 0, stationConsts.radius);
circle.endFill;
codeGraph.text = code;
codeGraph.style.fill = fillcolor;
codeGraph.style.fill = codeGraphFillColor;
codeGraph.setVectorFontSize(stationConsts.codeControlFontSize);
codeGraph.anchor.set(0.5);
}
clear(): void {
this.circleA.clear();
this.circleB.clear();
this.circleC.clear();
this.circleD.clear();
this.circleE.clear();
this.codeGraphA.text = '';
this.codeGraphB.text = '';
this.arrow.clear();
this.inArrow.clear();
this.codeGraphC.text = '';
this.codeGraphD.text = '';
this.codeGraphE.text = '';
}
}
export class Station extends JlGraphic {

View File

@ -4,6 +4,7 @@ import {
GraphicApp,
GraphicDrawAssistant,
GraphicInteractionPlugin,
GraphicRelation,
GraphicTransformEvent,
JlDrawApp,
JlGraphic,
@ -31,7 +32,7 @@ import {
GraphicEditPlugin,
getWaypointRangeIndex,
} from 'src/jl-graphic/plugins/GraphicEditPlugin';
import { Section } from '../section/Section';
import { Section, SectionPort } from '../section/Section';
import AbsorbablePoint, {
AbsorbableLine,
} from 'src/jl-graphic/graphic/AbsorbablePosition';
@ -338,8 +339,8 @@ export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin<Tur
tep = new TurnoutEditPlugin(turnout, { onEditPointCreate });
turnout.addAssistantAppend(tep);
}
tep.reset();
tep.showAll();
tep.setRelatedDrag();
}
onUnSelected(g: DisplayObject) {
@ -380,6 +381,82 @@ export class TurnoutEditPlugin extends GraphicEditPlugin<Turnout> {
this.removeChildren();
this.initEditPoints();
}
hideAll(): void {
super.hideAll();
}
setRelatedDrag() {
this.editPoints.forEach((eps, i) => {
const ep = eps[eps.length - 1];
let relations: GraphicRelation[];
if (i === 0) {
relations = this.graphic.relationManage
.getRelationsOfGraphic(this.graphic)
.filter(
(relation) =>
relation.getRelationParam(this.graphic).param === TurnoutPort.A
);
} else if (i === 1) {
relations = this.graphic.relationManage
.getRelationsOfGraphic(this.graphic)
.filter(
(relation) =>
relation.getRelationParam(this.graphic).param === TurnoutPort.B
);
} else {
relations = this.graphic.relationManage
.getRelationsOfGraphic(this.graphic)
.filter(
(relation) =>
relation.getRelationParam(this.graphic).param === TurnoutPort.C
);
}
if (!relations.length) return;
const otherGraphics = relations.map((relation) =>
relation.getOtherGraphic(this.graphic)
);
console.log(otherGraphics);
const otherPorts = relations.map(
(relation) => relation.getOtherRelationParam(this.graphic).param
);
const point: IPointData[] = [];
otherGraphics.map((otherGraphic, i) => {
const otherPort = otherPorts[i];
if (otherGraphic instanceof Turnout) {
if (otherPort === TurnoutPort.A) {
point.push(
otherGraphic.datas.pointA[otherGraphic.datas.pointA.length - 1]
);
} else if (otherPort === TurnoutPort.B) {
point.push(
otherGraphic.datas.pointB[otherGraphic.datas.pointB.length - 1]
);
} else if (otherPort === TurnoutPort.C) {
point.push(
otherGraphic.datas.pointC[otherGraphic.datas.pointC.length - 1]
);
}
} else if (otherGraphic instanceof Section) {
if (otherPort === SectionPort.A) {
point.push(otherGraphic.datas.points[0]);
} else if (otherPort === SectionPort.B) {
point.push(
otherGraphic.datas.points[otherGraphic.datas.points.length - 1]
);
}
}
});
const transformingHandler = () => {
otherGraphics.forEach((otherGraphic, i) => {
const p = otherGraphic.canvasToLocalPoint(ep);
point[i].x = p.x;
point[i].y = p.y;
otherGraphic.repaint();
});
};
ep.on('transforming', transformingHandler);
});
}
initEditPoints() {
const cpA = this.graphic.localToCanvasPoints(...this.graphic.datas.pointA);