123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- import { Pos, Size } from "@/utils/math";
- import { extractConnectedSegments } from "@/utils/polygon";
- import { validNum } from "@/utils/shared";
- import { aiIconMap, iconGroups } from "../constant";
- import { Euler, Quaternion } from "three";
- export enum SCENE_TYPE {
- fuse = "fuse",
- mesh = "mesh",
- cloud = "cloud",
- }
- export type Scene = {
- type: SCENE_TYPE;
- m: string;
- title: string;
- id: string;
- };
- export type SceneFloor = {
- name: string;
- subgroup?: number;
- geos: (Pos & { z: number })[][];
- thumb?: string;
- box?: {
- bound: {
- x_min: number;
- x_max: number;
- y_min: number;
- y_max: number;
- z_min: number;
- z_max: number;
- };
- rotate: number;
- scale: number;
- };
- compass?: number;
- };
- export type SceneFloors = SceneFloor[];
- export type Taging = {
- url: string;
- position: Pos & { z: number };
- size?: Size;
- rotate?: number;
- name?: string;
- pixel?: boolean;
- subgroup?: string;
- };
- export const SceneTypeNames = {
- [SCENE_TYPE.fuse]: "融合场景",
- [SCENE_TYPE.mesh]: "Mesh场景",
- [SCENE_TYPE.cloud]: "点云场景",
- };
- export const getSceneApi = async (type: string | undefined, url: string) => {
- if (url[0] === "/") {
- url = url.substring(1, url.length);
- }
- let origin = type ? window.platform.resourceURLS[type] : '';
- if (origin[origin.length - 1] !== "/") {
- origin = origin + "/";
- }
- const uri = origin + url;
- // try {
- // uri = new URL(window.platform.resourceURLS[type]).toString();
- // } catch {
- // uri = window.platform.resourceURLS[type] + url;
- // }
- const res = await fetch(uri, { method: "HEAD" });
- if (res.status !== 200) {
- throw `${uri}链接错误`;
- }
- return uri;
- };
- export type Tagings = Taging[];
- export const compassGets = {
- [SCENE_TYPE.fuse]: () => void 0,
- [SCENE_TYPE.cloud]: () => void 0,
- [SCENE_TYPE.mesh]: async (scene: Scene) => {
- const prev = `/scene_view_data/${scene.m}`;
- const config = await getSceneApi("oss", `${prev}/data/scene.json`)
- .then((url) => fetch(url))
- .then((res) => res.json())
- .catch(() => ({ version: 0, billboards: 0, tags: 0, orientation: 0 }));
- const floorpanCompass = await getSceneApi(
- "oss",
- `${prev}/user/floorplan.json?_=${config.version}`
- )
- .then((url) => fetch(url))
- .then((res) => res.json())
- .then((data) => data.compass)
- .catch(() => null);
- return typeof floorpanCompass === "number"
- ? floorpanCompass
- : Number(config.orientation);
- },
- };
- export const taggingGets = {
- [SCENE_TYPE.fuse]: async (scene: Scene, options: string[]) => {
- if (!options.includes("hot")) return [];
- const reqOpts = { headers: { share: "1" } };
- const icons = await getSceneApi(
- scene.type,
- `/fusion/edit/hotIcon/list?caseId=${scene.m}`
- )
- .then((url) => fetch(url, reqOpts))
- .then((res) => res.json())
- .then((res) => res.data)
- .catch(() => []);
- const tagTypes: any[] = await getSceneApi(
- scene.type,
- `/fusion/caseTag/allList?caseId=${scene.m}`
- )
- .then((url) => fetch(url, reqOpts))
- .then((res) => res.json())
- .then((res) => res.data)
- .catch(() => []);
- const tags: Tagings = [];
- const reqs = tagTypes.map((type) =>
- getSceneApi(
- scene.type,
- `/fusion/caseTagPoint/allList?tagId=${type.tagId}`
- )
- .then((url) => fetch(url, reqOpts))
- .then((res) => res.json())
- .then((res) => res.data)
- .then((items) => {
- items.forEach((item: any) => {
- tags.push({
- url: icons.find((icon: any) => icon.iconId === type.hotIconId)
- ?.iconUrl,
- position: JSON.parse(item.tagPoint),
- });
- });
- })
- .catch(() => [])
- );
- await Promise.all(reqs);
- return tags;
- },
- [SCENE_TYPE.cloud]: async (scene: Scene, options: string[]) => {
- if (!options.includes("hot")) return [];
- const tags: Tagings = await getSceneApi(
- scene.type,
- `/laser/poi/${scene.m}/list`
- )
- .then((url) => fetch(url))
- .then((res) => res.json())
- .then((res) => res.data.list)
- .then((pois) =>
- pois.map((poi: any) => ({
- url: poi.hotStyleAtom.icon,
- position: poi.dataset_location,
- }))
- )
- .catch(() => []);
- return tags;
- },
- [SCENE_TYPE.mesh]: async (scene: Scene, options: string[]) => {
- const tags: Tagings = [];
- const prev = `/scene_view_data/${scene.m}`;
- const config = await getSceneApi("oss", `${prev}/data/scene.json`)
- .then((url) => fetch(url))
- .then((res) => res.json())
- .catch(() => ({ version: 0, billboards: 0, tags: 0, orientation: 0 }));
- if (options.includes("hot") && config.tags) {
- const medias = await getSceneApi(
- "oss",
- `${prev}/user/hot.json?_=${config.version}`
- )
- .then((url) => fetch(url))
- .then((res) => res.json())
- .catch(() => []);
- const reqs = medias.map((media: any) => {
- if (!validNum(media.position.x) || !validNum(media.position.y)) return;
- return getSceneApi("oss", `${prev}/user/${media.icon}`)
- .then((url) => {
- tags.push({ url, position: media.position });
- })
- .catch(() => {});
- });
- await Promise.all(reqs);
- }
- if (options.includes("signage") && config.billboards) {
- const signages = await getSceneApi(
- "oss",
- `${prev}/user/billboards.json?_=${config.version}`
- )
- .then((url) => fetch(url))
- .then((res) => res.json())
- .catch(() => []);
- const reqs = signages.map((signage: any) => {
- if (!validNum(signage.pos[0]) || !validNum(signage.pos[2])) return;
- console.error(signage)
- const getIcon =
- signage.icon.indexOf("style-") === 0
- ? getSceneApi(undefined, `/styles/${signage.icon}.svg`).catch((e) => {
- console.error(e)
- return getSceneApi(
- "ossRoot",
- `/sdk/images/billboard/${signage.icon}.png`
- )
- })
- : getSceneApi("oss", `${prev}/user/${signage.icon}`);
- const q = new Quaternion(...signage.qua)
- const yRotate = new Euler().setFromQuaternion(q, 'XYZ').y + Math.PI
-
- return getIcon
- .then((url) => {
- tags.push({
- url,
- position: {
- x: signage.pos[0],
- y: signage.pos[2],
- z:
- signage.pos[1] < 0
- ? Math.ceil(signage.pos[1] * 10) / 10
- : Math.floor(signage.pos[1] * 10) / 10,
- },
- rotate: yRotate,
- size: {
- width: signage.width * (signage.scaleRatio / 100),
- height: signage.height * (signage.scaleRatio / 100),
- },
- });
- })
- .catch(() => {});
- });
- await Promise.all(reqs);
- }
- await getSceneApi(
- "oss",
- `${prev}/data/floorplan/ai.json?_=${config.version}`
- )
- .then((url) => fetch(url))
- .then((res) => res.json())
- .then((datas) => {
- for (const data of datas) {
- const reg = data.imagePath.match(/floor_(\d)\.png/);
- const subgroup = reg ? Number(reg[1]) : undefined;
- for (const shape of data.shapes) {
- const pos = {
- x: (shape.bbox[0] + shape.bbox[2]) / 2 / data.imageWidth,
- y: (shape.bbox[1] + shape.bbox[3]) / 2 / data.imageHeight,
- z: undefined,
- };
- const size = {
- width: (shape.bbox[2] - shape.bbox[0]) / data.imageWidth,
- height: (shape.bbox[3] - shape.bbox[1]) / data.imageHeight,
- };
- const icon =
- shape.category in aiIconMap
- ? (aiIconMap as any)[shape.category]
- : shape.category;
- let name = "";
- for (const group of iconGroups) {
- for (const itemGroup of group.children) {
- for (const item of itemGroup.children) {
- if (item.icon === icon) {
- name = item.name;
- }
- }
- }
- }
- if (name) {
- tags.push({
- position: pos,
- url: `./icons/${icon ? icon : "circle"}.svg`,
- name,
- pixel: true,
- size,
- subgroup,
- } as any);
- } else {
- console.error("找不到ai家具", icon, name, pos);
- }
- }
- }
- })
- .catch((e) => {
- console.error(e);
- });
- console.log("tags", tags);
- return tags;
- },
- };
- export const getFloors = {
- [SCENE_TYPE.mesh]: async (scene: Scene) => {
- return getSceneApi(
- "oss",
- `/scene_view_data/${scene.m}/data/floorplan_cad.json?_=${Date.now()}`
- )
- .then((url) => fetch(url))
- .then((res) => res.json())
- .catch(() => ({ floors: [] }));
- },
- };
- export const lineGets = {
- [SCENE_TYPE.fuse]: async (scene: Scene) => {
- const tags = await taggingGets[SCENE_TYPE.fuse](scene, ["hot"]);
- return { name: "1楼", geos: [tags.map((item) => item.position)] };
- },
- [SCENE_TYPE.mesh]: async (scene: Scene, floorName?: string) => {
- const prev = `/scene_view_data/${scene.m}/data/`;
- const [{ floors }, bounds] = await Promise.all([
- getFloors[SCENE_TYPE.mesh](scene),
- getSceneApi("oss", `${prev}floorplan/info.json`)
- .then((url) => fetch(url))
- .then((res) => res.json())
- .then((data) => data.floors)
- .catch(() => []),
- ]);
- const data: any = [];
- const reqs = floors
- .filter((item: any) => !floorName || item.name === floorName)
- .map((floor: any) => {
- const bound = {
- ...(floor.cadInfo.cadBoundingBox || {}),
- ...(bounds.find((i: any) => i.subgroup === floor.subgroup)?.bound ||
- {}),
- };
- const item: any = {
- name: floor.name,
- subgroup: floor.subgroup,
- thumb: "",
- box: {
- bound: {
- ...bound,
- y_min: -bound.y_max,
- y_max: -bound.y_min,
- z_max: bound.z_max ? Number(bound.z_max) : bound.z_max,
- z_min: bound.z_min ? Number(bound.z_min) : bound.z_min,
- },
- rotate: floor.cadInfo.res,
- scale: floor.cadInfo.currentScale,
- },
- geos: extractConnectedSegments(floor.segment).map((geo) => {
- return geo.map((id) => {
- const p = floor["vertex-xy"].find((item: any) => item.id === id);
- return { x: p.x, y: -p.y } as Pos;
- });
- }),
- };
- data.push(item);
- return getSceneApi(
- "oss",
- `${prev}floorplan/floor_${floor.subgroup}.png`
- )
- .then((url) => (item.thumb = url))
- .catch(() => (item.thumb = ""));
- });
- await Promise.all(reqs);
- return data;
- },
- [SCENE_TYPE.cloud]: async (scene: Scene) => {
- const tags = await taggingGets[SCENE_TYPE.cloud](scene, ["hot"]);
- return { name: "1楼", geos: [tags.map((item) => item.position)] };
- },
- };
|