Merge branch 'master' of git.code.tencent.com:beijing-rtss-test/bj-rtss-client
This commit is contained in:
commit
6bd8bf17b9
@ -77,6 +77,10 @@
|
||||
drawStore.selectedGraphicType === AxleCountingSection.Type
|
||||
"
|
||||
></axle-counting-section-property>
|
||||
<LogicSectionProperty
|
||||
v-else-if="drawStore.selectedGraphicType === LogicSection.Type"
|
||||
>
|
||||
</LogicSectionProperty>
|
||||
<separator-property
|
||||
v-else-if="drawStore.selectedGraphicType === Separator.Type"
|
||||
></separator-property>
|
||||
@ -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';
|
||||
|
||||
|
@ -6,6 +6,15 @@
|
||||
v-model="axleCountingModel.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="计轴索引编号"
|
||||
type="textarea"
|
||||
@blur="onUpdate"
|
||||
v-model="axleCountingModel.indexNumber"
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
|
@ -7,6 +7,15 @@
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="计轴区段索引编号"
|
||||
type="textarea"
|
||||
@blur="onUpdate"
|
||||
v-model="axleCountingSectionModel.indexNumber"
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="计轴区段名称"
|
||||
@ -16,31 +25,30 @@
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model="kilometerSystem.coordinateSystem"
|
||||
:options="CoordinateSystemOptions"
|
||||
:map-options="true"
|
||||
:emit-value="true"
|
||||
@update:model-value="onUpdate"
|
||||
label="坐标系"
|
||||
></q-select>
|
||||
<q-input
|
||||
outlined
|
||||
style="margin-top: 10px"
|
||||
v-model.number="kilometerSystem.kilometer"
|
||||
type="number"
|
||||
@blur="onUpdate"
|
||||
label="公里标(mm):"
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> 关联的计轴 </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="item in sectionRelations"
|
||||
v-for="item in axleCountingRelations"
|
||||
:key="item"
|
||||
square
|
||||
color="primary"
|
||||
text-color="white"
|
||||
>
|
||||
{{ item }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> 关联道岔的位置关系 </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="item in turnoutRelations"
|
||||
:key="item"
|
||||
square
|
||||
color="primary"
|
||||
@ -59,19 +67,17 @@
|
||||
import { AxleCountingSectionData } from 'src/drawApp/graphics/AxleCountingSectionInteraction';
|
||||
import { AxleCounting } from 'src/graphics/axleCounting/AxleCounting';
|
||||
import { AxleCountingSection } from 'src/graphics/axleCountingSection/AxleCountingSection';
|
||||
import { Turnout } from 'src/graphics/turnout/Turnout';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { computed, onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const axleCountingSectionModel = reactive(new AxleCountingSectionData());
|
||||
const kilometerSystem = reactive({ coordinateSystem: '', kilometer: 0 });
|
||||
|
||||
const CoordinateSystemOptions = [
|
||||
{ label: '车辆段', value: 'DEPOT' },
|
||||
{ label: '停车场', value: 'PARKING_LOT' },
|
||||
{ label: '正线', value: 'MAIN_LINE' },
|
||||
{ label: '换线', value: 'TRANSFER' },
|
||||
];
|
||||
enum turoutPos {
|
||||
'定位',
|
||||
'反位',
|
||||
}
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
@ -101,7 +107,7 @@ function onUpdate() {
|
||||
}
|
||||
}
|
||||
|
||||
const sectionRelations = computed(() => {
|
||||
const axleCountingRelations = computed(() => {
|
||||
const axleCountingSection = drawStore.selectedGraphic as AxleCountingSection;
|
||||
const sectionRelations =
|
||||
axleCountingSection?.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
@ -112,7 +118,22 @@ const sectionRelations = computed(() => {
|
||||
(relation) =>
|
||||
`${
|
||||
relation.getOtherGraphic<AxleCounting>(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));
|
||||
});
|
||||
|
92
src/components/draw-app/properties/LogicSectionProperty.vue
Normal file
92
src/components/draw-app/properties/LogicSectionProperty.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<q-form class="q-gutter-sm">
|
||||
<q-input
|
||||
outlined
|
||||
readonly
|
||||
v-model="logicSectionModel.id"
|
||||
label="id"
|
||||
hint=""
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="索引编号"
|
||||
type="textarea"
|
||||
@blur="onUpdate"
|
||||
v-model="logicSectionModel.indexNumber"
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-input
|
||||
outlined
|
||||
label="逻辑区段名称"
|
||||
type="textarea"
|
||||
@blur="onUpdate"
|
||||
v-model="logicSectionModel.code"
|
||||
lazy-rules
|
||||
autogrow
|
||||
/>
|
||||
<q-list bordered separator class="rounded-borders">
|
||||
<q-item>
|
||||
<q-item-section no-wrap class="q-gutter-y-sm column">
|
||||
<q-item-label> 关联的计轴区段 </q-item-label>
|
||||
<div class="q-gutter-sm row">
|
||||
<q-chip
|
||||
v-for="item in logicSectionRelations"
|
||||
:key="item"
|
||||
square
|
||||
color="primary"
|
||||
text-color="white"
|
||||
>
|
||||
{{ item }}
|
||||
</q-chip>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LogicSectionData } from 'src/drawApp/graphics/LogicSectionInteraction';
|
||||
import { AxleCountingSection } from 'src/graphics/axleCountingSection/AxleCountingSection';
|
||||
import { LogicSection } from 'src/graphics/logicSection/LogicSection';
|
||||
import { useDrawStore } from 'src/stores/draw-store';
|
||||
import { computed, onMounted, reactive, watch } from 'vue';
|
||||
|
||||
const drawStore = useDrawStore();
|
||||
const logicSectionModel = reactive(new LogicSectionData());
|
||||
|
||||
drawStore.$subscribe;
|
||||
watch(
|
||||
() => drawStore.selectedGraphic,
|
||||
(val) => {
|
||||
if (val && val.type == LogicSection.Type) {
|
||||
logicSectionModel.copyFrom(val.saveData() as LogicSectionData);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const logicSection = drawStore.selectedGraphic as LogicSection;
|
||||
if (logicSection) {
|
||||
logicSectionModel.copyFrom(logicSection.saveData());
|
||||
}
|
||||
});
|
||||
|
||||
function onUpdate() {
|
||||
const logicSection = drawStore.selectedGraphic as LogicSection;
|
||||
if (logicSection) {
|
||||
drawStore
|
||||
.getDrawApp()
|
||||
.updateGraphicAndRecord(logicSection, logicSectionModel);
|
||||
}
|
||||
}
|
||||
|
||||
const logicSectionRelations = computed(() => {
|
||||
const logicSection = drawStore.selectedGraphic as LogicSection;
|
||||
const axleCountingSection = logicSection.queryStore.queryById(
|
||||
logicSection.datas.axleSectionId
|
||||
) as AxleCountingSection;
|
||||
return [axleCountingSection.datas.code];
|
||||
});
|
||||
</script>
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
63
src/drawApp/graphics/LogicSectionInteraction.ts
Normal file
63
src/drawApp/graphics/LogicSectionInteraction.ts
Normal file
@ -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<graphicData.LogicSection>();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
@ -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<StateTrain>();
|
||||
get code(): string {
|
||||
return this.states.trainIndex;
|
||||
}
|
||||
|
||||
get states(): train.TrainInfo {
|
||||
return this.getState<train.TrainInfo>();
|
||||
}
|
||||
|
||||
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<Train> {
|
||||
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<keyof state.TrainMode> = [
|
||||
'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<keyof state.TrainMode> = [
|
||||
'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);
|
||||
|
@ -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>(
|
||||
AxleCounting.Type
|
||||
);
|
||||
const trainWindows = app.queryStore.queryByType<TrainWindow>(
|
||||
TrainWindow.Type
|
||||
const axleCountingSections =
|
||||
app.queryStore.queryByType<AxleCountingSection>(AxleCountingSection.Type);
|
||||
const logicSections = app.queryStore.queryByType<LogicSection>(
|
||||
LogicSection.Type
|
||||
);
|
||||
const sections = app.queryStore.queryByType<Section>(Section.Type);
|
||||
const sectionLinks = app.queryStore.queryByType<SectionLink>(
|
||||
SectionLink.Type
|
||||
);
|
||||
const turnouts = app.queryStore.queryByType<Turnout>(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>(
|
||||
AxleCountingSection.Type
|
||||
);
|
||||
axleCountingSections.forEach((axleCountingSection) => {
|
||||
axleCountingSection.visible = false;
|
||||
});
|
||||
const sectionLinks = app.queryStore.queryByType<SectionLink>(
|
||||
SectionLink.Type
|
||||
);
|
||||
sectionLinks.forEach((sectionLink) => {
|
||||
sectionLink.visible = false;
|
||||
});
|
||||
const logicSections = app.queryStore.queryByType<LogicSection>(
|
||||
LogicSection.Type
|
||||
);
|
||||
logicSections.forEach((logicSection) => {
|
||||
logicSection.visible = false;
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<string, number>,
|
||||
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>(
|
||||
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>(
|
||||
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) => {
|
||||
axleCountings.forEach((axleCounting) => {
|
||||
//计轴关联的道岔
|
||||
const axleCountingRelations =
|
||||
axleCountings[0].relationManage.getRelationsOfGraphicAndOtherType(
|
||||
axleCountings[0],
|
||||
axleCounting.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
axleCounting,
|
||||
Turnout.Type
|
||||
);
|
||||
axleCountingRelations.forEach((relation) => {
|
||||
const refDevice = relation.getOtherGraphic<Section>(axleCountings[0]);
|
||||
fourTurnout;
|
||||
});
|
||||
});
|
||||
|
||||
/* 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 refTurnout = relation.getOtherGraphic<Turnout>(axleCounting);
|
||||
//道岔关联的计轴
|
||||
const turnoutRelations =
|
||||
refTurnout.relationManage.getRelationsOfGraphicAndOtherType(
|
||||
refTurnout,
|
||||
AxleCounting.Type
|
||||
);
|
||||
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
|
||||
);
|
||||
}
|
||||
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)
|
||||
turnoutRelations.forEach((relation) => {
|
||||
const refAxleCounting =
|
||||
relation.getOtherGraphic<AxleCounting>(refTurnout);
|
||||
if (
|
||||
refAxleCounting.id !== axleCountings[0].id &&
|
||||
refAxleCounting.id !== axleCountings[1].id
|
||||
) {
|
||||
this.draw([downAxleCountings[i], downAxleCountings[i + 2]]);
|
||||
i += 2;
|
||||
}
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
function buildAbsorbablePositions(
|
||||
axleCountingSection: AxleCountingSection
|
||||
): AbsorbablePosition[] {
|
||||
const aps: AbsorbablePosition[] = [];
|
||||
const axleCountingSections =
|
||||
axleCountingSection.queryStore.queryByType<AxleCountingSection>(
|
||||
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);
|
||||
fourAxleCounting.push({
|
||||
axleCounting: refAxleCounting,
|
||||
refTurout: refTurnout,
|
||||
});
|
||||
return aps;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
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) {
|
||||
@ -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<AxleCountingSection> {
|
||||
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<Axl
|
||||
g.labelGraphic.cursor = 'pointer';
|
||||
g.labelGraphic.selectable = true;
|
||||
g.labelGraphic.draggable = true;
|
||||
g.on('selected', this.onSelected, this);
|
||||
g.on('_rightclick', this.onContextMenu, this);
|
||||
}
|
||||
unbind(g: AxleCountingSection): void {
|
||||
g.eventMode = 'none';
|
||||
@ -254,13 +358,71 @@ export class AxleCountingSectionInteraction extends GraphicInteractionPlugin<Axl
|
||||
g.labelGraphic.draggable = false;
|
||||
g.labelGraphic.selectable = false;
|
||||
g.labelGraphic.transformSave = false;
|
||||
g.off('selected', this.onSelected, this);
|
||||
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);
|
||||
}
|
||||
onSelected(): void {
|
||||
const AxleCountingSection = this.app
|
||||
.selectedGraphics[0] as AxleCountingSection;
|
||||
this.app.setOptions({
|
||||
absorbablePositions: buildAbsorbablePositions(AxleCountingSection),
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
110
src/graphics/logicSection/LogicSection.ts
Normal file
110
src/graphics/logicSection/LogicSection.ts
Normal file
@ -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<ILogicSectionData>();
|
||||
}
|
||||
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<LogicSection> {
|
||||
constructor(dataTemplate: ILogicSectionData) {
|
||||
super(LogicSection.Type, {
|
||||
dataTemplate,
|
||||
});
|
||||
}
|
||||
new(): LogicSection {
|
||||
const logicSection = new LogicSection();
|
||||
logicSection.loadData(this.datas);
|
||||
return logicSection;
|
||||
}
|
||||
}
|
163
src/graphics/logicSection/LogicSectionDrawAssistant.ts
Normal file
163
src/graphics/logicSection/LogicSectionDrawAssistant.ts
Normal file
@ -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>(
|
||||
LogicSection.Type
|
||||
);
|
||||
// this.app.deleteGraphics(...logicSections);
|
||||
// return;
|
||||
logicSections.forEach((logicSection) => {
|
||||
map.set(`${logicSection.datas.axleSectionId}`, 1);
|
||||
});
|
||||
const axleCountingSections =
|
||||
this.app.queryStore.queryByType<AxleCountingSection>(
|
||||
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<LogicSection> {
|
||||
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;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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,12 +67,7 @@ export class SectionLinkDraw extends GraphicDrawAssistant<
|
||||
data.points = this.points;
|
||||
return true;
|
||||
}
|
||||
oneGenerates() {
|
||||
// localToCanvasPoints
|
||||
const sectionList = this.app.queryStore.queryByType<Section>(Section.Type);
|
||||
const turnoutList = this.app.queryStore.queryByType<Turnout>(Turnout.Type);
|
||||
console.log(sectionList.length, turnoutList.length);
|
||||
sectionList.forEach((section: Section) => {
|
||||
generateBySection(section: Section) {
|
||||
const sectionLink = new SectionLink();
|
||||
sectionLink.loadData(this.graphicTemplate.datas);
|
||||
sectionLink.id = GraphicIdGenerator.next();
|
||||
@ -80,36 +77,138 @@ export class SectionLinkDraw extends GraphicDrawAssistant<
|
||||
});
|
||||
sectionLink.datas.points = points;
|
||||
this.storeGraphic(sectionLink);
|
||||
});
|
||||
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);
|
||||
}
|
||||
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 pointA = [forkP];
|
||||
const pointB = [forkP];
|
||||
const pointC = [forkP];
|
||||
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>(
|
||||
AxleCounting.Type
|
||||
);
|
||||
const turnoutList = this.app.queryStore.queryByType<Turnout>(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<SectionLink>
|
||||
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;
|
||||
// }
|
||||
}
|
||||
|
@ -19,9 +19,9 @@ export enum separatorTypeEnum {
|
||||
}
|
||||
|
||||
export const SeparatorConsts = {
|
||||
height: 15,
|
||||
height: 12,
|
||||
lineWidth: 2,
|
||||
lineColor: '0x617799',
|
||||
lineColor: '0xFFFFFF',
|
||||
circleColor: '0xEF0200',
|
||||
radius: 5,
|
||||
};
|
||||
|
@ -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,22 +185,34 @@ 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;
|
||||
const arrow = this.arrow;
|
||||
arrow.beginFill(aColor, 1);
|
||||
arrow.drawPolygon(arrowPoint);
|
||||
arrow.endFill();
|
||||
if (states.mode?.ipModeTrainStoped) {
|
||||
this.arrow.visible = false;
|
||||
}
|
||||
run() {
|
||||
this.pause.visible = false;
|
||||
} else {
|
||||
this.arrow.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TrainBody extends Container {
|
||||
@ -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;
|
||||
} else if (states.mode?.ipModeTrainTypeManual) {
|
||||
codeA = 'MM';
|
||||
fillBColor = typeColorEnum.manual;
|
||||
} else if (states.mode?.ipModeTrainTypeSpecial) {
|
||||
codeA = '';
|
||||
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) {
|
||||
codeB = '---';
|
||||
} else if (states.mode?.ipModeTrainTypeSpecial) {
|
||||
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<ITrainState>();
|
||||
}
|
||||
|
||||
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);
|
||||
if (this.states.mode?.ipModeTrainHolded) {
|
||||
this.showStatus('扣');
|
||||
} else {
|
||||
this.hideStatus('扣');
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.trainHead.stop();
|
||||
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('警');
|
||||
}
|
||||
run() {
|
||||
this.trainHead.run();
|
||||
}
|
||||
|
||||
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<Train> {
|
||||
@ -394,7 +417,7 @@ export class TrainTemplate extends JlGraphicTemplate<Train> {
|
||||
}
|
||||
new(): Train {
|
||||
const train = new Train();
|
||||
train.loadData(this.datas);
|
||||
train.id = GraphicIdGenerator.next();
|
||||
train.loadState(this.states);
|
||||
return train;
|
||||
}
|
||||
|
@ -37,6 +37,9 @@
|
||||
>
|
||||
<q-item-section>一键生成计轴区段</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable v-close-popup @click="oneClickLogicSection">
|
||||
<q-item-section>一键生成逻辑区段</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
@ -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<SectionLinkDraw>(SectionLink.Type);
|
||||
|
Loading…
Reference in New Issue
Block a user