wip-道岔

This commit is contained in:
Yuan 2023-06-08 09:38:14 +08:00
parent 2424b8120c
commit 9dd01ac10e
5 changed files with 557 additions and 23 deletions

View File

@ -0,0 +1,75 @@
import { ITrunoutData } from 'src/graphics/turnout/Turnout';
import * as pb_1 from 'google-protobuf';
import { GraphicDataBase } from './GraphicDataBase';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { IPointData } from 'pixi.js';
import { GraphicData } from 'src/jl-graphic';
export class TurnoutData extends GraphicDataBase implements ITrunoutData {
constructor(data?: graphicData.Turnout) {
let turnout;
if (!data) {
turnout = new graphicData.Turnout({
common: GraphicDataBase.defaultCommonInfo(),
});
} else {
turnout = data;
}
super(turnout);
}
get data(): graphicData.Turnout {
return this.getData<graphicData.Turnout>();
}
get code(): string {
return this.data.code;
}
set code(v: string) {
this.data.code = v;
}
get lineWidth(): number {
return this.data.lineWidth;
}
set lineWidth(v: number) {
this.data.lineWidth = v;
}
get lineColor(): string {
return this.data.lineColor;
}
set lineColor(v: string) {
this.data.lineColor = v;
}
get forkPoint(): IPointData {
return this.data.forkPoint;
}
set forkPoint(v: IPointData) {
this.data.forkPoint = new graphicData.Point({ x: v.x, y: v.y });
}
get pointA(): IPointData {
return this.data.pointA;
}
set pointA(v: IPointData) {
this.data.pointA = new graphicData.Point({ x: v.x, y: v.y });
}
get pointB(): IPointData {
return this.data.pointB;
}
set pointB(v: IPointData) {
this.data.pointB = new graphicData.Point({ x: v.x, y: v.y });
}
get pointC(): IPointData {
return this.data.pointC;
}
set pointC(v: IPointData) {
this.data.pointC = new graphicData.Point({ x: v.x, y: v.y });
}
clone(): TurnoutData {
return new TurnoutData(this.data.cloneMessage());
}
copyFrom(data: TurnoutData): void {
pb_1.Message.copyInto(data.data, this.data);
}
eq(other: TurnoutData): boolean {
return pb_1.Message.equals(this.data, other.data);
}
}

View File

@ -29,6 +29,9 @@ import { PlatformData } from './graphics/PlatformInteraction';
import { StationData } from './graphics/StationInteraction';
import { TrainData } from './graphics/TrainInteraction';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { Turnout } from 'src/graphics/turnout/Turnout';
import { TurnoutDraw } from 'src/graphics/turnout/TurnoutDrawAssistant';
import { TurnoutData } from './graphics/TurnoutInteraction';
export function fromStoragePoint(p: graphicData.Point): Point {
return new Point(p.x, p.y);
@ -118,6 +121,9 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
new TrainDraw(app, () => {
return new TrainData();
}),
new TurnoutDraw(app, () => {
return new TurnoutData();
}),
],
});
@ -147,6 +153,15 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
},
})
);
app.addKeyboardListener(
new KeyListener({
value: 'KeyW',
onPress: () => {
console.log(app.interactionPlugin(Turnout.Type));
app.interactionPlugin(Turnout.Type).resume();
},
})
);
app.addKeyboardListener(
new KeyListener({
value: 'KeyR',
@ -159,6 +174,7 @@ export function initDrawApp(dom: HTMLElement): JlDrawApp {
new KeyListener({
value: 'KeyF',
onPress: () => {
console.log(1);
app.interactionPlugin(IscsFan.Type).resume();
},
})
@ -240,6 +256,9 @@ export function saveDrawDatas(app: JlDrawApp) {
} else if (Train.Type === g.type) {
const trainData = (g as Train).saveData();
storage.train.push((trainData as TrainData).data);
} else if (Turnout.Type === g.type) {
const turnoutData = (g as Turnout).saveData();
storage.turnouts.push((turnoutData as TurnoutData).data);
}
});
const base64 = fromUint8Array(storage.serialize());
@ -276,6 +295,9 @@ export function loadDrawDatas(app: GraphicApp) {
storage.train.forEach((train) => {
datas.push(new TrainData(train));
});
storage.turnouts.forEach((turnout) => {
datas.push(new TurnoutData(turnout));
});
app.loadGraphic(datas);
} else {
app.loadGraphic([]);

View File

@ -1,53 +1,120 @@
import { Color, Graphics, IPointData } from 'pixi.js';
import { GraphicData, JlGraphic } from 'src/jl-graphic';
import {
GraphicData,
GraphicState,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'src/jl-graphic';
export interface ITrunoutData extends GraphicData {
get code(): string;
set code(code: string);
get lineWidth(): number;
set lineWidth(code: number);
set lineWidth(width: number);
get lineColor(): string;
set lineColor(code: string);
set lineColor(color: string);
get forkPoint(): IPointData;
set forkPoint(point: IPointData);
get pointA(): IPointData;
set pointA(code: IPointData);
set pointA(point: IPointData);
get pointB(): IPointData;
set pointB(code: IPointData);
set pointB(point: IPointData);
get pointC(): IPointData;
set pointC(code: IPointData);
set pointC(point: IPointData);
clone(): ITrunoutData;
copyFrom(data: ITrunoutData): void;
eq(other: ITrunoutData): boolean;
}
export enum TurnoutPosition {
NORMAL = 0,
REVERSE = 1,
}
export interface ITurnoutState extends GraphicState {
position: TurnoutPosition;
}
export class Turnout extends JlGraphic {
static Type = 'Turnout';
graphics: {
forkPoint: {
AB: Graphics;
AC: Graphics;
};
fork: Graphics;
sections: Graphics;
label: VectorText;
};
constructor() {
super(Turnout.Type);
this.graphics = {
forkPoint: { AB: new Graphics(), AC: new Graphics() },
fork: new Graphics(),
sections: new Graphics(),
label: new VectorText(),
};
this.addChild(this.graphics.fork);
this.addChild(this.graphics.sections);
this.graphics.label.anchor.set(0.5);
this.graphics.label.style.fill = '#0f0';
this.graphics.label.setVectorFontSize(16);
this.addChild(this.graphics.label);
}
get datas(): ITrunoutData {
return this.getDatas<ITrunoutData>();
}
get states(): ITurnoutState {
return this.getStates<ITurnoutState>();
}
doRepaint(): void {
const { pointA, pointB, pointC } = this.datas;
const { pointA, pointB, pointC, forkPoint } = this.datas;
const intersectB = Turnout.getIntersectionPoint(forkPoint, 20, pointB);
const intersectC = Turnout.getIntersectionPoint(forkPoint, 20, pointC);
const forkPoint: IPointData = {
x: pointA.x + (pointB.x - pointA.x),
y: pointA.y + (pointB.y - pointA.y),
};
this.graphics.sections
.clear()
.lineStyle(this.datas.lineWidth, new Color(this.datas.lineColor))
.moveTo(pointA.x, pointA.y)
.lineTo(forkPoint.x, forkPoint.y)
.moveTo(pointB.x, pointB.y)
.lineTo(intersectB.x, intersectB.y)
.moveTo(pointC.x, pointC.y)
.lineTo(intersectC.x, intersectC.y);
// this.lineGraphic.clear();
// this.lineGraphic.lineStyle(this.datas.lineWidth, new Color());
this.graphics.fork
.clear()
.lineStyle(this.datas.lineWidth, new Color(this.datas.lineColor))
.moveTo(forkPoint.x, forkPoint.y)
.lineTo(intersectB.x, intersectB.y);
this.graphics.label.text = this.datas.code;
this.graphics.label.position.set(
this.datas.forkPoint.x + 20,
this.datas.forkPoint.y + 20
);
}
static getIntersectionPoint(
c: IPointData,
r: number,
p: IPointData
): IPointData {
const len = Math.sqrt((c.x - p.x) ** 2 + (c.y - p.y) ** 2);
const scale = r / len;
return { x: c.x + scale * (p.x - c.x), y: c.y + scale * (p.y - c.y) };
}
}
export class TurnoutTemplate extends JlGraphicTemplate<Turnout> {
lineWidth: number;
lineColor: string;
constructor() {
super(Turnout.Type);
this.lineWidth = 5;
this.lineColor = '#5578b6';
}
new() {
return new Turnout();
}
}

View File

@ -0,0 +1,144 @@
import {
DraggablePoint,
GraphicApp,
GraphicDrawAssistant,
GraphicInteractionPlugin,
JlDrawApp,
JlGraphic,
linePoint,
} from 'src/jl-graphic';
import { ITrunoutData, Turnout, TurnoutTemplate } from './Turnout';
import {
DisplayObject,
FederatedMouseEvent,
Graphics,
IHitArea,
IPointData,
Point,
} from 'pixi.js';
import { PolylineEditPlugin } from 'src/jl-graphic/plugins/GraphicEditPlugin';
export class TurnoutDraw extends GraphicDrawAssistant<
TurnoutTemplate,
ITrunoutData
> {
graphic = new Graphics();
point: Point = new Point(0, 0);
constructor(app: JlDrawApp, createData: () => ITrunoutData) {
super(app, new TurnoutTemplate(), createData, Turnout.Type, '道岔Turnout');
this.container.addChild(this.graphic);
}
onLeftDown(e: FederatedMouseEvent): void {
console.log(e);
this.createAndStore(true);
}
prepareData(data: ITrunoutData): boolean {
data.forkPoint = this.point;
data.lineColor = this.graphicTemplate.lineColor;
data.lineWidth = this.graphicTemplate.lineWidth;
data.forkPoint = this.point;
const { pointA, pointB, pointC } = this.getDefaultEndPoint(this.point);
data.pointA = pointA;
data.pointB = pointB;
data.pointC = pointC;
data.code = 'AAA';
return true;
}
getDefaultEndPoint(p: IPointData): {
pointA: IPointData;
pointB: IPointData;
pointC: IPointData;
} {
return {
pointA: new Point(p.x + 50, p.y),
pointB: new Point(p.x - 50, p.y),
pointC: new Point(p.x - 50, p.y - 50),
};
}
redraw(cp: Point): void {
const { pointA, pointB, pointC } = this.getDefaultEndPoint(cp);
const intersectC = Turnout.getIntersectionPoint(cp, 20, pointC);
this.graphic
.clear()
.lineStyle(this.graphicTemplate.lineWidth, this.graphicTemplate.lineColor)
.moveTo(pointA.x, pointA.y)
.lineTo(cp.x, cp.y)
.moveTo(pointB.x, pointB.y)
.lineTo(cp.x, cp.y)
.moveTo(pointC.x, pointC.y)
.lineTo(intersectC.x, intersectC.y);
this.point.set(cp.x, cp.y);
}
}
export class TurnoutHitArea implements IHitArea {
turnout: Turnout;
constructor(turnout: Turnout) {
this.turnout = turnout;
}
contains(x: number, y: number): boolean {
const { pointA, pointB, pointC, forkPoint } = this.turnout.datas;
return (
linePoint(pointA, forkPoint, { x, y }, this.turnout.datas.lineWidth) ||
linePoint(pointB, forkPoint, { x, y }, this.turnout.datas.lineWidth) ||
linePoint(pointC, forkPoint, { x, y }, this.turnout.datas.lineWidth)
);
}
}
// function onEditPointCreate(
// g: ILineGraphic,
// dp: DraggablePoint,
// index: number
// ): void {
// const link = g as Link;
// if (index === 0 || index == link.datas.points.length - 1) {
// // 端点
// dp.on('transformstart', (e: GraphicTransformEvent) => {
// if (e.isShift()) {
// link.getGraphicApp().setOptions({
// absorbablePositions: buildAbsorbablePositions(link),
// });
// }
// });
// }
// }
export class TurnoutPointsEditPlugin extends GraphicInteractionPlugin<Turnout> {
static Name = 'TurnoutPointsDrag';
constructor(app: GraphicApp) {
super(TurnoutPointsEditPlugin.Name, app);
}
bind(g: Turnout): void {
g.graphics.sections.eventMode = 'static';
g.graphics.sections.cursor = 'pointer';
g.graphics.fork.eventMode = 'static';
g.graphics.fork.cursor = 'pointer';
g.hitArea = new TurnoutHitArea(g);
g.on('selected', this.onSelected, this);
}
unbind(g: Turnout): void {
g.off('selected', this.onSelected, this);
}
onSelected(g: DisplayObject) {
console.log(g);
// const turnout = g as Turnout;
// let editPlugin = turnout.getAssistantAppend<PolylineEditPlugin>(
// PolylineEditPlugin.Name
// );
// if (!editPlugin) {
// // editPlugin = new PolylineEditPlugin(turnout, { onEditPointCreate });
// // turnout.addAssistantAppend(editPlugin);
// }
}
filter(...grahpics: JlGraphic[]): Turnout[] | undefined {
return grahpics.filter((g) => g.type == Turnout.Type) as Turnout[];
}
}

View File

@ -15,9 +15,10 @@ export namespace graphicData {
stations?: Station[];
Rects?: Rect[];
train?: Train[];
turnouts?: Turnout[];
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6, 7], this.#one_of_decls);
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6, 7, 8], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("canvas" in data && data.canvas != undefined) {
this.canvas = data.canvas;
@ -40,6 +41,9 @@ export namespace graphicData {
if ("train" in data && data.train != undefined) {
this.train = data.train;
}
if ("turnouts" in data && data.turnouts != undefined) {
this.turnouts = data.turnouts;
}
}
}
get canvas() {
@ -87,6 +91,12 @@ export namespace graphicData {
set train(value: Train[]) {
pb_1.Message.setRepeatedWrapperField(this, 7, value);
}
get turnouts() {
return pb_1.Message.getRepeatedWrapperField(this, Turnout, 8) as Turnout[];
}
set turnouts(value: Turnout[]) {
pb_1.Message.setRepeatedWrapperField(this, 8, value);
}
static fromObject(data: {
canvas?: ReturnType<typeof Canvas.prototype.toObject>;
links?: ReturnType<typeof Link.prototype.toObject>[];
@ -95,6 +105,7 @@ export namespace graphicData {
stations?: ReturnType<typeof Station.prototype.toObject>[];
Rects?: ReturnType<typeof Rect.prototype.toObject>[];
train?: ReturnType<typeof Train.prototype.toObject>[];
turnouts?: ReturnType<typeof Turnout.prototype.toObject>[];
}): RtssGraphicStorage {
const message = new RtssGraphicStorage({});
if (data.canvas != null) {
@ -118,6 +129,9 @@ export namespace graphicData {
if (data.train != null) {
message.train = data.train.map(item => Train.fromObject(item));
}
if (data.turnouts != null) {
message.turnouts = data.turnouts.map(item => Turnout.fromObject(item));
}
return message;
}
toObject() {
@ -129,6 +143,7 @@ export namespace graphicData {
stations?: ReturnType<typeof Station.prototype.toObject>[];
Rects?: ReturnType<typeof Rect.prototype.toObject>[];
train?: ReturnType<typeof Train.prototype.toObject>[];
turnouts?: ReturnType<typeof Turnout.prototype.toObject>[];
} = {};
if (this.canvas != null) {
data.canvas = this.canvas.toObject();
@ -151,6 +166,9 @@ export namespace graphicData {
if (this.train != null) {
data.train = this.train.map((item: Train) => item.toObject());
}
if (this.turnouts != null) {
data.turnouts = this.turnouts.map((item: Turnout) => item.toObject());
}
return data;
}
serialize(): Uint8Array;
@ -171,6 +189,8 @@ export namespace graphicData {
writer.writeRepeatedMessage(6, this.Rects, (item: Rect) => item.serialize(writer));
if (this.train.length)
writer.writeRepeatedMessage(7, this.train, (item: Train) => item.serialize(writer));
if (this.turnouts.length)
writer.writeRepeatedMessage(8, this.turnouts, (item: Turnout) => item.serialize(writer));
if (!w)
return writer.getResultBuffer();
}
@ -201,6 +221,9 @@ export namespace graphicData {
case 7:
reader.readMessage(message.train, () => pb_1.Message.addToRepeatedWrapperField(message, 7, Train.deserialize(reader), Train));
break;
case 8:
reader.readMessage(message.turnouts, () => pb_1.Message.addToRepeatedWrapperField(message, 8, Turnout.deserialize(reader), Turnout));
break;
default: reader.skipField();
}
}
@ -2268,23 +2291,202 @@ export namespace graphicData {
}
export class Turnout extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {}) {
constructor(data?: any[] | {
common?: CommonInfo;
code?: string;
lineColor?: string;
lineWidth?: number;
forkPoint?: Point;
pointA?: Point;
pointB?: Point;
pointC?: Point;
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") { }
if (!Array.isArray(data) && typeof data == "object") {
if ("common" in data && data.common != undefined) {
this.common = data.common;
}
if ("code" in data && data.code != undefined) {
this.code = data.code;
}
if ("lineColor" in data && data.lineColor != undefined) {
this.lineColor = data.lineColor;
}
if ("lineWidth" in data && data.lineWidth != undefined) {
this.lineWidth = data.lineWidth;
}
if ("forkPoint" in data && data.forkPoint != undefined) {
this.forkPoint = data.forkPoint;
}
if ("pointA" in data && data.pointA != undefined) {
this.pointA = data.pointA;
}
if ("pointB" in data && data.pointB != undefined) {
this.pointB = data.pointB;
}
if ("pointC" in data && data.pointC != undefined) {
this.pointC = data.pointC;
}
}
}
static fromObject(data: {}): Turnout {
get common() {
return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo;
}
set common(value: CommonInfo) {
pb_1.Message.setWrapperField(this, 1, value);
}
get has_common() {
return pb_1.Message.getField(this, 1) != null;
}
get code() {
return pb_1.Message.getFieldWithDefault(this, 2, "") as string;
}
set code(value: string) {
pb_1.Message.setField(this, 2, value);
}
get lineColor() {
return pb_1.Message.getFieldWithDefault(this, 3, "") as string;
}
set lineColor(value: string) {
pb_1.Message.setField(this, 3, value);
}
get lineWidth() {
return pb_1.Message.getFieldWithDefault(this, 4, 0) as number;
}
set lineWidth(value: number) {
pb_1.Message.setField(this, 4, value);
}
get forkPoint() {
return pb_1.Message.getWrapperField(this, Point, 5) as Point;
}
set forkPoint(value: Point) {
pb_1.Message.setWrapperField(this, 5, value);
}
get has_forkPoint() {
return pb_1.Message.getField(this, 5) != null;
}
get pointA() {
return pb_1.Message.getWrapperField(this, Point, 6) as Point;
}
set pointA(value: Point) {
pb_1.Message.setWrapperField(this, 6, value);
}
get has_pointA() {
return pb_1.Message.getField(this, 6) != null;
}
get pointB() {
return pb_1.Message.getWrapperField(this, Point, 7) as Point;
}
set pointB(value: Point) {
pb_1.Message.setWrapperField(this, 7, value);
}
get has_pointB() {
return pb_1.Message.getField(this, 7) != null;
}
get pointC() {
return pb_1.Message.getWrapperField(this, Point, 8) as Point;
}
set pointC(value: Point) {
pb_1.Message.setWrapperField(this, 8, value);
}
get has_pointC() {
return pb_1.Message.getField(this, 8) != null;
}
static fromObject(data: {
common?: ReturnType<typeof CommonInfo.prototype.toObject>;
code?: string;
lineColor?: string;
lineWidth?: number;
forkPoint?: ReturnType<typeof Point.prototype.toObject>;
pointA?: ReturnType<typeof Point.prototype.toObject>;
pointB?: ReturnType<typeof Point.prototype.toObject>;
pointC?: ReturnType<typeof Point.prototype.toObject>;
}): Turnout {
const message = new Turnout({});
if (data.common != null) {
message.common = CommonInfo.fromObject(data.common);
}
if (data.code != null) {
message.code = data.code;
}
if (data.lineColor != null) {
message.lineColor = data.lineColor;
}
if (data.lineWidth != null) {
message.lineWidth = data.lineWidth;
}
if (data.forkPoint != null) {
message.forkPoint = Point.fromObject(data.forkPoint);
}
if (data.pointA != null) {
message.pointA = Point.fromObject(data.pointA);
}
if (data.pointB != null) {
message.pointB = Point.fromObject(data.pointB);
}
if (data.pointC != null) {
message.pointC = Point.fromObject(data.pointC);
}
return message;
}
toObject() {
const data: {} = {};
const data: {
common?: ReturnType<typeof CommonInfo.prototype.toObject>;
code?: string;
lineColor?: string;
lineWidth?: number;
forkPoint?: ReturnType<typeof Point.prototype.toObject>;
pointA?: ReturnType<typeof Point.prototype.toObject>;
pointB?: ReturnType<typeof Point.prototype.toObject>;
pointC?: ReturnType<typeof Point.prototype.toObject>;
} = {};
if (this.common != null) {
data.common = this.common.toObject();
}
if (this.code != null) {
data.code = this.code;
}
if (this.lineColor != null) {
data.lineColor = this.lineColor;
}
if (this.lineWidth != null) {
data.lineWidth = this.lineWidth;
}
if (this.forkPoint != null) {
data.forkPoint = this.forkPoint.toObject();
}
if (this.pointA != null) {
data.pointA = this.pointA.toObject();
}
if (this.pointB != null) {
data.pointB = this.pointB.toObject();
}
if (this.pointC != null) {
data.pointC = this.pointC.toObject();
}
return data;
}
serialize(): Uint8Array;
serialize(w: pb_1.BinaryWriter): void;
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
const writer = w || new pb_1.BinaryWriter();
if (this.has_common)
writer.writeMessage(1, this.common, () => this.common.serialize(writer));
if (this.code.length)
writer.writeString(2, this.code);
if (this.lineColor.length)
writer.writeString(3, this.lineColor);
if (this.lineWidth != 0)
writer.writeInt32(4, this.lineWidth);
if (this.has_forkPoint)
writer.writeMessage(5, this.forkPoint, () => this.forkPoint.serialize(writer));
if (this.has_pointA)
writer.writeMessage(6, this.pointA, () => this.pointA.serialize(writer));
if (this.has_pointB)
writer.writeMessage(7, this.pointB, () => this.pointB.serialize(writer));
if (this.has_pointC)
writer.writeMessage(8, this.pointC, () => this.pointC.serialize(writer));
if (!w)
return writer.getResultBuffer();
}
@ -2294,6 +2496,30 @@ export namespace graphicData {
if (reader.isEndGroup())
break;
switch (reader.getFieldNumber()) {
case 1:
reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader));
break;
case 2:
message.code = reader.readString();
break;
case 3:
message.lineColor = reader.readString();
break;
case 4:
message.lineWidth = reader.readInt32();
break;
case 5:
reader.readMessage(message.forkPoint, () => message.forkPoint = Point.deserialize(reader));
break;
case 6:
reader.readMessage(message.pointA, () => message.pointA = Point.deserialize(reader));
break;
case 7:
reader.readMessage(message.pointB, () => message.pointB = Point.deserialize(reader));
break;
case 8:
reader.readMessage(message.pointC, () => message.pointC = Point.deserialize(reader));
break;
default: reader.skipField();
}
}