Section
This commit is contained in:
parent
574bce4b31
commit
a354c9f136
56
src/common/common.ts
Normal file
56
src/common/common.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
export enum DevicePort {
|
||||||
|
A = 0,
|
||||||
|
B = 1,
|
||||||
|
C = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum DeviceType {
|
||||||
|
Section = 0,
|
||||||
|
Turnout = 1,
|
||||||
|
TrainWindow = 2,
|
||||||
|
AxleCounting = 3,
|
||||||
|
SectionLink = 4,
|
||||||
|
Signal = 5,
|
||||||
|
Station = 6,
|
||||||
|
ScreenDoor = 7,
|
||||||
|
SignalFaultAlarm = 8,
|
||||||
|
Breakers = 9,
|
||||||
|
PowerScreen = 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Direction {
|
||||||
|
LEFT = 0,
|
||||||
|
RIGHT = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KilometerSystem {
|
||||||
|
get coordinateSystem(): string;
|
||||||
|
set coordinateSystem(v: string);
|
||||||
|
get kilometer(): number;
|
||||||
|
set kilometer(v: number);
|
||||||
|
get direction(): Direction;
|
||||||
|
set direction(v: Direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRelatedRef {
|
||||||
|
deviceType: DeviceType; //关联的设备类型
|
||||||
|
id: number; //关联的设备ID
|
||||||
|
devicePort: DevicePort; //关联的设备端口
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace IRelatedRef {
|
||||||
|
export function create(
|
||||||
|
type: string,
|
||||||
|
id: number,
|
||||||
|
port: DevicePort,
|
||||||
|
): IRelatedRef {
|
||||||
|
const typeNum = Object.keys(DeviceType).indexOf(type);
|
||||||
|
if (typeNum < 0) throw Error('Invalid device type');
|
||||||
|
typeNum as DeviceType;
|
||||||
|
return {
|
||||||
|
deviceType: typeNum,
|
||||||
|
id,
|
||||||
|
devicePort: port,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
32
src/packages/AxleCounting/AxleCounting.ts
Normal file
32
src/packages/AxleCounting/AxleCounting.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { GraphicData, JlGraphic } from 'jl-graphic';
|
||||||
|
import { IRelatedRef, KilometerSystem } from 'src/common/common';
|
||||||
|
|
||||||
|
enum TypeDetectionPoint {
|
||||||
|
AxleCounting = 0,
|
||||||
|
SectionBoundary = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAxleCountingData extends GraphicData {
|
||||||
|
code: string;
|
||||||
|
kilometerSystem: KilometerSystem;
|
||||||
|
axleCountingRef: IRelatedRef[];
|
||||||
|
type: TypeDetectionPoint;
|
||||||
|
centralizedStations: number[];
|
||||||
|
clone(): IAxleCountingData;
|
||||||
|
copyFrom(data: IAxleCountingData): void;
|
||||||
|
eq(other: IAxleCountingData): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AxleCounting extends JlGraphic {
|
||||||
|
static Type = 'axleCounting';
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(AxleCounting.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
doRepaint(): void {}
|
||||||
|
|
||||||
|
get datas(): IAxleCountingData {
|
||||||
|
return this.getDatas<IAxleCountingData>();
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
import { GraphicData, JlGraphic } from 'jl-graphic'
|
|
||||||
import { IPointData } from 'pixi.js'
|
|
||||||
import { SectionGraphic } from './SectionGraphic'
|
|
||||||
|
|
||||||
export interface ISectionData extends GraphicData {
|
|
||||||
code: string
|
|
||||||
points: IPointData[]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SectionDisplayConfig {
|
|
||||||
lineColor: string;
|
|
||||||
lineWidth: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Section extends JlGraphic {
|
|
||||||
static Type = 'Section'
|
|
||||||
lineGraphic: SectionGraphic
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(Section.Type)
|
|
||||||
this.lineGraphic = new SectionGraphic();
|
|
||||||
// this.transformSave = true;
|
|
||||||
this.addChild(this.lineGraphic);
|
|
||||||
}
|
|
||||||
|
|
||||||
doRepaint(): void {
|
|
||||||
console.log('repaint')
|
|
||||||
}
|
|
||||||
}
|
|
14
src/packages/Section/bjrtss/Section.ts
Normal file
14
src/packages/Section/bjrtss/Section.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Section as SectionBase, SectionDisplayConfig } from "../common/Section";
|
||||||
|
|
||||||
|
const displayConfig: SectionDisplayConfig = {
|
||||||
|
lineColor: '#5578b6',
|
||||||
|
occupiedColor: '#f00',
|
||||||
|
lineWidth: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Section extends SectionBase {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.setDisplayConfig(displayConfig)
|
||||||
|
}
|
||||||
|
}
|
355
src/packages/Section/common/Section.ts
Normal file
355
src/packages/Section/common/Section.ts
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
import {
|
||||||
|
GraphicData,
|
||||||
|
GraphicRelationParam,
|
||||||
|
GraphicState,
|
||||||
|
JlGraphic,
|
||||||
|
JlGraphicTemplate,
|
||||||
|
Vector2,
|
||||||
|
VectorText,
|
||||||
|
convertToBezierParams,
|
||||||
|
distance2,
|
||||||
|
splitLineEvenly,
|
||||||
|
} from 'jl-graphic';
|
||||||
|
import { IPointData } from 'pixi.js';
|
||||||
|
import { SectionGraphic } from './SectionGraphic';
|
||||||
|
import { DevicePort, DeviceType, IRelatedRef } from 'src/common/common';
|
||||||
|
import { Turnout } from 'src/packages/Turnout/Turnout';
|
||||||
|
import { AxleCounting } from 'src/packages/AxleCounting/AxleCounting';
|
||||||
|
|
||||||
|
const tolerance = 0.01;
|
||||||
|
|
||||||
|
export interface ISectionData extends GraphicData {
|
||||||
|
code: string;
|
||||||
|
isCurve: boolean;
|
||||||
|
segmentsCount: number;
|
||||||
|
points: IPointData[];
|
||||||
|
sectionType: SectionType;
|
||||||
|
paRef?: IRelatedRef;
|
||||||
|
pbRef?: IRelatedRef;
|
||||||
|
axleCountings?: number[];
|
||||||
|
centralizedStations?: number[];
|
||||||
|
trackSectionId?: number;
|
||||||
|
clone(): ISectionData;
|
||||||
|
copyFrom(data: ISectionData): void;
|
||||||
|
eq(other: ISectionData): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ISectionState extends GraphicState {
|
||||||
|
id: number;
|
||||||
|
occupied: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SectionType {
|
||||||
|
Physical = 0, //物理区段
|
||||||
|
Logic = 1, //逻辑区段
|
||||||
|
TurnoutPhysical = 2, //道岔物理区段
|
||||||
|
Track = 4, //轨道区段
|
||||||
|
TrackLogic = 5, //轨道逻辑区段
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SectionDisplayConfig {
|
||||||
|
lineColor: string;
|
||||||
|
occupiedColor: string;
|
||||||
|
lineWidth: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultDisplayConfig: SectionDisplayConfig = {
|
||||||
|
lineColor: '#5578b6',
|
||||||
|
occupiedColor: '#f00',
|
||||||
|
lineWidth: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Section extends JlGraphic {
|
||||||
|
static Type = 'Section';
|
||||||
|
lineGraphic: SectionGraphic;
|
||||||
|
labelGraphic: VectorText;
|
||||||
|
displayConfig = defaultDisplayConfig;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(Section.Type);
|
||||||
|
this.lineGraphic = new SectionGraphic();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
setDisplayConfig(config: SectionDisplayConfig) {
|
||||||
|
this.displayConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
getVerticesList(): IPointData[] {
|
||||||
|
if (this.datas.isCurve) {
|
||||||
|
return [
|
||||||
|
this.datas.points[0],
|
||||||
|
...convertToBezierParams(this.datas.points).map((param) => param.p2),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return this.datas.points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getStartPoint() {
|
||||||
|
return this.datas.points[0];
|
||||||
|
}
|
||||||
|
getEndPoint(): IPointData {
|
||||||
|
return this.datas.points[this.datas.points.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
doRepaint(): void {
|
||||||
|
this.lineGraphic.clear();
|
||||||
|
if (this.datas.sectionType === SectionType.TurnoutPhysical) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.lineGraphic.isCurve = this.datas.isCurve;
|
||||||
|
if (this.lineGraphic.isCurve) {
|
||||||
|
this.lineGraphic.segmentsCount = this.datas.segmentsCount;
|
||||||
|
}
|
||||||
|
this.lineGraphic.points = this.datas.points;
|
||||||
|
this.lineGraphic.lineStyle(
|
||||||
|
this.displayConfig.lineWidth,
|
||||||
|
this.states.occupied
|
||||||
|
? this.displayConfig.occupiedColor
|
||||||
|
: this.displayConfig.lineColor,
|
||||||
|
);
|
||||||
|
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 datas(): ISectionData {
|
||||||
|
return this.getDatas<ISectionData>();
|
||||||
|
}
|
||||||
|
get states(): ISectionState {
|
||||||
|
return this.getStates<ISectionState>();
|
||||||
|
}
|
||||||
|
get linePoints(): IPointData[] {
|
||||||
|
return this.datas.points;
|
||||||
|
}
|
||||||
|
set linePoints(points: IPointData[]) {
|
||||||
|
const old = this.datas.clone();
|
||||||
|
old.points = points;
|
||||||
|
this.updateData(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
getConnectElement(port: DevicePort) {
|
||||||
|
const relation = this.relationManage
|
||||||
|
.getRelationsOfGraphic(this)
|
||||||
|
.find(
|
||||||
|
(relation) =>
|
||||||
|
relation.getRelationParam(this).getParam<DevicePort>() === port &&
|
||||||
|
(relation.getOtherGraphic(this) instanceof Section ||
|
||||||
|
relation.getOtherGraphic(this) instanceof Turnout),
|
||||||
|
);
|
||||||
|
if (!relation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
g: relation?.getOtherGraphic(this) as Section | Turnout,
|
||||||
|
port: relation?.getOtherRelationParam(this).getParam<DevicePort>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取拆分逻辑区段数据 */
|
||||||
|
getSplitPoints(count: number): IPointData[][] {
|
||||||
|
if (this.datas.points.length !== 2) {
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildRelation() {
|
||||||
|
this.relationManage.deleteRelationOfGraphicAndOtherType(this, Section.Type);
|
||||||
|
|
||||||
|
if (this.datas.sectionType === SectionType.Physical) {
|
||||||
|
this.queryStore.queryByType<Section>(Section.Type).forEach((section) => {
|
||||||
|
if (section.id === this.id) return;
|
||||||
|
|
||||||
|
let param: DevicePort[] = [];
|
||||||
|
if (
|
||||||
|
distance2(
|
||||||
|
this.localToCanvasPoint(this.getStartPoint()),
|
||||||
|
section.localToCanvasPoint(section.getStartPoint()),
|
||||||
|
) <= tolerance
|
||||||
|
) {
|
||||||
|
param = [DevicePort.A, DevicePort.A];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
distance2(
|
||||||
|
this.localToCanvasPoint(this.getEndPoint()),
|
||||||
|
section.localToCanvasPoint(section.getStartPoint()),
|
||||||
|
) <= tolerance
|
||||||
|
) {
|
||||||
|
param = [DevicePort.B, DevicePort.A];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
distance2(
|
||||||
|
this.localToCanvasPoint(this.getStartPoint()),
|
||||||
|
section.localToCanvasPoint(section.getEndPoint()),
|
||||||
|
) <= tolerance
|
||||||
|
) {
|
||||||
|
param = [DevicePort.A, DevicePort.B];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
distance2(
|
||||||
|
this.localToCanvasPoint(this.getEndPoint()),
|
||||||
|
section.localToCanvasPoint(section.getEndPoint()),
|
||||||
|
) <= tolerance
|
||||||
|
) {
|
||||||
|
param = [DevicePort.B, DevicePort.B];
|
||||||
|
}
|
||||||
|
if (param.length) {
|
||||||
|
this.relationManage.addRelation(
|
||||||
|
new GraphicRelationParam(this, param[0]),
|
||||||
|
new GraphicRelationParam(section, param[1]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveRelations() {
|
||||||
|
const paRelation = this.relationManage
|
||||||
|
.getRelationsOfGraphic(this)
|
||||||
|
.find(
|
||||||
|
(relation) =>
|
||||||
|
relation.getRelationParam(this).param === DevicePort.A &&
|
||||||
|
(relation.getOtherGraphic(this) instanceof Section ||
|
||||||
|
relation.getOtherGraphic(this) instanceof Turnout),
|
||||||
|
);
|
||||||
|
const paDevice = paRelation?.getOtherGraphic<Section | Turnout>(this);
|
||||||
|
if (paDevice) {
|
||||||
|
this.datas.paRef = IRelatedRef.create(
|
||||||
|
paDevice.type,
|
||||||
|
paDevice.id,
|
||||||
|
paRelation!.getOtherRelationParam(this).getParam(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.datas.paRef = undefined;
|
||||||
|
}
|
||||||
|
const pbRelation = this.relationManage
|
||||||
|
.getRelationsOfGraphic(this)
|
||||||
|
.find(
|
||||||
|
(relation) =>
|
||||||
|
relation.getRelationParam(this).param === DevicePort.B &&
|
||||||
|
(relation.getOtherGraphic(this) instanceof Section ||
|
||||||
|
relation.getOtherGraphic(this) instanceof Turnout),
|
||||||
|
);
|
||||||
|
const pbDevice = pbRelation?.getOtherGraphic<Section | Turnout>(this);
|
||||||
|
if (pbDevice) {
|
||||||
|
this.datas.pbRef = IRelatedRef.create(
|
||||||
|
pbDevice.type,
|
||||||
|
pbDevice.id,
|
||||||
|
pbRelation?.getOtherRelationParam(this).param,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.datas.pbRef = undefined;
|
||||||
|
}
|
||||||
|
this.datas.axleCountings = this.relationManage
|
||||||
|
.getRelationsOfGraphicAndOtherType(this, AxleCounting.Type)
|
||||||
|
.map((relation) => relation.getOtherGraphic<AxleCounting>(this).datas.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadRelations() {
|
||||||
|
if (this.datas?.paRef?.id) {
|
||||||
|
this.relationManage.addRelation(
|
||||||
|
new GraphicRelationParam(this, DevicePort.A),
|
||||||
|
new GraphicRelationParam(
|
||||||
|
this.queryStore.queryById(this.datas.paRef.id),
|
||||||
|
DevicePort[this.datas.paRef.devicePort],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this.datas?.pbRef?.id) {
|
||||||
|
this.relationManage.addRelation(
|
||||||
|
new GraphicRelationParam(this, DevicePort.B),
|
||||||
|
new GraphicRelationParam(
|
||||||
|
this.queryStore.queryById(this.datas.pbRef.id),
|
||||||
|
DevicePort[this.datas.pbRef.devicePort],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this.datas.trackSectionId) {
|
||||||
|
this.relationManage.addRelation(
|
||||||
|
this,
|
||||||
|
this.queryStore.queryById<Section>(this.datas.trackSectionId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (this.datas.sectionType === SectionType.TurnoutPhysical) {
|
||||||
|
if (this.datas.axleCountings) {
|
||||||
|
this.datas.axleCountings.forEach((id) => {
|
||||||
|
this.relationManage.addRelation(
|
||||||
|
this,
|
||||||
|
this.queryStore.queryById<AxleCounting>(id),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SectionTemplate extends JlGraphicTemplate<Section> {
|
||||||
|
constructor(dataTemplate: ISectionData, stateTemplate?: ISectionState) {
|
||||||
|
super(Section.Type, {
|
||||||
|
dataTemplate,
|
||||||
|
stateTemplate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
new(): Section {
|
||||||
|
const section = new Section();
|
||||||
|
section.loadData(this.datas);
|
||||||
|
section.loadState(this.states);
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user