dataHandle.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. import { AttachCAD as CAD } from '../index'
  2. import { Data, _Point, _Line, _window, _door, _column, FloorData } from '../base/processing/index'
  3. import Stack from '../base/stack'
  4. import Point from '../core/point'
  5. import Case from '../architecture/casement'
  6. import Door from '../architecture/door/index'
  7. import Column from '../architecture/column'
  8. import GroundCase from '../architecture/groundCase'
  9. import SlideDoor from '../architecture/slideDoor'
  10. import BayCase from '../architecture/bayCase'
  11. import FurnColumn from '../furniture/column'
  12. import FurnFlue from '../furniture/flue'
  13. import { debounce } from '../util'
  14. import Line from '../core/line'
  15. import wallline from '../core/wallline'
  16. import DoubleDoor from '../architecture/doubleDoor'
  17. import Tagging from '../label/tagging'
  18. import linearch from '../architecture/linearch'
  19. import furn from '../furniture/furn'
  20. import calcRoom from './calcRoom'
  21. let notSave = false
  22. export interface transformRet {
  23. getData: (isCalcRoom?: boolean) => FloorData
  24. loadData: (data: FloorData | Data) => void
  25. getCurrentData: () => FloorData
  26. }
  27. type stackStatus = { previous: boolean, next: boolean }
  28. export interface stackRet {
  29. getStackState: () => stackStatus
  30. preservation: () => void
  31. previous: () => stackStatus
  32. stack: Stack
  33. next: () => stackStatus
  34. clearStack: () => void
  35. }
  36. // 兼容V2
  37. const compatiblev2 = (data: any): Data => {
  38. data.column = data.column || []
  39. data.window = data.window || []
  40. data.doubleDoor = data.doubleDoor || []
  41. data.door = data.door || []
  42. data.groundCase = data.groundCase || []
  43. data.bayCase = data.bayCase || []
  44. data.slideDoor = data.slideDoor || []
  45. data.tagging = data.tagging || []
  46. data.furnColumn = data.furnColumn || []
  47. data.furnFlue = data.furnFlue || []
  48. let eles = ['column', 'window', 'door', 'groundCase', 'bayCase', 'slideDoor', 'tagging', 'furnColumn', 'furnFlue']
  49. if (data['vertex-xy']) {
  50. data.vertex = data['vertex-xy']
  51. data.wall = data['segment'].map(item => ({ id: item.id, p1: item.a, p2: item.b, border: item.border, exterior: item.exterior }))
  52. }
  53. if (data['outdoor-segment']) {
  54. data.wall = data.wall.concat(data['outdoor-segment'].map(item => ({ id: item.id, p1: item.a, p2: item.b, border: item.border, exterior: true })))
  55. data.vertex = data.vertex.concat(data['outdoor-vertex'])
  56. }
  57. for (let i = 0; i < data.wall.length; i++) {
  58. let checkWalls = data.wall.filter(item => item !== data.wall[i])
  59. let so = checkWalls.find(({ p1, p2 }) => {
  60. return (p1 === data.wall[i].p1 && p2 === data.wall[i].p2) ||
  61. (p2 === data.wall[i].p1 && p1 === data.wall[i].p2)
  62. })
  63. if (so) {
  64. eles.forEach(attr => {
  65. data[attr].forEach((item) => {
  66. if (item.line === data.wall[i].id) {
  67. item.line = so.id
  68. console.log('update', item)
  69. }
  70. })
  71. })
  72. data.wall.splice(i--, 1)
  73. }
  74. }
  75. data.vertex = data.vertex.filter(p => data.wall.some(({ p1, p2 }) => p.id === p1 || p.id === p2))
  76. return data
  77. }
  78. // 反转cad图所有点的Y轴 因为cad与三维Y方向不一样
  79. export const roateDataY = (data: Data): Data => {
  80. data = {
  81. ...data,
  82. vertex: data.vertex.map(p => ({ ...p, y: -p.y })),
  83. window: [...data.window],
  84. column: [...data.column],
  85. door: [...data.door],
  86. groundCase: [...data.groundCase],
  87. slideDoor: [...data.slideDoor],
  88. bayCase: [...data.bayCase],
  89. tagging: [...data.tagging],
  90. furnColumn: [...data.furnColumn],
  91. furnFlue: [...data.furnFlue],
  92. doubleDoor: [...data.doubleDoor]
  93. };
  94. [data.window, data.column, data.door, data.slideDoor, data.tagging, data.groundCase, data.bayCase, data.furnColumn, data.furnFlue, data.doubleDoor].forEach((eles) => {
  95. eles.forEach((ele, i) => {
  96. eles[i] = {
  97. ...ele,
  98. // 反转Y
  99. pos: ele.pos.map((p, i) => (i % 2) ? -p : p)
  100. }
  101. })
  102. })
  103. return data
  104. }
  105. // 附加数据与svg转换功能
  106. export const attchTransform = (cad: CAD) => {
  107. // 获取数据
  108. cad.getData = (isCalcRoom = false): FloorData => {
  109. return {
  110. floors: cad.processings.map(processing => {
  111. let data = roateDataY(processing.toData())
  112. data.dire = processing.direction.angle
  113. if (isCalcRoom) {
  114. data = calcRoom(data, cad)
  115. }
  116. return data
  117. })
  118. }
  119. }
  120. // 加载数据
  121. cad.loadData = (ndata: FloorData | Data) => {
  122. if (!(ndata as FloorData).floors) {
  123. (ndata as Data).show = true
  124. ndata = {floors: [(ndata as Data)]}
  125. }
  126. let data: FloorData = JSON.parse(JSON.stringify(ndata)) as FloorData
  127. if (!data.floors.some(item => item.show)) {
  128. data.floors[0].show = true
  129. }
  130. data.floors = data.floors.map(floor => roateDataY(compatiblev2(floor)))
  131. notSave = true
  132. // 卸载旧数据
  133. cad.processings.forEach(processing => {
  134. // 卸载旧数据
  135. processing.attrs.forEach(attr => {
  136. while (processing[attr].length) {
  137. // 同步删除
  138. processing[attr][0].ele.destroy(true, true)
  139. }
  140. })
  141. })
  142. data.floors.forEach(item => {
  143. let processing = cad.processings.find(({id}) => id === item.id)
  144. if (!processing) {
  145. processing = cad.addProcessing()
  146. processing.id = item.id
  147. }
  148. })
  149. for (let i = 0; i < cad.processings.length; i++) {
  150. if (!data.floors.some(({id}) => cad.processings[i].id === id)) {
  151. cad.delProcessing(cad.processings[i--])
  152. }
  153. }
  154. cad.processings.forEach(processing => {
  155. for (let i = 0; i < processing.render.elements.length; i++) {
  156. let ele = processing.render.elements[i]
  157. let delAttrs = [Case, Door, SlideDoor, DoubleDoor, Column, wallline, Point, GroundCase, Tagging, BayCase, FurnColumn, FurnFlue]
  158. if (delAttrs.some(cls => ele instanceof cls)) {
  159. processing.render.remove(ele)
  160. i--
  161. }
  162. }
  163. })
  164. data.floors.forEach(item => {
  165. let processing = cad.processings.find(({id}) => {
  166. return id === item.id
  167. })
  168. item.surplus = []
  169. processing.toEles(item)
  170. processing.direction.__state.direct = true
  171. processing.direction.angle = item.dire || 0
  172. processing.direction.__state.direct = false
  173. processing.direction.update()
  174. cad.adapt(item, void 0, void 0, data.floors[0])
  175. })
  176. setTimeout(() => notSave = false, 5000)
  177. }
  178. }
  179. // 附加栈功能
  180. export const attchStack = (cad: CAD) => {
  181. sessionStorage.clear();
  182. let current = 0
  183. let stack = new Stack('cad_' + Date.now())
  184. cad.stack = stack
  185. const getRet = (c = current): stackStatus => {
  186. let slen = stack.getLength()
  187. let previous = slen === 1 && current === 1 ? false : c > 0
  188. return { previous: previous, next: c < slen - 1 }
  189. }
  190. cad.clearStack = () => {
  191. sessionStorage.clear()
  192. stack.setLength(current = 0)
  193. }
  194. cad.getCurrentData = () => stack.get(current - 1)
  195. // 保存
  196. cad.preservation = debounce(() => {
  197. if ((cad as any).stoppreservation) return;
  198. // if (notSave) return;
  199. let newData = cad.getData()
  200. let prevIndex = stack.getLength() - 1
  201. // 旧版数据,先注释
  202. // newData["vertex-xy"] = newData["vertex-xy"].concat(newData.surplus)
  203. // delete newData.surplus
  204. if (prevIndex === 0 ||
  205. JSON.stringify(newData) !== JSON.stringify(stack.get(prevIndex))
  206. ) {
  207. // stack.setLength(current + 1)
  208. stack.push(newData)
  209. ++current
  210. }
  211. }, 500)
  212. let minStep = 500
  213. let currDate = Date.now()
  214. let timeout
  215. // 撤销
  216. cad.previous = (): stackStatus => {
  217. if (!getRet().previous) return getRet()
  218. --current
  219. clearTimeout(timeout)
  220. timeout = setTimeout(() => {
  221. // console.log(stack.get(current))
  222. cad.loadData(stack.get(current))
  223. }, minStep)
  224. return getRet()
  225. }
  226. // 回退
  227. cad.next = (): stackStatus => {
  228. if (!getRet().next) return getRet()
  229. ++current
  230. clearTimeout(timeout)
  231. timeout = setTimeout(() => {
  232. cad.loadData(stack.get(current))
  233. }, minStep)
  234. return getRet()
  235. if (Date.now() - currDate > minStep) {
  236. currDate = Date.now()
  237. getRet().next && cad.loadData(stack.get(++current))
  238. }
  239. return getRet()
  240. }
  241. cad.getStackState = getRet
  242. let destroy = cad.destroy
  243. cad.destroy = function (...args) {
  244. stack = null
  245. destroy.apply(this, args)
  246. }
  247. }
  248. // 附加自动保存功能
  249. export const autoPreservation = (cad: CAD) => {
  250. [Point, Case, Door, Column, GroundCase, SlideDoor, BayCase, FurnColumn, Line, FurnFlue, wallline, DoubleDoor].forEach(cls => {
  251. let dragend = cls.prototype.dragEnd
  252. cls.prototype.dragEnd = async function (...args) {
  253. dragend && await dragend.call(this, ...args)
  254. setTimeout(() => {
  255. cad.preservation()
  256. }, 100)
  257. }
  258. let destroy = cad.destroy
  259. cad.destroy = function (...args) {
  260. destroy.apply(this, args)
  261. cls.prototype.dragEnd = dragend
  262. }
  263. });
  264. const increase = cad.increase
  265. cad.increase = (...args) => {
  266. let ret = increase.call(cad, ...args)
  267. if (!ret.error) {
  268. setTimeout(() => {
  269. cad.preservation()
  270. }, 100)
  271. }
  272. return ret
  273. }
  274. cad.preservation()
  275. }