车站站台计轴

This commit is contained in:
joylink_zhaoerwei 2024-01-05 17:42:53 +08:00
parent 99baef2afd
commit 0b8055bb73
9 changed files with 54 additions and 630 deletions

View File

@ -23,7 +23,7 @@
"echarts": "^5.4.3",
"google-protobuf": "^3.21.2",
"jl-graphic": "git+https://git.code.tencent.com/jl-framework/graphic-pixi.git#v0.1.3",
"rt-graphic-component": "git+https://git.code.tencent.com/jl-framework/rt-graphic-component.git#v0.0.10",
"rt-graphic-component": "git+https://git.code.tencent.com/jl-framework/rt-graphic-component.git#v0.0.12",
"js-base64": "^3.7.5",
"pinia": "^2.0.11",
"quasar": "^2.6.0",

View File

@ -20,9 +20,11 @@ import { ConcentrationDividingLineDraw } from 'src/graphics/concentrationDividin
import { Polygon, PolygonTemplate } from 'src/graphics/polygon/Polygon';
import { PolygonData } from './graphics/PolygonInteraction';
import { PolygonDraw } from 'src/graphics/polygon/PolygonDrawAssistant';
import { Platform, PlatformTemplate } from 'src/graphics/platform/Platform';
import { CategoryType as StyleType } from 'rt-graphic-component/components/packages/Platform/PlatformConfig';
import { Platform } from 'src/graphics/platform/Platform';
import { PlatformData, PlatformState } from './graphics/PlatformInteraction';
import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant';
import { PlatformTemplate } from 'rt-graphic-component/components/packages/Platform/PlatformTemplate';
import { PlatformDraw } from 'rt-graphic-component/components/packages/Platform/PlatformDrawAssistant';
import {
ScreenDoor,
ScreenDoorTemplate,
@ -32,8 +34,9 @@ import {
ScreenDoorState,
} from './graphics/ScreenDoorInteraction';
import { ScreenDoorDraw } from 'src/graphics/screenDoor/ScreenDoorDrawAssistant';
import { Station, StationTemplate } from 'src/graphics/station/Station';
import { StationDraw } from 'src/graphics/station/StationDrawAssistant';
import { Station } from 'src/graphics/station/Station';
import { StationTemplate } from 'rt-graphic-component/components/packages/Station/StationTemplate';
import { StationDraw } from 'rt-graphic-component/components/packages/Station/StationDrawAssistant';
import { StationData, StationState } from './graphics/StationInteraction';
import {
OneClickGenerateDraw,
@ -157,7 +160,12 @@ export const DefaultCanvasMenu = new ContextMenu({
export function initCommonDrawApp(app: IDrawApp) {
new PlatformDraw(
app,
new PlatformTemplate(new PlatformData(), new PlatformState())
new PlatformTemplate(
new PlatformData(),
new PlatformState(),
StyleType.BeiJing
),
'svguse:../../drawIcon.svg#icon-platform'
);
new ScreenDoorDraw(
app,
@ -165,7 +173,12 @@ export function initCommonDrawApp(app: IDrawApp) {
);
new StationDraw(
app,
new StationTemplate(new StationData(), new StationState())
new StationTemplate(
new StationData(),
new StationState(),
StyleType.BeiJing
),
'svguse:../../drawIcon.svg#icon-station'
);
// new SignalDraw(app, new SignalTemplate(new SignalData(), new SignalState()));
new SectionDraw(

View File

@ -27,7 +27,9 @@ import {
PlatformOperateInteraction,
PlatformState,
} from './graphics/PlatformInteraction';
import { PlatformTemplate, Platform } from 'src/graphics/platform/Platform';
import { CategoryType as StyleType } from 'rt-graphic-component/components/packages/Platform/PlatformConfig';
import { Platform } from 'src/graphics/platform/Platform';
import { PlatformTemplate } from 'rt-graphic-component/components/packages/Platform/PlatformTemplate';
import {
ScreenDoorData,
ScreenDoorState,
@ -42,7 +44,8 @@ import {
StationOperateInteraction,
StationState,
} from './graphics/StationInteraction';
import { Station, StationTemplate } from 'src/graphics/station/Station';
import { Station } from 'src/graphics/station/Station';
import { StationTemplate } from 'rt-graphic-component/components/packages/Station/StationTemplate';
import {
TurnoutData,
TurnoutOperationPlugin,
@ -233,9 +236,17 @@ export function initLineScene(lineApp: IGraphicApp, sceneName: string) {
const graphicTemplate = [
new TrainTemplate(new TrainState()),
new SignalTemplate(new SignalData(), new SignalState()),
new PlatformTemplate(new PlatformData(), new PlatformState()),
new PlatformTemplate(
new PlatformData(),
new PlatformState(),
StyleType.BeiJing
),
new ScreenDoorTemplate(new ScreenDoorData(), new ScreenDoorState()),
new StationTemplate(new StationData(), new StationState()),
new StationTemplate(
new StationData(),
new StationState(),
StyleType.BeiJing
),
new TurnoutTemplate(new TurnoutData(), new TurnoutStates()),
new SectionTemplate(new SectionData(), new SectionStates()),
new AxleCountingTemplate(new AxleCountingData()),

View File

@ -1,133 +1,9 @@
import { Color, Container, Graphics } from 'pixi.js';
import {
GraphicData,
GraphicRelationParam,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'jl-graphic';
import { IRelatedRefData, protoPort2Data } from '../CommonGraphics';
import { KilometerSystem } from '../signal/Signal';
AxleCounting,
IAxleCountingData,
AxleCountingTemplate,
AxleCountingConsts,
} from 'rt-graphic-component/components/packages/AxleCounting/AxleCounting';
enum TypeDetectionPoint {
AxleCounting = 0,
SectionBoundary = 1,
}
export interface IAxleCountingData extends GraphicData {
get code(): string; // 编号
set code(v: string);
get kilometerSystem(): KilometerSystem;
set kilometerSystem(v: KilometerSystem);
get axleCountingRef(): IRelatedRefData[]; //关联的设备
set axleCountingRef(ref: IRelatedRefData[]);
get type(): TypeDetectionPoint; // 计轴、区段边界
set type(v: TypeDetectionPoint);
get centralizedStations(): number[];
set centralizedStations(v: number[]);
clone(): IAxleCountingData;
copyFrom(data: IAxleCountingData): void;
eq(other: IAxleCountingData): boolean;
}
export const AxleCountingConsts = {
radius: 6,
borderWidth: 1,
circleColorBlue: '0x08F80D',
circleColorRed: '0xff0000',
codeFontSize: 22,
codeOffsetY: 30,
kilometerCodeColor: '0xFFFFFF',
kilometerCodeFontSize: 14,
kilometerCodeOffsetY: 95,
offsetSection: 50,
};
class TwoCircleGraphic extends Container {
circleA: Graphics = new Graphics();
circleB: Graphics = new Graphics();
line: Graphics = new Graphics();
constructor() {
super();
this.addChild(this.circleA);
this.addChild(this.circleB);
this.addChild(this.line);
}
draw(data: IAxleCountingData): void {
this.drawCircle(this.circleA, data);
this.drawCircle(this.circleB, data);
this.circleA.position.set(-12, 0);
this.circleB.position.set(12, 0);
this.line.clear();
let color = AxleCountingConsts.circleColorBlue;
if (data.type == 1) {
color = AxleCountingConsts.circleColorRed;
}
this.line.lineStyle(1, new Color(color));
this.line.moveTo(-24, 0);
this.line.lineTo(24, 0);
}
drawCircle(circle: Graphics, data: IAxleCountingData): void {
circle.clear();
let color = AxleCountingConsts.circleColorBlue;
if (data.type == 1) {
color = AxleCountingConsts.circleColorRed;
}
circle.lineStyle(AxleCountingConsts.borderWidth, new Color(color));
circle.beginFill(color, 1);
circle.drawCircle(0, 0, AxleCountingConsts.radius);
circle.endFill;
}
clear(): void {
this.circleA.clear();
this.circleB.clear();
}
}
export class AxleCounting extends JlGraphic {
static Type = 'AxleCounting';
twoCircle: TwoCircleGraphic = new TwoCircleGraphic();
kilometerGraph: VectorText = new VectorText(''); //公里标
direction: number;
constructor(direction: number) {
super(AxleCounting.Type);
this.addChild(this.twoCircle);
this.addChild(this.kilometerGraph);
this.kilometerGraph.name = 'kilometer';
this.direction = direction;
}
get datas(): IAxleCountingData {
return this.getDatas<IAxleCountingData>();
}
doRepaint(): void {
this.twoCircle.draw(this.datas);
}
buildRelation(): void {
this.loadRelations();
}
loadRelations(): void {
if (this.datas.axleCountingRef.length) {
this.datas.axleCountingRef.forEach((device) => {
this.relationManage.addRelation(
new GraphicRelationParam(this, 'A'),
new GraphicRelationParam(
this.queryStore.queryById(device.id),
protoPort2Data(device.devicePort)
)
);
});
}
}
}
export class AxleCountingTemplate extends JlGraphicTemplate<AxleCounting> {
constructor(dataTemplate: IAxleCountingData) {
super(AxleCounting.Type, {
dataTemplate,
});
}
new(): AxleCounting {
const axleCounting = new AxleCounting(1);
axleCounting.loadData(this.datas);
return axleCounting;
}
}
export { AxleCounting, AxleCountingTemplate, AxleCountingConsts };
export type { IAxleCountingData };

View File

@ -175,7 +175,8 @@ export class AxleCountingDraw extends GraphicDrawAssistant<
});
axleCountingRefs.forEach((axleCountingRef) => {
map.set(
`${axleCountingRef.id}-${graphicData.RelatedRef.DevicePort[axleCountingRef.devicePort]
`${axleCountingRef.id}-${
graphicData.RelatedRef.DevicePort[axleCountingRef.devicePort]
}`,
1
);
@ -379,21 +380,12 @@ export class AxleCountingInteraction extends GraphicInteractionPlugin<AxleCounti
g.cursor = 'pointer';
g.scalable = true;
g.rotatable = true;
g.kilometerGraph.eventMode = 'static';
g.kilometerGraph.cursor = 'pointer';
g.kilometerGraph.draggable = true;
g.kilometerGraph.selectable = true;
g.kilometerGraph.transformSave = true;
g.on('selected', this.onSelected, this);
}
unbind(g: AxleCounting): void {
g.eventMode = 'none';
g.scalable = false;
g.rotatable = false;
g.kilometerGraph.eventMode = 'none';
g.kilometerGraph.draggable = false;
g.kilometerGraph.selectable = false;
g.kilometerGraph.transformSave = false;
g.off('selected', this.onSelected, this);
}
onSelected(): void {

View File

@ -1,166 +1,6 @@
import { Color, Container, Graphics, Rectangle } from 'pixi.js';
import {
GraphicData,
GraphicState,
JlGraphic,
JlGraphicTemplate,
distance2,
getRectangleCenter,
} from 'jl-graphic';
import { Station } from '../station/Station';
import { Section } from '../section/Section';
import { state } from 'src/protos/device_state';
import { graphicData } from 'src/protos/stationLayoutGraphics';
import { XiAnPlatform as Platform } from 'rt-graphic-component/components/packages/Platform/XiAnPlatform';
import { IPlatformData } from 'rt-graphic-component/components/packages/Platform/PlatformConfig';
import { IXiAnPlatformState as IPlatformState } from 'rt-graphic-component/components/packages/Platform/XiAnPlatform';
export interface IPlatformData extends GraphicData {
get code(): string; // 编号
set code(v: string);
get refStation(): number; // 关联的车站
set refStation(v: number);
get refSection(): number; // 关联的物理区段
set refSection(v: number);
get refEsbRelayCode(): string; // 关联的紧急停车继电器的编号
set refEsbRelayCode(v: string);
get type(): graphicData.Platform.TypeOfPlatform; //站台上下行
set type(v: graphicData.Platform.TypeOfPlatform);
clone(): IPlatformData;
copyFrom(data: IPlatformData): void;
eq(other: IPlatformData): boolean;
}
export interface IPlatformState extends GraphicState {
id?: number;
empj?: boolean;
spksState?: state.ReplyState[];
mkxJState?: state.MkxJState;
}
const platformConsts = {
width: 90,
height: 20,
lineWidth: 3,
white: '0xffffff', //站台颜色
};
//子元素--矩形
export class rectGraphic extends Container {
static Type = 'RectPlatForm';
rectGraphic: Graphics;
constructor() {
super();
this.rectGraphic = new Graphics();
this.addChild(this.rectGraphic);
}
draw(state: IPlatformState): void {
const rectGraphic = this.rectGraphic;
const fillColor = platformConsts.white;
rectGraphic
.clear()
.lineStyle(platformConsts.lineWidth, new Color(fillColor))
.beginFill(fillColor, 1)
.drawRect(0, 0, platformConsts.width, platformConsts.height).endFill;
rectGraphic.pivot = getRectangleCenter(
new Rectangle(0, 0, platformConsts.width, platformConsts.height)
);
}
clear(): void {
this.rectGraphic.clear();
}
}
export class Platform extends JlGraphic {
static Type = 'Platform';
rectGraphic: rectGraphic = new rectGraphic();
constructor() {
super(Platform.Type);
this.addChild(this.rectGraphic);
}
get datas(): IPlatformData {
return this.getDatas<IPlatformData>();
}
get states(): IPlatformState {
return this.getStates<IPlatformState>();
}
doRepaint(): void {
this.rectGraphic.draw(this.states);
}
buildRelation() {
const stationas = this.queryStore.queryByType<Station>(Station.Type);
for (let i = 0; i < stationas.length; i++) {
const sP = stationas[i].localBoundsToCanvasPoints();
if (this.x > sP[0].x && this.x < sP[1].x) {
this.relationManage.addRelation(this, stationas[i]);
break;
}
}
const sections = this.queryStore.queryByType<Section>(Section.Type);
const minDistanceRefSections: Section[] = [];
sections.forEach((section) => {
const sP = section.localBoundsToCanvasPoints();
if (this.x > sP[0].x && this.x < sP[1].x) {
minDistanceRefSections.push(section);
}
});
if (minDistanceRefSections) {
const refSection = minDistanceRefSections.reduce((prev, cur) => {
return distance2(
prev.localToCanvasPoint(getRectangleCenter(prev.getLocalBounds())),
this.position
) >
distance2(
cur.localToCanvasPoint(getRectangleCenter(cur.getLocalBounds())),
this.position
)
? cur
: prev;
});
this.relationManage.deleteRelationOfGraphicAndOtherType(
this,
Section.Type
);
this.relationManage.addRelation(this, refSection);
}
}
saveRelations() {
const refStation = this.relationManage
.getRelationsOfGraphicAndOtherType(this, Station.Type)
.map((relation) => relation.getOtherGraphic<Station>(this).datas.id);
if (refStation.length) {
this.datas.refStation = refStation[0];
}
const refSection = this.relationManage
.getRelationsOfGraphicAndOtherType(this, Section.Type)
.map((relation) => relation.getOtherGraphic<Section>(this).datas.id);
if (refSection.length) {
this.datas.refSection = refSection[0];
}
}
loadRelations() {
if (this.datas.refStation) {
this.relationManage.addRelation(
this,
this.queryStore.queryById<Platform>(this.datas.refStation)
);
}
if (this.datas.refSection) {
this.relationManage.addRelation(
this,
this.queryStore.queryById<Platform>(this.datas.refSection)
);
}
}
}
export class PlatformTemplate extends JlGraphicTemplate<Platform> {
constructor(dataTemplate: IPlatformData, stateTemplate: IPlatformState) {
super(Platform.Type, {
dataTemplate,
stateTemplate,
});
}
new(): Platform {
const platform = new Platform();
platform.loadData(this.datas);
platform.loadState(this.states);
return platform;
}
}
export { Platform };
export type { IPlatformState, IPlatformData };

View File

@ -1,103 +0,0 @@
import { FederatedPointerEvent, Point } from 'pixi.js';
import {
AbsorbableLine,
AbsorbablePosition,
GraphicDrawAssistant,
GraphicInteractionPlugin,
IDrawApp,
JlGraphic,
} from 'jl-graphic';
import { IPlatformData, Platform, PlatformTemplate } from './Platform';
export interface IPlatformDrawOptions {
newData: () => IPlatformData;
}
export class PlatformDraw extends GraphicDrawAssistant<
PlatformTemplate,
IPlatformData
> {
platformGraphic: Platform;
constructor(app: IDrawApp, template: PlatformTemplate) {
super(
app,
template,
'svguse:../../drawIcon.svg#icon-platform',
'站台Platform'
);
this.platformGraphic = this.graphicTemplate.new();
this.container.addChild(this.platformGraphic);
platformInteraction.init(app);
}
bind(): void {
super.bind();
this.platformGraphic.loadData(this.graphicTemplate.datas);
this.platformGraphic.doRepaint();
}
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: IPlatformData): boolean {
data.transform = this.container.saveTransform();
return true;
}
}
function buildAbsorbablePositions(platform: Platform): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const platforms = platform.queryStore.queryByType<Platform>(Platform.Type);
const { width, height } = platform.getGraphicApp().canvas;
platforms.forEach((other) => {
if (other.id == platform.id) {
return;
}
const ps = other.datas.transform.position;
const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y });
const ys = new AbsorbableLine({ x: ps.x, y: 0 }, { x: ps.x, y: height });
aps.push(xs, ys);
});
return aps;
}
export class platformInteraction extends GraphicInteractionPlugin<Platform> {
static Name = 'platform_transform';
constructor(app: IDrawApp) {
super(platformInteraction.Name, app);
}
static init(app: IDrawApp) {
return new platformInteraction(app);
}
filter(...grahpics: JlGraphic[]): Platform[] | undefined {
return grahpics
.filter((g) => g.type === Platform.Type)
.map((g) => g as Platform);
}
bind(g: Platform): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.scalable = true;
g.rotatable = true;
g.on('selected', this.onSelected, this);
}
unbind(g: Platform): void {
g.eventMode = 'none';
g.scalable = false;
g.rotatable = false;
g.off('selected', this.onSelected, this);
}
onSelected(): void {
const platform = this.app.selectedGraphics[0] as Platform;
this.app.setOptions({
absorbablePositions: buildAbsorbablePositions(platform),
});
}
}

View File

@ -1,109 +1,6 @@
import {
GraphicData,
GraphicState,
JlGraphic,
JlGraphicTemplate,
VectorText,
} from 'jl-graphic';
import { KilometerSystem } from '../signal/Signal';
import { Platform } from '../platform/Platform';
import { BeiJingStation as Station } from 'rt-graphic-component/components/packages/Station/BeiJingStation';
import { IStationData } from 'rt-graphic-component/components/packages/Station/StationConfig';
import { IBeiJingStationState as IStationState } from 'rt-graphic-component/components/packages/Station/BeiJingStation';
export interface IStationData extends GraphicData {
get code(): string; // 车站站名
set code(v: string);
get stationName(): string; // 车站名
set stationName(v: string);
get kilometerSystem(): KilometerSystem;
set kilometerSystem(v: KilometerSystem);
get concentrationStations(): boolean; //是否集中站
set concentrationStations(v: boolean);
get refIbpMapCode(): string;
set refIbpMapCode(v: string);
get depots(): boolean; //是否车辆段
set depots(v: boolean);
get manageStations(): number[]; //集中站管理的车站
set manageStations(v: number[]);
clone(): IStationData;
copyFrom(data: IStationData): void;
eq(other: IStationData): boolean;
}
export interface IStationState extends GraphicState {
id: number;
}
const stationConsts = {
codeColor: '0xF48815',
codeFontSize: 22,
kilometerCodeColor: '0xFFFFFF',
kilometerCodeFontSize: 8,
kilometerCodeOffsetY: -25,
};
export class Station extends JlGraphic {
static Type = 'station';
codeGraph: VectorText = new VectorText(''); //车站站名
kilometerGraph: VectorText = new VectorText(''); //公里标
constructor() {
super(Station.Type);
this.addChild(this.codeGraph);
this.addChild(this.kilometerGraph);
}
get datas(): IStationData {
return this.getDatas<IStationData>();
}
get states(): IStationState {
return this.getStates<IStationState>();
}
doRepaint(): void {
const codeGraph = this.codeGraph;
const kilometerGraph = this.kilometerGraph;
codeGraph.text = this.datas?.code || '车站Station';
codeGraph.style.fill = stationConsts.codeColor;
codeGraph.setVectorFontSize(stationConsts.codeFontSize);
codeGraph.anchor.set(0.5);
const kilometerCode = this.datas.kilometerSystem?.kilometer || 12345678;
if (Math.floor(kilometerCode * 1000).toString().length > 3) {
const kiloBit = Math.floor(Number(kilometerCode) / 1000000).toString();
kilometerGraph.text =
'K' +
kiloBit +
'+' +
(
Number(kilometerCode.toString().substring(kiloBit.length)) / 1000
).toFixed(3);
} else {
kilometerGraph.text = (kilometerCode * 1000).toFixed(3);
}
kilometerGraph.style.fill = stationConsts.kilometerCodeColor;
kilometerGraph.setVectorFontSize(stationConsts.kilometerCodeFontSize);
kilometerGraph.anchor.set(0.5);
kilometerGraph.position.set(0, stationConsts.kilometerCodeOffsetY);
}
getPlatforms(): Platform[] {
const relations = this.relationManage.getRelationsOfGraphicAndOtherType(
this,
Platform.Type
);
return relations.map((r) => r.getOtherGraphic(this));
}
}
export class StationTemplate extends JlGraphicTemplate<Station> {
hasControl: boolean;
constructor(dataTemplate: IStationData, stateTemplate: IStationState) {
super(Station.Type, {
dataTemplate,
stateTemplate,
});
this.hasControl = true;
}
new(): Station {
const station = new Station();
station.loadData(this.datas);
station.loadState(this.states);
return station;
}
}
export { Station };
export type { IStationState, IStationData };

View File

@ -1,102 +0,0 @@
import { FederatedPointerEvent, Point } from 'pixi.js';
import {
AbsorbableLine,
AbsorbablePosition,
GraphicDrawAssistant,
GraphicInteractionPlugin,
IDrawApp,
JlGraphic,
} from 'jl-graphic';
import { IStationData, Station, StationTemplate } from './Station';
export interface IStationDrawOptions {
newData: () => IStationData;
}
export class StationDraw extends GraphicDrawAssistant<
StationTemplate,
IStationData
> {
codeGraph: Station;
constructor(app: IDrawApp, template: StationTemplate) {
super(
app,
template,
'svguse:../../drawIcon.svg#icon-station',
'车站Station'
);
this.codeGraph = this.graphicTemplate.new();
this.container.addChild(this.codeGraph);
stationInteraction.init(app);
}
bind(): void {
super.bind();
this.codeGraph.loadData(this.graphicTemplate.datas);
this.codeGraph.doRepaint();
}
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: IStationData): boolean {
data.transform = this.container.saveTransform();
return true;
}
}
function buildAbsorbablePositions(station: Station): AbsorbablePosition[] {
const aps: AbsorbablePosition[] = [];
const stations = station.queryStore.queryByType<Station>(Station.Type);
const { width } = station.getGraphicApp().canvas;
stations.forEach((other) => {
if (other.id == station.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);
});
return aps;
}
export class stationInteraction extends GraphicInteractionPlugin<Station> {
static Name = 'station_transform';
constructor(app: IDrawApp) {
super(stationInteraction.Name, app);
}
static init(app: IDrawApp) {
return new stationInteraction(app);
}
filter(...grahpics: JlGraphic[]): Station[] | undefined {
return grahpics
.filter((g) => g.type === Station.Type)
.map((g) => g as Station);
}
bind(g: Station): void {
g.eventMode = 'static';
g.cursor = 'pointer';
g.scalable = true;
g.rotatable = true;
g.on('selected', this.onSelected, this);
}
unbind(g: Station): void {
g.eventMode = 'none';
g.scalable = false;
g.rotatable = false;
g.off('selected', this.onSelected, this);
}
onSelected(): void {
const station = this.app.selectedGraphics[0] as Station;
this.app.setOptions({
absorbablePositions: buildAbsorbablePositions(station),
});
}
}