Compare commits
2 Commits
2e5dd24f39
...
0728911ef7
Author | SHA1 | Date | |
---|---|---|---|
0728911ef7 | |||
72f0415f27 |
@ -63,8 +63,16 @@ const select = (id: string) => {
|
|||||||
</a-list>
|
</a-list>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-collapse-panel :header="$t('互斥区')">
|
<!-- 点位类型面板 -->
|
||||||
<a-list rowKey="id" :data-source="areas.filter(({ area }) => area?.type === MapAreaType.互斥区)">
|
<a-collapse-panel :header="$t('普通点')">
|
||||||
|
<a-list
|
||||||
|
rowKey="id"
|
||||||
|
:data-source="
|
||||||
|
points.filter(
|
||||||
|
({ id, point }) => point?.type === MapPointType.普通点 && !id?.includes('view-center-point'),
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
<template #renderItem="{ item }">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item
|
<a-list-item
|
||||||
class="ph-16"
|
class="ph-16"
|
||||||
@ -78,8 +86,159 @@ const select = (id: string) => {
|
|||||||
</a-list>
|
</a-list>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
|
||||||
<a-collapse-panel :header="$t('非互斥区')">
|
<a-collapse-panel :header="$t('等待点')">
|
||||||
<a-list rowKey="id" :data-source="areas.filter(({ area }) => area?.type === MapAreaType.非互斥区)">
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.等待点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('避让点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.避让点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('临时避让点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.临时避让点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('库区点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.库区点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('电梯点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.电梯点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('自动门点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.自动门点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('充电点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.充电点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('停靠点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.停靠点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('动作点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.动作点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<a-collapse-panel :header="$t('禁行点')">
|
||||||
|
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.禁行点)">
|
||||||
|
<template #renderItem="{ item }">
|
||||||
|
<a-list-item
|
||||||
|
class="ph-16"
|
||||||
|
:class="{ selected: item.id === current }"
|
||||||
|
style="height: 36px"
|
||||||
|
@click="select(item.id)"
|
||||||
|
>
|
||||||
|
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||||
|
</a-list-item>
|
||||||
|
</template>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
|
||||||
|
<!-- 路线类型面板 -->
|
||||||
|
<a-collapse-panel :header="$t('普通路线')">
|
||||||
|
<a-list rowKey="id" :data-source="routes.filter(({ route }) => route?.pass === MapRoutePassType.无)">
|
||||||
<template #renderItem="{ item }">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item
|
<a-list-item
|
||||||
class="ph-16"
|
class="ph-16"
|
||||||
@ -144,8 +303,9 @@ const select = (id: string) => {
|
|||||||
</a-list>
|
</a-list>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
|
||||||
<a-collapse-panel :header="$t('普通路线')">
|
<!-- 区域类型面板 -->
|
||||||
<a-list rowKey="id" :data-source="routes.filter(({ route }) => route?.pass === MapRoutePassType.无)">
|
<a-collapse-panel :header="$t('互斥区')">
|
||||||
|
<a-list rowKey="id" :data-source="areas.filter(({ area }) => area?.type === MapAreaType.互斥区)">
|
||||||
<template #renderItem="{ item }">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item
|
<a-list-item
|
||||||
class="ph-16"
|
class="ph-16"
|
||||||
@ -159,68 +319,8 @@ const select = (id: string) => {
|
|||||||
</a-list>
|
</a-list>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
|
||||||
<a-collapse-panel :header="$t('等待点')">
|
<a-collapse-panel :header="$t('非互斥区')">
|
||||||
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.等待点)">
|
<a-list rowKey="id" :data-source="areas.filter(({ area }) => area?.type === MapAreaType.非互斥区)">
|
||||||
<template #renderItem="{ item }">
|
|
||||||
<a-list-item
|
|
||||||
class="ph-16"
|
|
||||||
:class="{ selected: item.id === current }"
|
|
||||||
style="height: 36px"
|
|
||||||
@click="select(item.id)"
|
|
||||||
>
|
|
||||||
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
|
||||||
</a-list-item>
|
|
||||||
</template>
|
|
||||||
</a-list>
|
|
||||||
</a-collapse-panel>
|
|
||||||
|
|
||||||
<a-collapse-panel :header="$t('充电点')">
|
|
||||||
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.充电点)">
|
|
||||||
<template #renderItem="{ item }">
|
|
||||||
<a-list-item
|
|
||||||
class="ph-16"
|
|
||||||
:class="{ selected: item.id === current }"
|
|
||||||
style="height: 36px"
|
|
||||||
@click="select(item.id)"
|
|
||||||
>
|
|
||||||
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
|
||||||
</a-list-item>
|
|
||||||
</template>
|
|
||||||
</a-list>
|
|
||||||
</a-collapse-panel>
|
|
||||||
|
|
||||||
<a-collapse-panel :header="$t('停靠点')">
|
|
||||||
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.停靠点)">
|
|
||||||
<template #renderItem="{ item }">
|
|
||||||
<a-list-item
|
|
||||||
class="ph-16"
|
|
||||||
:class="{ selected: item.id === current }"
|
|
||||||
style="height: 36px"
|
|
||||||
@click="select(item.id)"
|
|
||||||
>
|
|
||||||
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
|
||||||
</a-list-item>
|
|
||||||
</template>
|
|
||||||
</a-list>
|
|
||||||
</a-collapse-panel>
|
|
||||||
|
|
||||||
<a-collapse-panel :header="$t('禁行点')">
|
|
||||||
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.禁行点)">
|
|
||||||
<template #renderItem="{ item }">
|
|
||||||
<a-list-item
|
|
||||||
class="ph-16"
|
|
||||||
:class="{ selected: item.id === current }"
|
|
||||||
style="height: 36px"
|
|
||||||
@click="select(item.id)"
|
|
||||||
>
|
|
||||||
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
|
||||||
</a-list-item>
|
|
||||||
</template>
|
|
||||||
</a-list>
|
|
||||||
</a-collapse-panel>
|
|
||||||
|
|
||||||
<a-collapse-panel :header="$t('普通点')">
|
|
||||||
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.普通点)">
|
|
||||||
<template #renderItem="{ item }">
|
<template #renderItem="{ item }">
|
||||||
<a-list-item
|
<a-list-item
|
||||||
class="ph-16"
|
class="ph-16"
|
||||||
|
@ -63,7 +63,7 @@ const importScene = async () => {
|
|||||||
const file = await selectFile('.scene');
|
const file = await selectFile('.scene');
|
||||||
if (!file?.size) return;
|
if (!file?.size) return;
|
||||||
const json = await decodeTextFile(file);
|
const json = await decodeTextFile(file);
|
||||||
editor.value?.load(json, editable.value, detail.value ?? {});
|
editor.value?.load(json, editable.value, detail.value ?? {}, true); // 第四个参数isImport=true
|
||||||
};
|
};
|
||||||
const exportScene = () => {
|
const exportScene = () => {
|
||||||
const json = editor.value?.save();
|
const json = editor.value?.save();
|
||||||
|
@ -100,7 +100,7 @@ const importScene = async () => {
|
|||||||
const file = await selectFile('.scene');
|
const file = await selectFile('.scene');
|
||||||
if (!file?.size) return;
|
if (!file?.size) return;
|
||||||
const json = await decodeTextFile(file);
|
const json = await decodeTextFile(file);
|
||||||
editor.value?.load(json, editable.value);
|
editor.value?.load(json, editable.value, undefined, true); // 第四个参数isImport=true
|
||||||
};
|
};
|
||||||
const exportScene = () => {
|
const exportScene = () => {
|
||||||
const json = editor.value?.save();
|
const json = editor.value?.save();
|
||||||
|
@ -45,8 +45,14 @@ export class EditorService extends Meta2d {
|
|||||||
* @param map 场景文件的JSON字符串,为空则创建新场景
|
* @param map 场景文件的JSON字符串,为空则创建新场景
|
||||||
* @param editable 是否可编辑状态,控制编辑器锁定状态
|
* @param editable 是否可编辑状态,控制编辑器锁定状态
|
||||||
* @param detail 群组场景详情,包含机器人组和机器人信息
|
* @param detail 群组场景详情,包含机器人组和机器人信息
|
||||||
|
* @param isImport 是否为导入场景文件,true时进行反向坐标转换
|
||||||
*/
|
*/
|
||||||
public async load(map?: string, editable = false, detail?: Partial<GroupSceneDetail>): Promise<void> {
|
public async load(
|
||||||
|
map?: string,
|
||||||
|
editable = false,
|
||||||
|
detail?: Partial<GroupSceneDetail>,
|
||||||
|
isImport = false,
|
||||||
|
): Promise<void> {
|
||||||
const scene: StandardScene = map ? JSON.parse(map) : {};
|
const scene: StandardScene = map ? JSON.parse(map) : {};
|
||||||
if (!isEmpty(detail?.group)) {
|
if (!isEmpty(detail?.group)) {
|
||||||
scene.robotGroups = [detail.group];
|
scene.robotGroups = [detail.group];
|
||||||
@ -59,9 +65,9 @@ export class EditorService extends Meta2d {
|
|||||||
this.open();
|
this.open();
|
||||||
this.setState(editable);
|
this.setState(editable);
|
||||||
this.#loadRobots(robotGroups, robots);
|
this.#loadRobots(robotGroups, robots);
|
||||||
await this.#loadScenePoints(points);
|
await this.#loadScenePoints(points, isImport);
|
||||||
this.#loadSceneRoutes(routes);
|
this.#loadSceneRoutes(routes, isImport);
|
||||||
await this.#loadSceneAreas(areas);
|
await this.#loadSceneAreas(areas, isImport);
|
||||||
this.store.historyIndex = undefined;
|
this.store.historyIndex = undefined;
|
||||||
this.store.histories = [];
|
this.store.histories = [];
|
||||||
// this.scale(scale);与xd 自定义缩放冲突,暂时去掉
|
// this.scale(scale);与xd 自定义缩放冲突,暂时去掉
|
||||||
@ -105,13 +111,22 @@ export class EditorService extends Meta2d {
|
|||||||
/**
|
/**
|
||||||
* 从场景数据加载点位到画布
|
* 从场景数据加载点位到画布
|
||||||
* @param points 标准场景点位数据数组
|
* @param points 标准场景点位数据数组
|
||||||
|
* @param isImport 是否为导入场景文件,true时进行反向坐标转换
|
||||||
*/
|
*/
|
||||||
async #loadScenePoints(points?: StandardScenePoint[]): Promise<void> {
|
async #loadScenePoints(points?: StandardScenePoint[], isImport = false): Promise<void> {
|
||||||
if (!points?.length) return;
|
if (!points?.length) return;
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
points.map(async (v) => {
|
points.map(async (v) => {
|
||||||
const { id, name, desc, x, y, type, extensionType, robots, actions, properties, deviceId, enabled } = v;
|
const { id, name, desc, x, y, type, extensionType, robots, actions, properties, deviceId, enabled } = v;
|
||||||
await this.addPoint({ x, y }, type, id);
|
// 只有在导入场景文件时才进行反向坐标转换
|
||||||
|
let finalX = x;
|
||||||
|
let finalY = y;
|
||||||
|
if (isImport) {
|
||||||
|
const transformedCoords = this.#reverseTransformCoordinate(x, y);
|
||||||
|
finalX = transformedCoords.x;
|
||||||
|
finalY = transformedCoords.y;
|
||||||
|
}
|
||||||
|
await this.addPoint({ x: finalX, y: finalY }, type, id);
|
||||||
this.setValue(
|
this.setValue(
|
||||||
{ id, label: name, desc, properties, point: { type, extensionType, robots, actions, deviceId, enabled } },
|
{ id, label: name, desc, properties, point: { type, extensionType, robots, actions, deviceId, enabled } },
|
||||||
{ render: false, history: false, doEvent: false },
|
{ render: false, history: false, doEvent: false },
|
||||||
@ -122,8 +137,9 @@ export class EditorService extends Meta2d {
|
|||||||
/**
|
/**
|
||||||
* 从场景数据加载路线到画布
|
* 从场景数据加载路线到画布
|
||||||
* @param routes 标准场景路线数据数组
|
* @param routes 标准场景路线数据数组
|
||||||
|
* @param isImport 是否为导入场景文件,true时进行反向坐标转换
|
||||||
*/
|
*/
|
||||||
#loadSceneRoutes(routes?: StandardSceneRoute[]): void {
|
#loadSceneRoutes(routes?: StandardSceneRoute[], isImport = false): void {
|
||||||
if (!routes?.length) return;
|
if (!routes?.length) return;
|
||||||
routes.map((v) => {
|
routes.map((v) => {
|
||||||
const { id, desc, from, to, type, pass, c1, c2, properties } = v;
|
const { id, desc, from, to, type, pass, c1, c2, properties } = v;
|
||||||
@ -133,6 +149,23 @@ export class EditorService extends Meta2d {
|
|||||||
this.addRoute([p1, p2], <MapRouteType>type, id);
|
this.addRoute([p1, p2], <MapRouteType>type, id);
|
||||||
const { x: x1, y: y1 } = this.getPointRect(p1)!;
|
const { x: x1, y: y1 } = this.getPointRect(p1)!;
|
||||||
const { x: x2, y: y2 } = this.getPointRect(p2)!;
|
const { x: x2, y: y2 } = this.getPointRect(p2)!;
|
||||||
|
|
||||||
|
// 只有在导入场景文件时才对控制点坐标进行反向转换
|
||||||
|
let transformedC1 = { x: (c1?.x ?? 0) - x1, y: (c1?.y ?? 0) - y1 };
|
||||||
|
let transformedC2 = { x: (c2?.x ?? 0) - x2, y: (c2?.y ?? 0) - y2 };
|
||||||
|
|
||||||
|
if (isImport) {
|
||||||
|
if (c1 && c1.x !== undefined && c1.y !== undefined) {
|
||||||
|
const reversedC1 = this.#reverseTransformCoordinate(c1.x, c1.y);
|
||||||
|
transformedC1 = { x: reversedC1.x - x1, y: reversedC1.y - y1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c2 && c2.x !== undefined && c2.y !== undefined) {
|
||||||
|
const reversedC2 = this.#reverseTransformCoordinate(c2.x, c2.y);
|
||||||
|
transformedC2 = { x: reversedC2.x - x2, y: reversedC2.y - y2 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setValue(
|
this.setValue(
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
@ -141,20 +174,39 @@ export class EditorService extends Meta2d {
|
|||||||
route: {
|
route: {
|
||||||
type,
|
type,
|
||||||
pass,
|
pass,
|
||||||
c1: { x: (c1?.x ?? 0) - x1, y: (c1?.y ?? 0) - y1 },
|
c1: transformedC1,
|
||||||
c2: { x: (c2?.x ?? 0) - x2, y: (c2?.y ?? 0) - y2 },
|
c2: transformedC2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ render: false, history: false, doEvent: false },
|
{ render: false, history: false, doEvent: false },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async #loadSceneAreas(areas?: StandardSceneArea[]): Promise<void> {
|
/**
|
||||||
|
* 从场景数据加载区域到画布
|
||||||
|
* @param areas 标准场景区域数据数组
|
||||||
|
* @param isImport 是否为导入场景文件,true时进行反向坐标转换
|
||||||
|
*/
|
||||||
|
async #loadSceneAreas(areas?: StandardSceneArea[], isImport = false): Promise<void> {
|
||||||
if (!areas?.length) return;
|
if (!areas?.length) return;
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
areas.map(async (v) => {
|
areas.map(async (v) => {
|
||||||
const { id, name, desc, x, y, w, h, type, points, routes, maxAmr, inoutflag, storageLocations, properties } = v;
|
const { id, name, desc, x, y, w, h, type, points, routes, maxAmr, inoutflag, storageLocations, properties } = v;
|
||||||
await this.addArea({ x, y }, { x: x + w, y: y + h }, type, id);
|
// 只有在导入场景文件时才进行反向坐标转换
|
||||||
|
let finalX = x;
|
||||||
|
let finalY = y;
|
||||||
|
let finalW = w;
|
||||||
|
let finalH = h;
|
||||||
|
|
||||||
|
if (isImport) {
|
||||||
|
const transformedCoords = this.#reverseTransformCoordinate(x, y);
|
||||||
|
finalX = transformedCoords.x;
|
||||||
|
finalY = transformedCoords.y;
|
||||||
|
finalW = this.#reverseTransformSize(w);
|
||||||
|
finalH = this.#reverseTransformSize(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.addArea({ x: finalX, y: finalY }, { x: finalX + finalW, y: finalY + finalH }, type, id);
|
||||||
|
|
||||||
// 对于库区类型,需要将点位名称数组转换为点位ID数组,并更新动作点的库位信息
|
// 对于库区类型,需要将点位名称数组转换为点位ID数组,并更新动作点的库位信息
|
||||||
let processedPoints = points;
|
let processedPoints = points;
|
||||||
@ -503,6 +555,34 @@ export class EditorService extends Meta2d {
|
|||||||
return this.#fixPrecision(scaledSize);
|
return this.#fixPrecision(scaledSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 反向坐标转换方法 - 将中心点原点的坐标转换为左上角原点的坐标 */
|
||||||
|
#reverseTransformCoordinate(x: number, y: number): { x: number; y: number } {
|
||||||
|
const { ratio = 1, width = 0, height = 0 } = this.#originalSceneData ?? {};
|
||||||
|
|
||||||
|
// 先进行坐标系转换:中心点原点 -> 左上角原点
|
||||||
|
const topLeftX = x + width / 2;
|
||||||
|
const topLeftY = height / 2 - y;
|
||||||
|
|
||||||
|
// 再根据ratio进行缩放
|
||||||
|
const scaledX = topLeftX * ratio;
|
||||||
|
const scaledY = topLeftY * ratio;
|
||||||
|
|
||||||
|
// 应用精度控制:保留3位小数,之后直接舍去
|
||||||
|
return {
|
||||||
|
x: this.#fixPrecision(scaledX),
|
||||||
|
y: this.#fixPrecision(scaledY),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 反向尺寸转换方法 - 根据ratio还原尺寸 */
|
||||||
|
#reverseTransformSize(size: number): number {
|
||||||
|
const { ratio = 1 } = this.#originalSceneData ?? {};
|
||||||
|
const scaledSize = size * ratio;
|
||||||
|
|
||||||
|
// 应用精度控制:保留3位小数,之后直接舍去
|
||||||
|
return this.#fixPrecision(scaledSize);
|
||||||
|
}
|
||||||
|
|
||||||
/** 精度控制方法 - 固定3位小数,3位之后直接舍去(不四舍五入),不足3位则补齐 */
|
/** 精度控制方法 - 固定3位小数,3位之后直接舍去(不四舍五入),不足3位则补齐 */
|
||||||
#fixPrecision(value: number): number {
|
#fixPrecision(value: number): number {
|
||||||
// 先截断到3位小数(不四舍五入)
|
// 先截断到3位小数(不四舍五入)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user