platform-draw.ts 7.1 KB

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