import { AttachCAD as CAD } from '../index' import { Data, _Point, _Line, _window, _door, _column, FloorData } from '../base/processing/index' import Stack from '../base/stack' import Point from '../core/point' import Case from '../architecture/casement' import Door from '../architecture/door/index' import Column from '../architecture/column' import GroundCase from '../architecture/groundCase' import SlideDoor from '../architecture/slideDoor' import BayCase from '../architecture/bayCase' import FurnColumn from '../furniture/column' import FurnFlue from '../furniture/flue' import { debounce } from '../util' import Line from '../core/line' import wallline from '../core/wallline' import DoubleDoor from '../architecture/doubleDoor' import Tagging from '../label/tagging' import linearch from '../architecture/linearch' import furn from '../furniture/furn' import calcRoom from './calcRoom' let notSave = false export interface transformRet { getData: (isCalcRoom?: boolean) => FloorData loadData: (data: FloorData | Data) => void getCurrentData: () => FloorData } type stackStatus = { previous: boolean, next: boolean } export interface stackRet { getStackState: () => stackStatus preservation: () => void previous: () => stackStatus stack: Stack next: () => stackStatus clearStack: () => void } // 兼容V2 const compatiblev2 = (data: any): Data => { data.column = data.column || [] data.window = data.window || [] data.doubleDoor = data.doubleDoor || [] data.door = data.door || [] data.groundCase = data.groundCase || [] data.bayCase = data.bayCase || [] data.slideDoor = data.slideDoor || [] data.tagging = data.tagging || [] data.furnColumn = data.furnColumn || [] data.furnFlue = data.furnFlue || [] let eles = ['column', 'window', 'door', 'groundCase', 'bayCase', 'slideDoor', 'tagging', 'furnColumn', 'furnFlue'] if (data['vertex-xy']) { data.vertex = data['vertex-xy'] data.wall = data['segment'].map(item => ({ id: item.id, p1: item.a, p2: item.b, border: item.border, exterior: item.exterior })) } if (data['outdoor-segment']) { data.wall = data.wall.concat(data['outdoor-segment'].map(item => ({ id: item.id, p1: item.a, p2: item.b, border: item.border, exterior: true }))) data.vertex = data.vertex.concat(data['outdoor-vertex']) } for (let i = 0; i < data.wall.length; i++) { let checkWalls = data.wall.filter(item => item !== data.wall[i]) let so = checkWalls.find(({ p1, p2 }) => { return (p1 === data.wall[i].p1 && p2 === data.wall[i].p2) || (p2 === data.wall[i].p1 && p1 === data.wall[i].p2) }) if (so) { eles.forEach(attr => { data[attr].forEach((item) => { if (item.line === data.wall[i].id) { item.line = so.id console.log('update', item) } }) }) data.wall.splice(i--, 1) } } data.vertex = data.vertex.filter(p => data.wall.some(({ p1, p2 }) => p.id === p1 || p.id === p2)) return data } // 反转cad图所有点的Y轴 因为cad与三维Y方向不一样 export const roateDataY = (data: Data): Data => { data = { ...data, vertex: data.vertex.map(p => ({ ...p, y: -p.y })), window: [...data.window], column: [...data.column], door: [...data.door], groundCase: [...data.groundCase], slideDoor: [...data.slideDoor], bayCase: [...data.bayCase], tagging: [...data.tagging], furnColumn: [...data.furnColumn], furnFlue: [...data.furnFlue], doubleDoor: [...data.doubleDoor] }; [data.window, data.column, data.door, data.slideDoor, data.tagging, data.groundCase, data.bayCase, data.furnColumn, data.furnFlue, data.doubleDoor].forEach((eles) => { eles.forEach((ele, i) => { eles[i] = { ...ele, // 反转Y pos: ele.pos.map((p, i) => (i % 2) ? -p : p) } }) }) return data } // 附加数据与svg转换功能 export const attchTransform = (cad: CAD) => { // 获取数据 cad.getData = (isCalcRoom = false): FloorData => { return { floors: cad.processings.map(processing => { let data = roateDataY(processing.toData()) data.dire = processing.direction.angle if (isCalcRoom) { data = calcRoom(data, cad) } return data }) } } // 加载数据 cad.loadData = (ndata: FloorData | Data) => { if (!(ndata as FloorData).floors) { (ndata as Data).show = true ndata = {floors: [(ndata as Data)]} } let data: FloorData = JSON.parse(JSON.stringify(ndata)) as FloorData if (!data.floors.some(item => item.show)) { data.floors[0].show = true } data.floors = data.floors.map(floor => roateDataY(compatiblev2(floor))) notSave = true // 卸载旧数据 cad.processings.forEach(processing => { // 卸载旧数据 processing.attrs.forEach(attr => { while (processing[attr].length) { // 同步删除 processing[attr][0].ele.destroy(true, true) } }) }) data.floors.forEach(item => { let processing = cad.processings.find(({id}) => id === item.id) if (!processing) { processing = cad.addProcessing() processing.id = item.id } }) for (let i = 0; i < cad.processings.length; i++) { if (!data.floors.some(({id}) => cad.processings[i].id === id)) { cad.delProcessing(cad.processings[i--]) } } cad.processings.forEach(processing => { for (let i = 0; i < processing.render.elements.length; i++) { let ele = processing.render.elements[i] let delAttrs = [Case, Door, SlideDoor, DoubleDoor, Column, wallline, Point, GroundCase, Tagging, BayCase, FurnColumn, FurnFlue] if (delAttrs.some(cls => ele instanceof cls)) { processing.render.remove(ele) i-- } } }) data.floors.forEach(item => { let processing = cad.processings.find(({id}) => { return id === item.id }) item.surplus = [] processing.toEles(item) processing.direction.__state.direct = true processing.direction.angle = item.dire || 0 processing.direction.__state.direct = false processing.direction.update() cad.adapt(item, void 0, void 0, data.floors[0]) }) setTimeout(() => notSave = false, 5000) } } // 附加栈功能 export const attchStack = (cad: CAD) => { sessionStorage.clear(); let current = 0 let stack = new Stack('cad_' + Date.now()) cad.stack = stack const getRet = (c = current): stackStatus => { let slen = stack.getLength() let previous = slen === 1 && current === 1 ? false : c > 0 return { previous: previous, next: c < slen - 1 } } cad.clearStack = () => { sessionStorage.clear() stack.setLength(current = 0) } cad.getCurrentData = () => stack.get(current - 1) // 保存 cad.preservation = debounce(() => { if ((cad as any).stoppreservation) return; // if (notSave) return; let newData = cad.getData() let prevIndex = stack.getLength() - 1 // 旧版数据,先注释 // newData["vertex-xy"] = newData["vertex-xy"].concat(newData.surplus) // delete newData.surplus if (prevIndex === 0 || JSON.stringify(newData) !== JSON.stringify(stack.get(prevIndex)) ) { // stack.setLength(current + 1) stack.push(newData) ++current } }, 500) let minStep = 500 let currDate = Date.now() let timeout // 撤销 cad.previous = (): stackStatus => { if (!getRet().previous) return getRet() --current clearTimeout(timeout) timeout = setTimeout(() => { // console.log(stack.get(current)) cad.loadData(stack.get(current)) }, minStep) return getRet() } // 回退 cad.next = (): stackStatus => { if (!getRet().next) return getRet() ++current clearTimeout(timeout) timeout = setTimeout(() => { cad.loadData(stack.get(current)) }, minStep) return getRet() if (Date.now() - currDate > minStep) { currDate = Date.now() getRet().next && cad.loadData(stack.get(++current)) } return getRet() } cad.getStackState = getRet let destroy = cad.destroy cad.destroy = function (...args) { stack = null destroy.apply(this, args) } } // 附加自动保存功能 export const autoPreservation = (cad: CAD) => { [Point, Case, Door, Column, GroundCase, SlideDoor, BayCase, FurnColumn, Line, FurnFlue, wallline, DoubleDoor].forEach(cls => { let dragend = cls.prototype.dragEnd cls.prototype.dragEnd = async function (...args) { dragend && await dragend.call(this, ...args) setTimeout(() => { cad.preservation() }, 100) } let destroy = cad.destroy cad.destroy = function (...args) { destroy.apply(this, args) cls.prototype.dragEnd = dragend } }); const increase = cad.increase cad.increase = (...args) => { let ret = increase.call(cad, ...args) if (!ret.error) { setTimeout(() => { cad.preservation() }, 100) } return ret } cad.preservation() }