import { genBound, onlyId } from "@/utils/shared"; import { AIExposeData } from "../dialog/ai"; import { Draw } from "../components/container/use-draw"; import { SceneFloor } from "./platform-resource"; import { getBaseItem } from "@/core/components/util"; import { LineData, defaultStyle } from "@/core/components/line"; import { getInitCtx, normalLineData } from "@/core/components/line/use-draw"; import { defaultStyle as iconDefaultStyle } from "@/core/components/icon"; import { Transform } from "konva/lib/Util"; import { MathUtils } from "three"; const scaleResource = (info: AIExposeData, scale: number) => { const floors = info.floors.map((item) => ({ ...item, geos: item.geos.map((geo) => geo.map((p) => ({ x: p.x * scale, y: p.y * scale, z: p.z * scale })) ), box: item.box && { ...item.box, bound: { x_min: item.box.bound.x_min * scale, x_max: item.box.bound.x_max * scale, y_min: item.box.bound.y_min * scale, y_max: item.box.bound.y_max * scale, z_min: item.box.bound.z_min * scale, z_max: item.box.bound.z_max * scale, }, }, })); const taggings = info.taggings .map((item) => { if (!item.pixel) { return { ...item, position: { x: item.position.x * scale, y: item.position.y * scale, z: item.position.z * scale, }, }; } else if (item.subgroup !== undefined) { const floor = floors.find( (floor) => floor.subgroup === item.subgroup ); if (!floor || !floor.box) return; const w = floor.box.bound.x_max - floor.box.bound.x_min; const h = floor.box.bound.y_max - floor.box.bound.y_min; return { ...item, position: { x: (floor.box.bound.x_min + w * item.position.x) , y: (floor.box.bound.y_min + h * item.position.y) , z: (floor.box.bound.z_min + 0.001) , }, size: { width: item.size!.width * w , height: item.size!.height * h , }, }; } }) .filter((item) => !!item); return { ...info, taggings, floors, }; }; const getResourceLayers = (data: AIExposeData) => { return data.floors .map((floor) => { let box: SceneFloor["box"]; if (!floor.box || !floor.box.bound.x_max || !floor.box.bound.z_max) { const xs = floor.geos.flatMap((item) => item.map((p) => p.x)); const ys = floor.geos.flatMap((item) => item.map((p) => p.y)); const zs = floor.geos.flatMap((item) => item.map((p) => p.z)); box = { bound: { x_min: Math.min(...xs), x_max: Math.max(...xs), y_min: Math.min(...ys), y_max: Math.max(...ys), z_min: Math.min(...zs), z_max: Math.max(...zs), }, scale: 1, rotate: 0, }; } else { box = floor.box; } return { ...floor, box, taggings: data.taggings .filter((item) => { return ( item.position.z > box.bound.z_min && item.position.z <= box.bound.z_max ); }) .map((item) => ({ ...item, position: { x: item.position.x, y: item.position.y }, })), geos: floor.geos.map((item) => item.map((p) => ({ x: p.x, y: p.y }))), }; }) .filter((floor) => floor.taggings.length > 0 || floor.geos.length > 0); }; const drawLayerResource = ( layerResource: ReturnType[number], draw: Draw ) => { const bound = genBound(); const images: any[] = []; const createTime = Date.now(); let sGeo = draw.store.getTypeItems('line')[0] let geo: LineData = sGeo ? sGeo : { ...getBaseItem(), lines: [], points: [], polygon: [], attitude: [1, 0, 0, 1, 0, 0], createTime: createTime, } const geoCtx = getInitCtx() layerResource.geos.forEach((item) => { bound.update(item); if (item.length < 1) return; let a: string = onlyId(), b: string let i = 0 for (i = 0; i < item.length - 1; i++) { b = onlyId() const lId = onlyId() const l = { id: onlyId(), a, b, ...defaultStyle } const p = { id: a, ...item[i] } geoCtx.add.points[a] = p geoCtx.add.lines[lId] = l geo.points.push(p) geo.lines.push(l) a = b } const p = { id: b!, ...item[i] } geoCtx.add.points[b!] = p geo.points.push(p) }); draw.history.onceTrack(() => { geo = normalLineData(geo, geoCtx) if (sGeo) { draw.store.setItem('line', {id: geo.id, value: geo }); } else { draw.store.addItem('line', geo); } }) if (layerResource.thumb) { const box = layerResource.box; const width = box.bound.x_max - box.bound.x_min; const height = box.bound.y_max - box.bound.y_min; const mat = new Transform().translate( box.bound.x_min + width / 2, box.bound.y_min + height / 2 ); // .rotate(-MathUtils.degToRad(floor.box.rotate)); const thumb = { ...getBaseItem(), createTime: createTime - 1, url: layerResource.thumb, mat: mat.m, width, lock: import.meta.env.DEV ? false : true, height, cornerRadius: 0, }; images.push(thumb); } images.push( ...layerResource.taggings.map((item, ndx) => { bound.update(item.position); return { ...getBaseItem(), ...iconDefaultStyle, name: item.name, fill: '#000000', createTime: createTime + layerResource.geos.length + ndx, url: item.url, lock: import.meta.env.DEV ? false : true, mat: [1, 0, 0, 1, item.position.x, item.position.y], width: item.size ? item.size.width : 100, height: item.size ? item.size.height : 100, // width: 30, // height: 30, cornerRadius: 0, }; }) ); draw.store.addItems( "icon", images.filter((item) => item.url.includes(".svg")) ); draw.store.addItems( "image", images.filter((item) => !item.url.includes(".svg")) ); // draw.store.addItem("group", { // ...getBaseItem(), // ids: [...images, geo.id].map((item) => item.id), // }); return bound.get(); }; export const drawPlatformResource = (data: AIExposeData, draw: Draw) => { // 默认为米,为了方便绘图 一米转为100 const layers = getResourceLayers(scaleResource(data, 100)); const layerBounds: ReturnType[] = []; draw.history.onceTrack(() => { // draw.store.setConfig({ proportion: { scale: 10, unit: 'mm' } }); draw.store.setConfig({ proportion: { scale: 10, unit: "mm" } }); for (const layer of layers) { // if (!draw.store.layers.includes(layer.name)) { // draw.store.addLayer(layer.name); // } // draw.store.setCurrentLayer(layer.name); layerBounds.push(drawLayerResource(layer, draw)!); } if (typeof data.compass === "number") { draw.store.setConfig({ compass: { rotation: MathUtils.radToDeg(data.compass), url: draw.store.config.compass.url, }, }); } }); if (layerBounds.length === 0 || !draw.viewer.size) return; const flyBound = layerBounds[layerBounds.length - 1]!; const size = draw.viewer.size; if (flyBound.width < 10 || flyBound.height < 10) { draw.viewer.setViewMat([ 1, 0, 0, 1, flyBound.center.x + size.width / 2, flyBound.center.y + size.height / 2, ]); } else { const viewWidth = Math.max(flyBound.width, size.width); const viewHeight = Math.max(flyBound.height, size.height); const padding = Math.max( Math.min( (viewWidth - flyBound.width) / 2, (viewHeight - flyBound.height) / 2 ), 40 ); draw.viewer.setBound({ targetBound: flyBound, padding }); } };