import {CADElement, ElementProps} from '../core/element' import LinePoint from '../core/linepoint' import {point} from '../core/fixedpoint' import Line from '../core/wallline' import { Line as GeoLine, lineDis, isContainPoint, getDisPointLinePoints, pointLineDis, } from '../geometry' import {type} from '../util' export interface LineArchProps extends ElementProps { [k: string]: any linePoints: [point, point], attachment: Line, minWidth?: number, show?: boolean } /** * @category core * @subcategory CAD_Architecture */ class LineArch extends CADElement { linePoints: [LinePoint, LinePoint] // 同一线条所有建筑归为一个数组 static attaArch = new Map>() constructor({minWidth = 0.1, deleteWidth = 0.05, show = true, ...args}: LineArchProps) { super({...args, show}) this.zIndex = 1 this.linePoints = (this.linePoints.map(point => { let lp = new LinePoint({...point, renderer: this.renderer}, this.attachment); lp.click = () => this.changeSelect(true) return lp; })) as [LinePoint, LinePoint] this.minWidth = minWidth this.deleteWidth = deleteWidth this.real.setAttribute('class', 'variable') if (LineArch.attaArch.get(this.attachment)) { LineArch.attaArch.get(this.attachment).push(this) } else { LineArch.attaArch.set(this.attachment, [this]) } this.attachment.update() } // 设置新的附属线条 setAttachment(newAttachment: Line = this.attachment) { console.error('set new attach') if (this.attachment === newAttachment) return; let oldArchs = LineArch.attaArch.get(this.attachment) let newArchs = LineArch.attaArch.get(newAttachment) || LineArch.attaArch.set(newAttachment, []).get(newAttachment); oldArchs.splice(oldArchs.indexOf(this), 1) newArchs.push(this) this.linePoints.forEach(point => { point.line = newAttachment }) this.attachment = newAttachment } // 建筑端点离墙端点限制 checkPointBorder(point: point, line:GeoLine = this.attachment) :boolean { // return !isContainPoint(line, point) if (lineDis({points: [line.points[0], point]}) < 0.08) { return true } if (lineDis({points: [line.points[1], point]}) < 0.08) { return true } } // 点是否在沿线上 checkPoint(point: point, line:GeoLine = this.attachment) :boolean { return !isContainPoint(line, point) } // 宽度是否合格 checkWidth(points: [point, point] = this.linePoints) : boolean { return lineDis({points}) < this.minWidth } // 检测同一线条所有建筑是否重叠 checkPointOverlapAttaArch(archs: Array = LineArch.attaArch.get(this.attachment)) : boolean { if (archs.length <= 1) return false return archs.some(arch => archs.some(carch => arch !== carch && ( isContainPoint({points: carch.linePoints}, arch.linePoints[0]) || isContainPoint({points: carch.linePoints}, arch.linePoints[1]) ) ) ) } // 检测同一线条所有建筑是否在线上 checkLineAllPoint(archs: Array = LineArch.attaArch.get(this.attachment), line: GeoLine = this.attachment) : boolean { return archs.length !== 0 && archs.some(arch => !isContainPoint(line, arch.linePoints[0]) || !isContainPoint(line, arch.linePoints[1]) ) } // 获取线条内所有建筑,并且替换掉指定arch的points private getLineNewAll(points: [point, point] = this.linePoints, repArch = this) { let archs = [...LineArch.attaArch.get(this.attachment)] archs.splice(archs.indexOf(repArch), 1, { linePoints: points } as unknown as LineArch) return archs } // 检测是否合格通过 qualified(points: [point, point] = this.linePoints, line: GeoLine = this.attachment) { return !( this.checkPointBorder(points[0], line) || this.checkPointBorder(points[0], line) || this.checkPoint(points[0], line) || this.checkPoint(points[1], line) || this.checkWidth(points) ) } // 宿主线条点变化引起变化 lineChange (point = this.attachment.points[0], move: point = point) : {line: GeoLine, points: [point, point]} { let {x, y} = move let index = this.attachment.points.findIndex(item => item === point); // 获取当前变化线条 let line = { points: index === 0 ? [{x, y}, this.attachment.points[1]] : [this.attachment.points[0], {x, y}] } as GeoLine; let dis1 = lineDis({points: [line.points[index], this.linePoints[0]] }) let [p11, p12] = getDisPointLinePoints(line, line.points[index], dis1) let point1 = lineDis({points: [p11, this.linePoints[0]]}) > lineDis({points: [p12, this.linePoints[0]]}) ? p12 : p11 let dis2 = lineDis({points: [line.points[index], this.linePoints[1]] }) let [p21, p22] = getDisPointLinePoints(line, line.points[index], dis2) let point2 = lineDis({points: [p21, this.linePoints[1]]}) > lineDis({points: [p22, this.linePoints[1]]}) ? p22 : p21 // 让linepoint类检查一下 let points = ( lineDis({points: [this.linePoints[0], point1]}) < lineDis({points: [this.linePoints[0], point2]}) ? [point1, point2] : [point2, point1] ).map( (point) => { let p = LinePoint.prototype.getLineInsertPoint.call({...this.linePoints[0], line}, point) if (pointLineDis(this.attachment, p) > 0.1) { return lineDis({points: [this.attachment.points[0], p]}) < lineDis({points: [this.attachment.points[1], p]}) ? {x: this.attachment.points[0].x, y: this.attachment.points[0].y} : {x: this.attachment.points[1].x, y: this.attachment.points[1].y} } else { return p } } ) as [point, point] return { line, points } } // 建筑沿线点变化引起变化 pointChange(point, {x, y}): [point, point] { let index = this.linePoints.findIndex(p => p === point) return index === 0 ? [{x, y}, this.linePoints[1]] : [this.linePoints[0], {x, y}] } lineChangeCheck(points, line, archs) { return this.qualified(points, line) && !this.checkLineAllPoint(archs, line) && !this.checkPointOverlapAttaArch(archs) } // 当变化时 intercept(trgs: Array, {x, y}, rets) { if (type.isUndefined(x) || type.isUndefined(y)) return true; let seftPointIndex, linePoint // 如果是线条而引起的变化 if (linePoint = this.attachment.points.find(point => trgs.some(trg => trg === point))) { let {points, line} = this.lineChange(linePoint, {x, y}) // 把所有沿线建筑改为最新值 let arches: Array = trgs .filter(trg => trg instanceof LineArch && trg.attachment.id === this.attachment.id); arches = Array.from(new Set(arches)) this.attachment.nextTick(() => { if (!this.attachment || !this.attachment.points) { return this.destroy() } let {points, line} = this.lineChange(linePoint, {x: linePoint.x, y: linePoint.y}) points.forEach((point, i) => { if (point) { this.linePoints[i].x = point.x this.linePoints[i].y = point.y } }) this.nextTick(() => { if (this.linePoints && this.linePoints.length) { if (lineDis({points: this.linePoints}) <= this.deleteWidth) { this.destroy() } } }) }) this.attachment.update() // return false return {__points: points} // return true // 如果是linePoint引起的变化 } else if ( ~(seftPointIndex = trgs.findIndex(trg => this.linePoints.some(p => p === trg))) ) { // let ret = rets[seftPointIndex] // let points = this.pointChange(trgs[seftPointIndex], ret) // this.attachment.update() // return true // return !( // this.checkPointBorder(ret) || // this.checkPoint(ret) || // this.checkWidth(points) || // this.checkPointOverlapAttaArch(this.getLineNewAll(points)) // ) } } dragEnd() { this.nextTick(() => { if (lineDis({points: this.linePoints}) <= this.deleteWidth) { this.destroy() } }) } destroy() { let Archs = LineArch.attaArch.get(this.attachment) if (Archs) { Archs.splice(Archs.indexOf(this), 1) console.log(this.linePoints[0], this) this.linePoints[0] && this.linePoints[0].destroy && this.linePoints[0].destroy() this.linePoints[1] && this.linePoints[1].destroy && this.linePoints[1].destroy() this.attachment = null this.linePoints = null this.update = null super.destroy() this.attachment.update() } } } type LineArchTemp = LineArch & T export type LineArchTs = ({ new (data: T): LineArchTemp }) & { attaArch: Map> } export type LineArchClass = LineArch export default LineArch as LineArchTs