linearch.ts 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. import {CADElement, ElementProps} from '../core/element'
  2. import LinePoint from '../core/linepoint'
  3. import {point} from '../core/fixedpoint'
  4. import Line from '../core/wallline'
  5. import {
  6. Line as GeoLine,
  7. lineDis,
  8. isContainPoint,
  9. getDisPointLinePoints,
  10. pointLineDis,
  11. } from '../geometry'
  12. import {type} from '../util'
  13. export interface LineArchProps extends ElementProps {
  14. [k: string]: any
  15. linePoints: [point, point],
  16. attachment: Line,
  17. minWidth?: number,
  18. show?: boolean
  19. }
  20. /**
  21. * @category core
  22. * @subcategory CAD_Architecture
  23. */
  24. class LineArch extends CADElement<LineArchProps> {
  25. linePoints: [LinePoint, LinePoint]
  26. // 同一线条所有建筑归为一个数组
  27. static attaArch = new Map<Line, Array<LineArch>>()
  28. constructor({minWidth = 0.1, deleteWidth = 0.05, show = true, ...args}: LineArchProps) {
  29. super({...args, show})
  30. this.zIndex = 1
  31. this.linePoints = (this.linePoints.map(point => {
  32. let lp = new LinePoint({...point, renderer: this.renderer}, this.attachment);
  33. lp.click = () => this.changeSelect(true)
  34. return lp;
  35. })) as [LinePoint, LinePoint]
  36. this.minWidth = minWidth
  37. this.deleteWidth = deleteWidth
  38. this.real.setAttribute('class', 'variable')
  39. if (LineArch.attaArch.get(this.attachment)) {
  40. LineArch.attaArch.get(this.attachment).push(this)
  41. } else {
  42. LineArch.attaArch.set(this.attachment, [this])
  43. }
  44. this.attachment.update()
  45. }
  46. // 设置新的附属线条
  47. setAttachment(newAttachment: Line = this.attachment) {
  48. console.error('set new attach')
  49. if (this.attachment === newAttachment) return;
  50. let oldArchs = LineArch.attaArch.get(this.attachment)
  51. let newArchs = LineArch.attaArch.get(newAttachment) ||
  52. LineArch.attaArch.set(newAttachment, []).get(newAttachment);
  53. oldArchs.splice(oldArchs.indexOf(this), 1)
  54. newArchs.push(this)
  55. this.linePoints.forEach(point => {
  56. point.line = newAttachment
  57. })
  58. this.attachment = newAttachment
  59. }
  60. // 建筑端点离墙端点限制
  61. checkPointBorder(point: point, line:GeoLine = this.attachment) :boolean {
  62. // return !isContainPoint(line, point)
  63. if (lineDis({points: [line.points[0], point]}) < 0.08) {
  64. return true
  65. }
  66. if (lineDis({points: [line.points[1], point]}) < 0.08) {
  67. return true
  68. }
  69. }
  70. // 点是否在沿线上
  71. checkPoint(point: point, line:GeoLine = this.attachment) :boolean {
  72. return !isContainPoint(line, point)
  73. }
  74. // 宽度是否合格
  75. checkWidth(points: [point, point] = this.linePoints) : boolean {
  76. return lineDis({points}) < this.minWidth
  77. }
  78. // 检测同一线条所有建筑是否重叠
  79. checkPointOverlapAttaArch(archs: Array<LineArch> = LineArch.attaArch.get(this.attachment)) : boolean {
  80. if (archs.length <= 1) return false
  81. return archs.some(arch =>
  82. archs.some(carch =>
  83. arch !== carch && (
  84. isContainPoint({points: carch.linePoints}, arch.linePoints[0]) ||
  85. isContainPoint({points: carch.linePoints}, arch.linePoints[1])
  86. )
  87. )
  88. )
  89. }
  90. // 检测同一线条所有建筑是否在线上
  91. checkLineAllPoint(archs: Array<LineArch> = LineArch.attaArch.get(this.attachment), line: GeoLine = this.attachment) : boolean {
  92. return archs.length !== 0 && archs.some(arch =>
  93. !isContainPoint(line, arch.linePoints[0]) ||
  94. !isContainPoint(line, arch.linePoints[1])
  95. )
  96. }
  97. // 获取线条内所有建筑,并且替换掉指定arch的points
  98. private getLineNewAll(points: [point, point] = this.linePoints, repArch = this) {
  99. let archs = [...LineArch.attaArch.get(this.attachment)]
  100. archs.splice(archs.indexOf(repArch), 1, { linePoints: points } as unknown as LineArch)
  101. return archs
  102. }
  103. // 检测是否合格通过
  104. qualified(points: [point, point] = this.linePoints, line: GeoLine = this.attachment) {
  105. return !(
  106. this.checkPointBorder(points[0], line) ||
  107. this.checkPointBorder(points[0], line) ||
  108. this.checkPoint(points[0], line) ||
  109. this.checkPoint(points[1], line) ||
  110. this.checkWidth(points)
  111. )
  112. }
  113. // 宿主线条点变化引起变化
  114. lineChange (point = this.attachment.points[0], move: point = point) : {line: GeoLine, points: [point, point]} {
  115. let {x, y} = move
  116. let index = this.attachment.points.findIndex(item => item === point);
  117. // 获取当前变化线条
  118. let line = { points: index === 0 ?
  119. [{x, y}, this.attachment.points[1]] : [this.attachment.points[0], {x, y}]
  120. } as GeoLine;
  121. let dis1 = lineDis({points: [line.points[index], this.linePoints[0]] })
  122. let [p11, p12] = getDisPointLinePoints(line, line.points[index], dis1)
  123. let point1 = lineDis({points: [p11, this.linePoints[0]]}) > lineDis({points: [p12, this.linePoints[0]]}) ? p12 : p11
  124. let dis2 = lineDis({points: [line.points[index], this.linePoints[1]] })
  125. let [p21, p22] = getDisPointLinePoints(line, line.points[index], dis2)
  126. let point2 = lineDis({points: [p21, this.linePoints[1]]}) > lineDis({points: [p22, this.linePoints[1]]}) ? p22 : p21
  127. // 让linepoint类检查一下
  128. let points = (
  129. lineDis({points: [this.linePoints[0], point1]}) < lineDis({points: [this.linePoints[0], point2]}) ?
  130. [point1, point2] : [point2, point1]
  131. ).map(
  132. (point) => {
  133. let p = LinePoint.prototype.getLineInsertPoint.call({...this.linePoints[0], line}, point)
  134. if (pointLineDis(this.attachment, p) > 0.1) {
  135. return lineDis({points: [this.attachment.points[0], p]}) < lineDis({points: [this.attachment.points[1], p]}) ?
  136. {x: this.attachment.points[0].x, y: this.attachment.points[0].y} :
  137. {x: this.attachment.points[1].x, y: this.attachment.points[1].y}
  138. } else {
  139. return p
  140. }
  141. }
  142. ) as [point, point]
  143. return { line, points }
  144. }
  145. // 建筑沿线点变化引起变化
  146. pointChange(point, {x, y}): [point, point] {
  147. let index = this.linePoints.findIndex(p => p === point)
  148. return index === 0 ?
  149. [{x, y}, this.linePoints[1]] : [this.linePoints[0], {x, y}]
  150. }
  151. lineChangeCheck(points, line, archs) {
  152. return this.qualified(points, line) && !this.checkLineAllPoint(archs, line) && !this.checkPointOverlapAttaArch(archs)
  153. }
  154. // 当变化时
  155. intercept(trgs: Array<any>, {x, y}, rets) {
  156. if (type.isUndefined(x) || type.isUndefined(y)) return true;
  157. let seftPointIndex, linePoint
  158. // 如果是线条而引起的变化
  159. if (linePoint = this.attachment.points.find(point => trgs.some(trg => trg === point))) {
  160. let {points, line} = this.lineChange(linePoint, {x, y})
  161. // 把所有沿线建筑改为最新值
  162. let arches: Array<LineArch> = trgs
  163. .filter(trg => trg instanceof LineArch && trg.attachment.id === this.attachment.id);
  164. arches = Array.from(new Set(arches))
  165. this.attachment.nextTick(() => {
  166. if (!this.attachment || !this.attachment.points) {
  167. return this.destroy()
  168. }
  169. let {points, line} = this.lineChange(linePoint, {x: linePoint.x, y: linePoint.y})
  170. points.forEach((point, i) => {
  171. if (point) {
  172. this.linePoints[i].x = point.x
  173. this.linePoints[i].y = point.y
  174. }
  175. })
  176. this.nextTick(() => {
  177. if (this.linePoints && this.linePoints.length) {
  178. if (lineDis({points: this.linePoints}) <= this.deleteWidth) {
  179. this.destroy()
  180. }
  181. }
  182. })
  183. })
  184. this.attachment.update()
  185. // return false
  186. return {__points: points}
  187. // return true
  188. // 如果是linePoint引起的变化
  189. } else if ( ~(seftPointIndex = trgs.findIndex(trg => this.linePoints.some(p => p === trg))) ) {
  190. // let ret = rets[seftPointIndex]
  191. // let points = this.pointChange(trgs[seftPointIndex], ret)
  192. // this.attachment.update()
  193. // return true
  194. // return !(
  195. // this.checkPointBorder(ret) ||
  196. // this.checkPoint(ret) ||
  197. // this.checkWidth(points) ||
  198. // this.checkPointOverlapAttaArch(this.getLineNewAll(points))
  199. // )
  200. }
  201. }
  202. dragEnd() {
  203. this.nextTick(() => {
  204. if (lineDis({points: this.linePoints}) <= this.deleteWidth) {
  205. this.destroy()
  206. }
  207. })
  208. }
  209. destroy() {
  210. let Archs = LineArch.attaArch.get(this.attachment)
  211. if (Archs) {
  212. Archs.splice(Archs.indexOf(this), 1)
  213. console.log(this.linePoints[0], this)
  214. this.linePoints[0] && this.linePoints[0].destroy && this.linePoints[0].destroy()
  215. this.linePoints[1] && this.linePoints[1].destroy && this.linePoints[1].destroy()
  216. this.attachment = null
  217. this.linePoints = null
  218. this.update = null
  219. super.destroy()
  220. this.attachment.update()
  221. }
  222. }
  223. }
  224. type LineArchTemp<T={}> = LineArch & T
  225. export type LineArchTs = ({ new <T={}, K = any>(data: T): LineArchTemp<T> }) & {
  226. attaArch: Map<Line, Array<LineArch>>
  227. }
  228. export type LineArchClass = LineArch
  229. export default LineArch as LineArchTs