platform-draw.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. import { genBound, onlyId } from "@/utils/shared";
  2. import { AIExposeData } from "../dialog/ai";
  3. import { Draw } from "../components/container/use-draw";
  4. import { SceneFloor } from "./platform-resource";
  5. import { getBaseItem } from "@/core/components/util";
  6. import { LineData, defaultStyle } from "@/core/components/line";
  7. import { getInitCtx, normalLineData } from "@/core/components/line/use-draw";
  8. import { defaultStyle as iconDefaultStyle } from "@/core/components/icon";
  9. import { Transform } from "konva/lib/Util";
  10. import { MathUtils } from "three";
  11. const scaleResource = (info: AIExposeData, scale: number) => {
  12. const floors = info.floors.map((item) => ({
  13. ...item,
  14. geos: item.geos.map((geo) =>
  15. geo.map((p) => ({ x: p.x * scale, y: p.y * scale, z: p.z * scale }))
  16. ),
  17. box: item.box && {
  18. ...item.box,
  19. bound: {
  20. x_min: item.box.bound.x_min * scale,
  21. x_max: item.box.bound.x_max * scale,
  22. y_min: item.box.bound.y_min * scale,
  23. y_max: item.box.bound.y_max * scale,
  24. z_min: item.box.bound.z_min * scale,
  25. z_max: item.box.bound.z_max * scale,
  26. },
  27. },
  28. }));
  29. const taggings = info.taggings
  30. .map((item) => {
  31. if (!item.pixel) {
  32. return {
  33. ...item,
  34. position: {
  35. x: item.position.x * scale,
  36. y: item.position.y * scale,
  37. z: item.position.z * scale,
  38. },
  39. };
  40. } else if (item.subgroup !== undefined) {
  41. const floor = floors.find(
  42. (floor) => floor.subgroup === item.subgroup
  43. );
  44. if (!floor || !floor.box) return;
  45. const w = floor.box.bound.x_max - floor.box.bound.x_min;
  46. const h = floor.box.bound.y_max - floor.box.bound.y_min;
  47. return {
  48. ...item,
  49. position: {
  50. x: (floor.box.bound.x_min + w * item.position.x) ,
  51. y: (floor.box.bound.y_min + h * item.position.y) ,
  52. z: (floor.box.bound.z_min + 0.001) ,
  53. },
  54. size: {
  55. width: item.size!.width * w ,
  56. height: item.size!.height * h ,
  57. },
  58. };
  59. }
  60. })
  61. .filter((item) => !!item);
  62. return {
  63. ...info,
  64. taggings,
  65. floors,
  66. };
  67. };
  68. const getResourceLayers = (data: AIExposeData) => {
  69. return data.floors
  70. .map((floor) => {
  71. let box: SceneFloor["box"];
  72. if (!floor.box || !floor.box.bound.x_max || !floor.box.bound.z_max) {
  73. const xs = floor.geos.flatMap((item) => item.map((p) => p.x));
  74. const ys = floor.geos.flatMap((item) => item.map((p) => p.y));
  75. const zs = floor.geos.flatMap((item) => item.map((p) => p.z));
  76. box = {
  77. bound: {
  78. x_min: Math.min(...xs),
  79. x_max: Math.max(...xs),
  80. y_min: Math.min(...ys),
  81. y_max: Math.max(...ys),
  82. z_min: Math.min(...zs),
  83. z_max: Math.max(...zs),
  84. },
  85. scale: 1,
  86. rotate: 0,
  87. };
  88. } else {
  89. box = floor.box;
  90. }
  91. return {
  92. ...floor,
  93. box,
  94. taggings: data.taggings
  95. .filter((item) => {
  96. return (
  97. item.position.z > box.bound.z_min &&
  98. item.position.z <= box.bound.z_max
  99. );
  100. })
  101. .map((item) => ({
  102. ...item,
  103. position: { x: item.position.x, y: item.position.y },
  104. })),
  105. geos: floor.geos.map((item) => item.map((p) => ({ x: p.x, y: p.y }))),
  106. };
  107. })
  108. .filter((floor) => floor.taggings.length > 0 || floor.geos.length > 0);
  109. };
  110. const drawLayerResource = (
  111. layerResource: ReturnType<typeof getResourceLayers>[number],
  112. draw: Draw
  113. ) => {
  114. const bound = genBound();
  115. const images: any[] = [];
  116. const createTime = Date.now();
  117. let sGeo = draw.store.getTypeItems('line')[0]
  118. let geo: LineData = sGeo ? sGeo : {
  119. ...getBaseItem(),
  120. lines: [],
  121. points: [],
  122. polygon: [],
  123. attitude: [1, 0, 0, 1, 0, 0],
  124. createTime: createTime,
  125. }
  126. const geoCtx = getInitCtx()
  127. layerResource.geos.forEach((item) => {
  128. bound.update(item);
  129. if (item.length < 1) return;
  130. let a: string = onlyId(), b: string
  131. let i = 0
  132. for (i = 0; i < item.length - 1; i++) {
  133. b = onlyId()
  134. const lId = onlyId()
  135. const l = { id: onlyId(), a, b, ...defaultStyle }
  136. const p = { id: a, ...item[i] }
  137. geoCtx.add.points[a] = p
  138. geoCtx.add.lines[lId] = l
  139. geo.points.push(p)
  140. geo.lines.push(l)
  141. a = b
  142. }
  143. const p = { id: b!, ...item[i] }
  144. geoCtx.add.points[b!] = p
  145. geo.points.push(p)
  146. });
  147. draw.history.onceTrack(() => {
  148. geo = normalLineData(geo, geoCtx)
  149. if (sGeo) {
  150. draw.store.setItem('line', {id: geo.id, value: geo });
  151. } else {
  152. draw.store.addItem('line', geo);
  153. }
  154. })
  155. if (layerResource.thumb) {
  156. const box = layerResource.box;
  157. const width = box.bound.x_max - box.bound.x_min;
  158. const height = box.bound.y_max - box.bound.y_min;
  159. const mat = new Transform().translate(
  160. box.bound.x_min + width / 2,
  161. box.bound.y_min + height / 2
  162. );
  163. // .rotate(-MathUtils.degToRad(floor.box.rotate));
  164. const thumb = {
  165. ...getBaseItem(),
  166. createTime: createTime - 1,
  167. url: layerResource.thumb,
  168. mat: mat.m,
  169. width,
  170. lock: import.meta.env.DEV ? false : true,
  171. height,
  172. cornerRadius: 0,
  173. };
  174. images.push(thumb);
  175. }
  176. images.push(
  177. ...layerResource.taggings.map((item, ndx) => {
  178. bound.update(item.position);
  179. return {
  180. ...getBaseItem(),
  181. ...iconDefaultStyle,
  182. name: item.name,
  183. fill: '#000000',
  184. createTime: createTime + layerResource.geos.length + ndx,
  185. url: item.url,
  186. lock: import.meta.env.DEV ? false : true,
  187. mat: [1, 0, 0, 1, item.position.x, item.position.y],
  188. width: item.size ? item.size.width : 100,
  189. height: item.size ? item.size.height : 100,
  190. // width: 30,
  191. // height: 30,
  192. cornerRadius: 0,
  193. };
  194. })
  195. );
  196. draw.store.addItems(
  197. "icon",
  198. images.filter((item) => item.url.includes(".svg"))
  199. );
  200. draw.store.addItems(
  201. "image",
  202. images.filter((item) => !item.url.includes(".svg"))
  203. );
  204. // draw.store.addItem("group", {
  205. // ...getBaseItem(),
  206. // ids: [...images, geo.id].map((item) => item.id),
  207. // });
  208. return bound.get();
  209. };
  210. export const drawPlatformResource = (data: AIExposeData, draw: Draw) => {
  211. // 默认为米,为了方便绘图 一米转为100
  212. const layers = getResourceLayers(scaleResource(data, 100));
  213. const layerBounds: ReturnType<typeof drawLayerResource>[] = [];
  214. draw.history.onceTrack(() => {
  215. // draw.store.setConfig({ proportion: { scale: 10, unit: 'mm' } });
  216. draw.store.setConfig({ proportion: { scale: 10, unit: "mm" } });
  217. for (const layer of layers) {
  218. // if (!draw.store.layers.includes(layer.name)) {
  219. // draw.store.addLayer(layer.name);
  220. // }
  221. // draw.store.setCurrentLayer(layer.name);
  222. layerBounds.push(drawLayerResource(layer, draw)!);
  223. }
  224. if (typeof data.compass === "number") {
  225. draw.store.setConfig({
  226. compass: {
  227. rotation: MathUtils.radToDeg(data.compass),
  228. url: draw.store.config.compass.url,
  229. },
  230. });
  231. }
  232. });
  233. if (layerBounds.length === 0 || !draw.viewer.size) return;
  234. const flyBound = layerBounds[layerBounds.length - 1]!;
  235. const size = draw.viewer.size;
  236. if (flyBound.width < 10 || flyBound.height < 10) {
  237. draw.viewer.setViewMat([
  238. 1,
  239. 0,
  240. 0,
  241. 1,
  242. flyBound.center.x + size.width / 2,
  243. flyBound.center.y + size.height / 2,
  244. ]);
  245. } else {
  246. const viewWidth = Math.max(flyBound.width, size.width);
  247. const viewHeight = Math.max(flyBound.height, size.height);
  248. const padding = Math.max(
  249. Math.min(
  250. (viewWidth - flyBound.width) / 2,
  251. (viewHeight - flyBound.height) / 2
  252. ),
  253. 40
  254. );
  255. draw.viewer.setBound({ targetBound: flyBound, padding });
  256. }
  257. };