1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147 |
- import { wallService } from '../Service/WallService'
- import { floorplanService } from '../Service/FloorplanService'
- import Constant from '../Constant'
- import { mathUtil } from '../MathUtil'
- import { elementService } from '../Service/ElementService'
- import { coordinate } from '../Coordinate'
- export default class MoveWall {
- constructor() {
- this.needUpdateRoom = false //是否重新计算房间
- this.startMoving = false
- this.moveFlag = false
- //拖拽墙角的时候,墙角的父亲与其他墙角相交
- this.adsorbPointWalls = {}
- //拖拽墙角的时候,该墙角与其他墙面相交
- this.splitWallId = null
- }
- // 测试要考虑pointId拖拽到包含他的所有墙的另一头
- // 这个函数不会删除/拆分/合并墙或者点
- movePoint(pointId, position, modifyPoint) {
- let point = floorplanService.getPoint(pointId)
- let linkedPointId = null
- let linkedWallId = null
- if (modifyPoint != null) {
- position = {
- x: modifyPoint.x,
- y: modifyPoint.y,
- }
- linkedPointId = modifyPoint.linkedPointId
- linkedWallId = modifyPoint.linkedWallId
- }
- this.needUpdateRoom = false
- this.adsorbPointWalls = {}
- this.splitWallId = null
- let flag = this.canMoveForPoint(pointId, position, linkedPointId, linkedWallId)
- if (!flag) {
- if (this.splitWallId == null && Object.keys(this.adsorbPointWalls).length > 0) {
- //要吸附一下
- const parent = point.parent
- const wall = floorplanService.getWall(Object.keys(parent)[0])
- const otherPointId = wall.getOtherPointId(pointId)
- let otherPoint = floorplanService.getPoint(otherPointId)
- let modifyPoint = floorplanService.getPoint(Object.keys(this.adsorbPointWalls)[0])
- let line = mathUtil.createLine1(otherPoint, modifyPoint)
- position = mathUtil.getJoinLinePoint(position, line)
- point.setPosition(position)
- }
- return false
- }
- let newPosition = null
- if (modifyPoint == null) {
- //90°或者180°纠正
- //不考虑当前角度
- //当前点的parent只有一个,考虑邻居点
- let neighPoints = wallService.getNeighPoints(pointId)
- if (neighPoints.length == 1) {
- newPosition = elementService.checkAngle(position, neighPoints[0].vectorId, pointId)
- }
- //当前点的parent有两个
- else if (neighPoints.length == 2) {
- newPosition = elementService.checkAngle(position, neighPoints[0].vectorId, pointId)
- if (!newPosition) {
- newPosition = elementService.checkAngle(position, neighPoints[1].vectorId, pointId)
- }
- // let angle = mathUtil.Angle(position, neighPoints[0], neighPoints[1])
- // if (Math.abs((angle / Math.PI) * 180 - 90) < 5) {
- // let line = mathUtil.createLine1(position, neighPoints[0])
- // let join = mathUtil.getJoinLinePoint(neighPoints[1], line)
- // if (join) {
- // mathUtil.clonePoint(position, join)
- // }
- // } else if (Math.abs((angle / Math.PI) * 180) < 5 || Math.abs((angle / Math.PI) * 180 - 180) < 5) {
- // let line = mathUtil.createLine1(neighPoints[0], neighPoints[1])
- // let join = mathUtil.getJoinLinePoint(position, line)
- // if (join) {
- // mathUtil.clonePoint(position, join)
- // }
- // }
- }
- if (newPosition) {
- flag = this.canMoveForPoint(pointId, newPosition, linkedPointId, linkedWallId)
- if (!flag) {
- return false
- }
- mathUtil.clonePoint(position, newPosition)
- }
- point.setPosition(position)
- }
- // 与别的墙角重合
- else if (modifyPoint.hasOwnProperty('linkedPointId') && modifyPoint.linkedPointId != null) {
- const wallId = wallService.getWallId(pointId, modifyPoint.linkedPointId)
- // pointId与linkedPointId属于同一堵墙,不允许,所以不移动
- if (wallId != null) {
- return false
- } else {
- point.setPosition(modifyPoint)
- this.needUpdateRoom = true
- }
- }
- // 与别的墙面重合
- // 如果墙面的交点与其余墙角的距离过短,那也不允许拖动
- else if (modifyPoint.hasOwnProperty('linkedWallId')) {
- const wall = floorplanService.getWall(modifyPoint.linkedWallId)
- const startPoint = floorplanService.getPoint(wall.start)
- const endPoint = floorplanService.getPoint(wall.end)
- // 与其余墙角的距离过短,不允许拖动
- if (mathUtil.getDistance(startPoint, position) < Constant.minAdsorb || mathUtil.getDistance(endPoint, position) < Constant.minAdsorb) {
- return false
- }
- point.setPosition(modifyPoint)
- this.needUpdateRoom = true
- } else {
- if (modifyPoint.hasOwnProperty('linkedPointIdX') && modifyPoint.linkedPointIdX) {
- //const linkedPointX = floorplanService.getPoint(modifyPoint.linkedPointIdX)
- //elementService.setCheckLinesX(position, linkedPointX)
- point.setPosition(position)
- }
- if (modifyPoint.hasOwnProperty('linkedPointIdY') && modifyPoint.linkedPointIdY) {
- //const linkedPointY = floorplanService.getPoint(modifyPoint.linkedPointIdY)
- //elementService.setCheckLinesY(position, linkedPointY)
- point.setPosition(position)
- }
- }
- return true
- }
- // 拖拽墙面
- moveWallPlane(wallId, dx, dy) {
- // 1表示可以继续移动,2表示不能移动(启动距离还不够),3表示wallId被删除了,4表示重新开始移动(需要达到一定距离才能启动),5表示不能移动(不合适)
- let MoveState = 1
- let wall = floorplanService.getWall(wallId)
- let startPointId = wall.start
- let endPointId = wall.end
- let startPoint = floorplanService.getPoint(wall.start)
- let endPoint = floorplanService.getPoint(wall.end)
- // 不考虑约束的情况,得到移动后的坐标
- const newpts = this.getNewPointsForMoveWall(wallId, dx, dy)
- let newLine = mathUtil.createLine1(newpts.point1, newpts.point2)
- // 获取约束信息,包括:是否新建墙,受约束的侧墙
- const limit = this.getTwoLimitInfos(wallId, newLine)
- this.needUpdateRoom = false
- // 不考虑吸附的情况下,经过约束条件后,得到的新的移动后的坐标
- let virtualStartPoint = mathUtil.getIntersectionPoint(newLine, limit.startLimitLine)
- let virtualEndPoint = mathUtil.getIntersectionPoint(newLine, limit.endLimitLine)
- // 刚刚开始移动的时候,或者吸附后再移动的时候,都需要积累一点移动距离才能真正开始移动
- if (!this.startMoving && (mathUtil.getDistance(startPoint, virtualStartPoint) < Constant.minAdsorb || mathUtil.getDistance(endPoint, virtualEndPoint) < Constant.minAdsorb)) {
- this.moveFlag = false
- MoveState = 2
- return MoveState
- }
- this.startMoving = true
- // 判断是否会吸附到邻居墙的另一头端点,同时确保新的坐标在邻居墙内
- let startInfo = this.updateVirtualPosition(wall.start, virtualStartPoint, limit.startWallId, limit.newStartWallId)
- let endInfo = this.updateVirtualPosition(wall.end, virtualEndPoint, limit.endWallId, limit.newEndWallId)
- if (startInfo == null || endInfo == null) {
- this.moveFlag = false
- MoveState = 2
- this.startMoving = false
- return MoveState
- }
- // 判断wallId的 1端/2端 吸附后,是否和别的墙重合
- let coincideFlag = false
- // wallId的长度,可能会很短,要删除
- let distance = null
- // 如果一头被吸附,另一头的坐标还要再次调整
- if (startInfo.adsorb && !endInfo.adsorb) {
- // 先更新newLine
- newLine = mathUtil.createLine3(newLine, startInfo.virtualPosition)
- // 需要判断夹角,如果接近0,则不能移动
- const flag = this.isOKForTwoSegmentsAngle(startInfo.adsorbPointId, wall.start, wall.end)
- if (!flag) {
- this.moveFlag = false
- MoveState = 5
- return MoveState
- }
- // 更新virtualEndPoint
- virtualEndPoint = mathUtil.getIntersectionPoint(newLine, limit.endLimitLine)
- // 再次判断是否吸附
- endInfo = this.updateVirtualPosition(wall.end, virtualEndPoint, limit.endWallId, limit.newEndWallId)
- if (endInfo == null) {
- endInfo = {
- adsorb: false,
- adsorbPointId: null,
- virtualPosition: virtualEndPoint,
- }
- }
- // 一头吸附后,wallId可能和别的墙重合
- coincideFlag = this.isCoincideForAdsorbOne(wall.start, startInfo.adsorbPointId, wallId)
- distance = mathUtil.getDistance(startInfo.virtualPosition, virtualEndPoint)
- MoveState = 4
- this.needUpdateRoom = true
- this.startMoving = false
- } else if (!startInfo.adsorb && endInfo.adsorb) {
- newLine = mathUtil.createLine3(newLine, endInfo.virtualPosition)
- // 需要判断夹角,如果接近0,则不能移动
- const flag = this.isOKForTwoSegmentsAngle(endInfo.adsorbPointId, wall.end, wall.start)
- if (!flag) {
- this.moveFlag = false
- MoveState = 5
- return MoveState
- }
- virtualStartPoint = mathUtil.getIntersectionPoint(newLine, limit.startLimitLine)
- startInfo = this.updateVirtualPosition(wall.start, virtualStartPoint, limit.startWallId, limit.newStartWallId)
- if (startInfo == null) {
- startInfo = {
- adsorb: false,
- adsorbPointId: null,
- virtualPosition: virtualStartPoint,
- }
- }
- coincideFlag = this.isCoincideForAdsorbOne(wall.end, endInfo.adsorbPointId, wallId)
- distance = mathUtil.getDistance(endInfo.virtualPosition, virtualStartPoint)
- MoveState = 4
- this.needUpdateRoom = true
- this.startMoving = false
- }
- // 两头同时吸附呢,wallId可能和别的墙重合
- if (startInfo && endInfo && startInfo.adsorb && endInfo.adsorb) {
- coincideFlag = this.isCoincideForAdsorbOne2(wallId, startInfo.adsorbPointId, endInfo.adsorbPointId)
- distance = mathUtil.getDistance(startInfo.virtualPosition, endInfo.virtualPosition)
- this.startMoving = false
- if (coincideFlag) {
- this.moveFlag = false
- MoveState = 5
- return MoveState
- }
- MoveState = 4
- this.needUpdateRoom = true
- } else {
- distance = mathUtil.getDistance(virtualStartPoint, virtualEndPoint)
- if (distance < Constant.minAdsorb) {
- // 执行deleteWallForLinked后start和end会变,所以提前保存
- this.deleteWallForLinked(wallId)
- startPoint = floorplanService.getPoint(startPointId)
- endPoint = floorplanService.getPoint(endPointId)
- if (!startPoint || !endPoint) {
- this.moveFlag = false
- MoveState = 3
- this.needUpdateRoom = true
- return MoveState
- }
- if (
- (Object.keys(startPoint.parent).length > 1 && Object.keys(endPoint.parent).length == 1) ||
- (Object.keys(startPoint.parent).length == 1 && Object.keys(endPoint.parent).length == 1)
- ) {
- wallService.moveTo(endPointId, startPointId)
- } else if (Object.keys(startPoint.parent).length == 1 && Object.keys(endPoint.parent).length > 1) {
- wallService.moveTo(startPointId, endPointId)
- }
- this.moveFlag = false
- MoveState = 3
- this.needUpdateRoom = true
- return MoveState
- }
- }
- startPointId = wall.start
- endPointId = wall.end
- // 是否交叉
- const crossFlag = this.isOKForCrossForMoveWall(virtualStartPoint, virtualEndPoint, wallId, startPointId, endPointId, startInfo.adsorbPointId, endInfo.adsorbPointId)
- // ok
- if (!crossFlag) {
- MoveState = 2
- this.moveFlag = false
- this.startMoving = false
- return MoveState
- }
- // 要删除墙了
- if (coincideFlag || (distance != null && distance < Constant.minAdsorb)) {
- this.deleteWallForLinked(wallId)
- MoveState = 3
- // 删除完墙,邻居墙可能会合并
- wallService.mergeWallForPoint(startPointId)
- wallService.mergeWallForPoint(endPointId)
- this.moveFlag = false
- this.needUpdateRoom = true
- return MoveState
- } else {
- // 要删除墙了
- const join = mathUtil.getIntersectionPoint3(startPoint, virtualStartPoint, endPoint, virtualEndPoint)
- if (join != null) {
- startPoint.setPosition(join)
- endPoint.setPosition(join)
- wallService.moveTo(startPointId, endPointId)
- MoveState = 3
- this.moveFlag = false
- this.needUpdateRoom = true
- return MoveState
- }
- }
- let overlapFlag = false
- if (!limit.newStartWallId && startInfo.adsorbPointId) {
- overlapFlag = wallService.isOverlapForMergePoint(startPointId, startInfo.adsorbPointId)
- } else if (!limit.newEndWallId && endInfo.adsorbPointId) {
- overlapFlag = wallService.isOverlapForMergePoint(endPointId, endInfo.adsorbPointId)
- }
- if (overlapFlag) {
- this.moveFlag = false
- MoveState = 5
- return MoveState
- }
- // 到了这一步,端点的新坐标已经确定了,这里开始更新端点坐标
- // 这里需要升级优化,因为 updatePointForMoveWall方法里也更新了edge,这个其实不需要的。
- this.updatePointForMoveWall(wallId, startPointId, startInfo, limit.startWallId, limit.newStartWallId)
- this.updatePointForMoveWall(wallId, endPointId, endInfo, limit.endWallId, limit.newEndWallId)
- wall = floorplanService.getWall(wallId)
- if (wall == null) {
- MoveState = 3
- this.moveFlag = false
- this.needUpdateRoom = true
- // console.log(271)
- return MoveState
- }
- if (MoveState == 1) {
- this.moveFlag = true
- } else {
- this.moveFlag = false
- }
- return MoveState
- }
- //拖拽墙角/墙面,被其他墙角吸附
- updateForAbsorbWallPoints() {
- if (Object.keys(this.adsorbPointWalls).length == 0) {
- return
- } else if (Object.keys(this.adsorbPointWalls).length == 2) {
- debugger
- }
- let joins = []
- let wallId = null
- for (let key in this.adsorbPointWalls) {
- let point = floorplanService.getPoint(key)
- joins.push({
- join: point,
- pointId: key,
- })
- wallId = this.adsorbPointWalls[key]
- }
- const wall = floorplanService.getWall(wallId)
- const startPoint = floorplanService.getPoint(wall.start)
- function sortNumber(a, b) {
- return mathUtil.getDistance(startPoint, a.join) - mathUtil.getDistance(startPoint, b.join)
- }
- joins = joins.sort(sortNumber.bind(this))
- for (let i = 0; i < joins.length; ++i) {
- const info = joins[i]
- const join = info.join
- const pointId = info.pointId
- wallService.splitWall(wallId, pointId, 'end')
- }
- }
- getNewPointsForMoveWall(wallId, dx, dy) {
- dx = dx / coordinate.res * Constant.defaultZoom/coordinate.zoom
- dy = -dy / coordinate.res * Constant.defaultZoom/coordinate.zoom
- const wall = floorplanService.getWall(wallId)
- const startPoint = floorplanService.getPoint(wall.start)
- const endPoint = floorplanService.getPoint(wall.end)
- const p1 = { x: startPoint.x + dx, y: startPoint.y + dy }
- const p2 = { x: endPoint.x + dx, y: endPoint.y + dy }
- return {
- point1: p1,
- point2: p2,
- }
- }
- getTwoLimitInfos(wallId, newLine) {
- const wall = floorplanService.getWall(wallId)
- const startPoint = floorplanService.getPoint(wall.start)
- const endPoint = floorplanService.getPoint(wall.end)
- let startLimitLine, endLimitLine, info
- const wallLine = mathUtil.createLine1(startPoint, endPoint)
- const limitInfos = {}
- limitInfos.newStartWallId = false // 不需要新建墙
- limitInfos.newEndWallId = false // 不需要新建墙
- // 先处理start
- if (Object.keys(startPoint.parent).length == 1) {
- startLimitLine = mathUtil.getVerticalLine(wallLine, startPoint)
- limitInfos.startWallId = null
- } else if (Object.keys(startPoint.parent).length == 2) {
- let tempWall
- if (Object.keys(startPoint.parent)[0] == wallId) {
- tempWall = floorplanService.getWall(Object.keys(startPoint.parent)[1])
- } else if (Object.keys(startPoint.parent)[1] == wallId) {
- tempWall = floorplanService.getWall(Object.keys(startPoint.parent)[0])
- }
- if (!tempWall) {
- console.error(352)
- }
- const angle = wallService.AngleForWall(tempWall.vectorId, wallId)
- startLimitLine = wallService.getLine(tempWall)
- limitInfos.startWallId = tempWall.vectorId
- if (angle > (Constant.maxAngle / 180) * Math.PI) {
- startLimitLine = mathUtil.getVerticalLine(wallLine, startPoint)
- limitInfos.startWallId = null
- limitInfos.newStartWallId = true
- }
- } else {
- let tempWall, tempWallId
- info = wallService.wallIdForMinAngle(wall.start, wallId)
- const wall1 = floorplanService.getWall(info.min0.wallId)
- const startPoint1 = floorplanService.getPoint(wall1.start)
- const endPoint1 = floorplanService.getPoint(wall1.end)
- const wall2 = floorplanService.getWall(info.min1.wallId)
- const startPoint2 = floorplanService.getPoint(wall2.start)
- const endPoint2 = floorplanService.getPoint(wall2.end)
- const join1 = mathUtil.getIntersectionPoint4(startPoint1, endPoint1, newLine)
- const join2 = mathUtil.getIntersectionPoint4(startPoint2, endPoint2, newLine)
- // 取角度大的
- if (join1 == null && join2 == null) {
- let angle0 = wallService.AngleForWall(wallId, info.min0.wallId)
- let angle1 = wallService.AngleForWall(wallId, info.min1.wallId)
- if (angle0 > Math.PI) {
- angle0 = Math.PI - angle0
- }
- if (angle1 > Math.PI) {
- angle1 = Math.PI - angle1
- }
- if (angle0 < angle1) {
- tempWallId = info.min0.wallId
- } else {
- tempWallId = info.min1.wallId
- }
- limitInfos.newStartWallId = true
- }
- // 取角度小的
- else if (join1 != null && join2 != null) {
- if (info.min0.angle < info.min1.angle) {
- tempWallId = info.min0.wallId
- } else {
- tempWallId = info.min1.wallId
- }
- } else if (join1 == null && join2 != null) {
- tempWallId = info.min1.wallId
- } else if (join1 != null && join2 == null) {
- tempWallId = info.min0.wallId
- }
- limitInfos.startWallId = tempWallId
- tempWall = floorplanService.getWall(tempWallId)
- const angle = wallService.AngleForWall(tempWallId, wallId)
- startLimitLine = wallService.getLine(tempWall)
- if (angle > (Constant.maxAngle / 180) * Math.PI) {
- startLimitLine = mathUtil.getVerticalLine(wallLine, startPoint)
- limitInfos.startWallId = null
- limitInfos.newStartWallId = true
- }
- }
- // 再处理end
- if (Object.keys(endPoint.parent).length == 1) {
- endLimitLine = mathUtil.getVerticalLine(wallLine, endPoint)
- limitInfos.endWallId = null
- } else if (Object.keys(endPoint.parent).length == 2) {
- let tempWall
- if (Object.keys(endPoint.parent)[0] == wallId) {
- tempWall = floorplanService.getWall(Object.keys(endPoint.parent)[1])
- } else if (Object.keys(endPoint.parent)[1] == wallId) {
- tempWall = floorplanService.getWall(Object.keys(endPoint.parent)[0])
- }
- const angle = wallService.AngleForWall(tempWall.vectorId, wallId)
- endLimitLine = wallService.getLine(tempWall)
- limitInfos.endWallId = tempWall.vectorId
- if (angle > (Constant.maxAngle / 180) * Math.PI) {
- endLimitLine = mathUtil.getVerticalLine(wallLine, endPoint)
- limitInfos.endWallId = null
- limitInfos.newEndWallId = true
- }
- } else {
- let tempWall, tempWallId
- info = wallService.wallIdForMinAngle(wall.end, wallId)
- const wall1 = floorplanService.getWall(info.min0.wallId)
- const startPoint1 = floorplanService.getPoint(wall1.start)
- const endPoint1 = floorplanService.getPoint(wall1.end)
- const wall2 = floorplanService.getWall(info.min1.wallId)
- const startPoint2 = floorplanService.getPoint(wall2.start)
- const endPoint2 = floorplanService.getPoint(wall2.end)
- const join1 = mathUtil.getIntersectionPoint4(startPoint1, endPoint1, newLine)
- const join2 = mathUtil.getIntersectionPoint4(startPoint2, endPoint2, newLine)
- // 取角度大的
- if (join1 == null && join2 == null) {
- let angle0 = wallService.AngleForWall(wallId, info.min0.wallId)
- let angle1 = wallService.AngleForWall(wallId, info.min1.wallId)
- if (angle0 > Math.PI) {
- angle0 = Math.PI - angle0
- }
- if (angle1 > Math.PI) {
- angle1 = Math.PI - angle1
- }
- if (angle0 < angle1) {
- tempWallId = info.min0.wallId
- } else {
- tempWallId = info.min1.wallId
- }
- limitInfos.newEndWallId = true
- }
- // 取角度小的
- else if (join1 != null && join2 != null) {
- if (info.min0.angle < info.min1.angle) {
- tempWallId = info.min0.wallId
- } else {
- tempWallId = info.min1.wallId
- }
- } else if (join1 == null && join2 != null) {
- tempWallId = info.min1.wallId
- } else if (join1 != null && join2 == null) {
- tempWallId = info.min0.wallId
- }
- limitInfos.endWallId = tempWallId
- tempWall = floorplanService.getWall(tempWallId)
- const angle = wallService.AngleForWall(tempWallId, wallId)
- endLimitLine = wallService.getLine(tempWall)
- if (angle > (Constant.maxAngle / 180) * Math.PI) {
- endLimitLine = mathUtil.getVerticalLine(wallLine, endPoint)
- limitInfos.endWallId = null
- limitInfos.newEndWallId = true
- }
- }
- limitInfos.startLimitLine = startLimitLine
- limitInfos.endLimitLine = endLimitLine
- return limitInfos
- }
- // 是否可以移动point
- // 两个判断:拖拽的墙(可能是多个),一方面不能与其他墙相交,另一方面这些墙之间或者与别的墙之间的角度必须大于Constant.minAngle
- canMoveForPoint(pointId, position, linkedPointId, linkedWallId) {
- const point = floorplanService.getPoint(pointId)
- // 先判断第二点(这些墙之间或者与别的墙之间的角度必须大于MinAngle)
- let flag = this.isOKForMinAngleWall(pointId, position)
- // 开始考虑第一点
- if (flag) {
- // 不仅仅角度,还有相交
- flag = this.isOKForCross(pointId, position, point.parent, linkedPointId, linkedWallId)
- }
- return flag
- }
- isOKForMinAngleWall(pointId, position) {
- const point = floorplanService.getPoint(pointId)
- const parent = point.parent
- const angle = this.getMinAngle(pointId, position)
- if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
- return false
- }
- // 判断邻居点
- for (const key in parent) {
- const wall = floorplanService.getWall(key)
- const otherPointId = wall.getOtherPointId(pointId)
- const info = this.getNeighMinAngle(otherPointId, key, position)
- if (info && Math.abs(info.angle) < (Constant.minAngle / 180) * Math.PI) {
- return false
- } else {
- const otherPoint = floorplanService.getPoint(otherPointId)
- if (mathUtil.getDistance(position, otherPoint) < Constant.minAdsorb) {
- return false
- }
- }
- }
- return true
- }
- //点pointId移动到position后,求出最小角度
- getMinAngle(pointId, position) {
- const point = floorplanService.getPoint(pointId)
- const parent = point.parent
- let angle = null
- if (Object.keys(parent).length == 1) {
- return 2 * Math.PI
- } else if (Object.keys(parent).length == 2) {
- const wall1 = floorplanService.getWall(Object.keys(parent)[0])
- const wall2 = floorplanService.getWall(Object.keys(parent)[1])
- const otherPointId1 = wall1.getOtherPointId(pointId)
- const otherPoint1 = floorplanService.getPoint(otherPointId1)
- const otherPointId2 = wall2.getOtherPointId(pointId)
- const otherPoint2 = floorplanService.getPoint(otherPointId2)
- angle = mathUtil.Angle(position, otherPoint1, otherPoint2)
- return angle
- } else {
- const _position = {
- x: position.x + 1,
- y: position.y,
- }
- let angles = []
- for (const key in parent) {
- const wall = floorplanService.getWall(key)
- const otherPointId = wall.getOtherPointId(pointId)
- const otherPoint = floorplanService.getPoint(otherPointId)
- if (mathUtil.equalPoint(_position, otherPoint)) {
- angles.push(0)
- continue
- } else {
- let angle = mathUtil.Angle(position, _position, otherPoint)
- // 统一按照逆时针顺序
- if (otherPoint.y < position.y) {
- angle = 2 * Math.PI - angle
- }
- angles.push(angle)
- }
- }
- angles = angles.sort(sortNumber)
- let minAngle = 2 * Math.PI
- for (let i = 0; i < angles.length - 1; ++i) {
- for (let j = i + 1; j < angles.length; ++j) {
- const _angle = angles[j] - angles[i]
- if (_angle < minAngle) {
- minAngle = _angle
- }
- }
- }
- const angle1 = angles[0]
- const angle2 = angles[angles.length - 1]
- if (angle1 < Math.PI && angle2 > Math.PI) {
- const dAngle = 2 * Math.PI + angle1 - angle2
- if (dAngle < minAngle) {
- minAngle = dAngle
- }
- }
- return minAngle
- }
- function sortNumber(a, b) {
- return a - b
- }
- }
- // 用于邻居点
- // pointId是顶点
- // position是wallId相对于pointId另一头的点的坐标,一般发生改变的时候使用这个函数
- getNeighMinAngle(otherPointId, wallId, position) {
- const point1 = floorplanService.getPoint(otherPointId)
- const point2 = {
- x: position.x,
- y: position.y,
- }
- let pointId3 = null
- let point3 = null
- let minAngle = null
- let result = null
- for (const key in point1.parent) {
- if (key == wallId) {
- continue
- }
- const wall = floorplanService.getWall(key)
- pointId3 = wall.getOtherPointId(otherPointId)
- point3 = floorplanService.getPoint(pointId3)
- const angle = mathUtil.Angle(point1, point2, point3)
- if (minAngle == null || minAngle > angle) {
- minAngle = angle
- result = {
- angle: minAngle,
- pointId: pointId3,
- }
- }
- }
- return result
- }
- // linkedPointId,linkedWallId表示吸附
- // wallIds是pointId的parent
- isOKForCross(pointId, position, wallIds, linkedPointId, linkedWallId) {
- const walls = floorplanService.getWalls()
- for (const key in walls) {
- if (wallIds.hasOwnProperty(key)) {
- continue
- } else if (linkedWallId == key) {
- continue
- }
- for (const _key in wallIds) {
- //相连就不用考虑了
- if (wallService.isWallLink(key, _key)) {
- continue
- }
- const _wall = floorplanService.getWall(_key)
- const otherPointId = _wall.getOtherPointId(pointId)
- const otherPoint = floorplanService.getPoint(otherPointId)
- const flag = this.isOKForCrossTwoWall(position, otherPoint, key, linkedPointId, linkedWallId, _wall.vectorId)
- // 交叉
- if (!flag) {
- this.adsorbPointWalls = {}
- return false
- }
- }
- }
- //需要吸附了。
- if (Object.keys(this.adsorbPointWalls).length > 0) {
- return false
- } else if (this.splitWallId != null) {
- return false
- }
- // 不交叉
- return true
- }
- // position1表示拖拽的点的坐标(修复过了的)
- // position2对应墙的另一头坐标
- // wallId表示其余的墙(与position1无关的墙)
- isOKForCrossTwoWall(position1, position2, wallId, linkedPointId, linkedWallId, dragWallId) {
- const wall = floorplanService.getWall(wallId)
- const startPoint = floorplanService.getPoint(wall.start)
- const endPoint = floorplanService.getPoint(wall.end)
- const join = mathUtil.getIntersectionPoint3(position1, position2, startPoint, endPoint)
- if (join && wall.start != linkedPointId && wall.end != linkedPointId) {
- // 交叉了
- this.splitWallId = wallId
- return true
- } else {
- if (mathUtil.equalPoint(position1, position2)) {
- return true
- }
- let line = mathUtil.createLine1(position1, position2)
- let join1 = mathUtil.getJoinLinePoint(startPoint, line)
- let join2 = mathUtil.getJoinLinePoint(endPoint, line)
- if (mathUtil.getDistance(join1, startPoint) < Constant.minAdsorb && mathUtil.PointInSegment(join1, position1, position2)) {
- if (wall.start != linkedPointId) {
- // 交叉了
- this.adsorbPointWalls[startPoint.vectorId] = dragWallId
- //为了找到全部的吸附点,暂时返回true,在外面一层再做判断
- return true
- }
- } else if (mathUtil.getDistance(join2, endPoint) < Constant.minAdsorb && mathUtil.PointInSegment(join2, position1, position2)) {
- if (wall.end != linkedPointId) {
- // 交叉了
- this.adsorbPointWalls[endPoint.vectorId] = dragWallId
- //为了找到全部的吸附点,暂时返回true,在外面一层再做判断
- return true
- }
- }
- line = mathUtil.createLine1(startPoint, endPoint)
- join1 = mathUtil.getJoinLinePoint(position1, line)
- join2 = mathUtil.getJoinLinePoint(position2, line)
- if (mathUtil.getDistance(join1, position1) < Constant.minAdsorb && mathUtil.PointInSegment(join1, startPoint, endPoint)) {
- if (wall.start != linkedPointId && wall.end != linkedPointId && wallId != linkedWallId) {
- // 交叉了
- //return false
- return true
- }
- } else if (mathUtil.getDistance(join2, position2) < Constant.minAdsorb && mathUtil.PointInSegment(join2, startPoint, endPoint)) {
- if (wall.start != linkedPointId && wall.end != linkedPointId && wallId != linkedWallId) {
- // 交叉了
- //return false
- return true
- }
- }
- }
- return true
- }
- isOKForCrossTwoWall2(position1, position2, wallId) {
- const wall = floorplanService.getWall(wallId)
- const startPoint = floorplanService.getPoint(wall.start)
- const endPoint = floorplanService.getPoint(wall.end)
- let flag = mathUtil.crossTwoLines(position1, position2, startPoint, endPoint, 0.01)
- if (flag) {
- // 交叉了
- return false
- } else {
- if (mathUtil.equalPoint(position1, position2)) {
- return true
- }
- flag = this.isCoincide(position1, position2, wallId)
- if (!flag) {
- return false
- }
- }
- return true
- }
- isOKForCrossTwoWall3(position1, position2, wallId) {
- const wall = floorplanService.getWall(wallId)
- const startPoint = floorplanService.getPoint(wall.start)
- const endPoint = floorplanService.getPoint(wall.end)
- const flag = mathUtil.crossTwoLines(position1, position2, startPoint, endPoint, 0.01)
- if (flag) {
- // 交叉了
- return false
- } else {
- if (mathUtil.equalPoint(position1, position2)) {
- return true
- }
- let line = mathUtil.createLine1(position1, position2)
- let join1 = mathUtil.getJoinLinePoint(startPoint, line)
- const join2 = mathUtil.getJoinLinePoint(endPoint, line)
- if (mathUtil.getDistance(join1, startPoint) < Constant.minAdsorb && mathUtil.PointInSegment(join1, position1, position2)) {
- // 交叉了
- return false
- } else if (mathUtil.getDistance(join2, endPoint) < Constant.minAdsorb && mathUtil.PointInSegment(join2, position1, position2)) {
- // 交叉了
- return false
- }
- line = mathUtil.createLine1(startPoint, endPoint)
- join1 = mathUtil.getJoinLinePoint(position1, line)
- if (mathUtil.getDistance(join1, position1) < Constant.minAdsorb && wallService.isContain(wall, join1)) {
- // 交叉了
- return false
- }
- }
- return true
- }
- isCoincide(position1, position2, wallId) {
- const wall = floorplanService.getWall(wallId)
- const startPoint = floorplanService.getPoint(wall.start)
- const endPoint = floorplanService.getPoint(wall.end)
- let line = mathUtil.createLine1(position1, position2)
- let join1 = mathUtil.getJoinLinePoint(startPoint, line)
- let join2 = mathUtil.getJoinLinePoint(endPoint, line)
- if (mathUtil.getDistance(join1, startPoint) < Constant.minAdsorb && mathUtil.PointInSegment(join1, position1, position2)) {
- // 交叉了
- return false
- } else if (mathUtil.getDistance(join2, endPoint) < Constant.minAdsorb && mathUtil.PointInSegment(join2, position1, position2)) {
- // 交叉了
- return false
- }
- line = mathUtil.createLine1(startPoint, endPoint)
- join1 = mathUtil.getJoinLinePoint(position1, line)
- join2 = mathUtil.getJoinLinePoint(position2, line)
- if (mathUtil.getDistance(join1, position1) < Constant.minAdsorb && wallService.isContain(wall, join1)) {
- // 交叉了
- return false
- } else if (mathUtil.getDistance(join2, position2) < Constant.minAdsorb && wallService.isContain(wall, join2)) {
- // 交叉了
- return false
- }
- return true
- }
- // 更新virtualPosition(一般是吸附)
- updateVirtualPosition(pointId, virtualPosition, limitWallId, needNew) {
- const limitWall = floorplanService.getWall(limitWallId)
- const point = floorplanService.getPoint(pointId)
- let otherPointId, otherPoint
- let adsorb = false
- // 不需要新建墙
- if (!needNew) {
- if (limitWall != null) {
- otherPointId = limitWall.getOtherPointId(pointId)
- otherPoint = floorplanService.getPoint(otherPointId)
- // 会吸附另一头
- if (
- mathUtil.getDistance(virtualPosition, otherPoint) < Constant.minAdsorb ||
- (!wallService.isContain(limitWall, virtualPosition) && mathUtil.getDistance(virtualPosition, otherPoint) < mathUtil.getDistance(virtualPosition, point))
- ) {
- mathUtil.clonePoint(virtualPosition, otherPoint)
- adsorb = true
- }
- }
- }
- // 需要新建墙
- else {
- // 新建的墙太短,不允许
- if (mathUtil.getDistance(point, virtualPosition) < Constant.minAdsorb) {
- return null
- }
- }
- return {
- adsorb: adsorb,
- adsorbPointId: adsorb ? otherPointId : null,
- virtualPosition: virtualPosition,
- }
- }
- // 两条线段的夹角,这两条线段分别有一个端点挨的很近
- isOKForTwoSegmentsAngle(pointId, pointId1, pointId2) {
- const point = floorplanService.getPoint(pointId)
- const point1 = floorplanService.getPoint(pointId1)
- const point2 = floorplanService.getPoint(pointId2)
- const dx = point.x - point1.x
- const dy = point.y - point1.y
- const newPoint2 = {
- x: dx + point2.x,
- y: dy + point2.y,
- }
- for (const key in point.parent) {
- const wall = floorplanService.getWall(key)
- const otherPointId = wall.getOtherPointId(pointId)
- const otherPoint = floorplanService.getPoint(otherPointId)
- const angle = mathUtil.Angle(point, otherPoint, newPoint2)
- if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
- return false
- }
- }
- return true
- }
- // 一头吸附后,是否会重合
- // pointId属于wallId,当pointId吸附到adsorbPointId时
- isCoincideForAdsorbOne(pointId, adsorbPointId, wallId) {
- if (pointId && adsorbPointId) {
- const wall = floorplanService.getWall(wallId)
- const otherPointId = wall.getOtherPointId(pointId)
- const _wallId = wallService.getWallId(otherPointId, adsorbPointId)
- if (_wallId != null) {
- return true
- }
- }
- return false
- }
- isCoincideForAdsorbOne2(wallId, adsorbPointId1, adsorbPointId2) {
- if (adsorbPointId1 && adsorbPointId2) {
- const _wallId = wallService.getWallId(adsorbPointId1, adsorbPointId2)
- if (_wallId != null) {
- return true
- }
- // 可能吸附的是两堵墙,但是这两堵墙呈180°
- else {
- let adsorbPoint = floorplanService.getPoint(adsorbPointId1)
- let parent = adsorbPoint.parent
- for (const key in parent) {
- const angle = wallService.AngleForWall3(wallId, key)
- if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
- return true
- }
- }
- adsorbPoint = floorplanService.getPoint(adsorbPointId2)
- parent = adsorbPoint.parent
- for (const key in parent) {
- const angle = wallService.AngleForWall3(wallId, key)
- if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
- return true
- }
- }
- }
- }
- return false
- }
- // position1和position2表示wall的两个端点坐标(下一步的)
- // position3和position4表示wall的start一边的线段(startPoint——virtualStartPoint)
- // position5和position6表示wall的end一边的线段(endPoint——virtualEndPoint)
- // adsorbPointId1对应start那一头的吸附点
- // adsorbPointId2对应end那一头的吸附点
- isOKForCrossForMoveWall(position1, position2, wallId, startPointId, endPointId, adsorbPointId1, adsorbPointId2) {
- const startPoint = floorplanService.getPoint(startPointId)
- const endPoint = floorplanService.getPoint(endPointId)
- let flag = true
- const walls = floorplanService.getWalls()
- for (const key in walls) {
- if (key == wallId) {
- continue
- }
- let flag1 = true
- let flag2 = true
- const _wall = floorplanService.getWall(key)
- if (adsorbPointId1 && (adsorbPointId1 == _wall.start || adsorbPointId1 == _wall.end)) {
- flag1 = false
- }
- if (adsorbPointId2 && (adsorbPointId2 == _wall.start || adsorbPointId2 == _wall.end)) {
- flag2 = false
- }
- if (_wall.start == startPointId || _wall.end == startPointId) {
- flag1 = false
- }
- if (_wall.start == endPointId || _wall.end == endPointId) {
- flag2 = false
- }
- // 两头不连
- if (flag1 && flag2) {
- flag = this.isOKForCrossTwoWall2(position1, position2, key)
- }
- if (!flag) {
- return false
- }
- if (flag1 && _wall.start != startPointId && _wall.end != startPointId) {
- flag = this.isOKForCrossTwoWall3(position1, startPoint, key)
- }
- if (!flag) {
- return false
- }
- if (flag2 && _wall.start != endPointId && _wall.end != endPointId) {
- flag = this.isOKForCrossTwoWall3(position2, endPoint, key)
- }
- if (!flag) {
- return false
- }
- }
- return flag
- }
- // 更新pointId的坐标
- updatePointForMoveWall(wallId, pointId, virtualInfo, limitWallId, needNew) {
- const point = floorplanService.getPoint(pointId)
- const wall = floorplanService.getWall(wallId)
- // 如果没有约束墙,只有两种情况:一种是不新建墙,另一种是需要新建墙
- if (limitWallId == null) {
- // 不需要新建墙,这种情况一般是pointId的parent只有一个
- if (!needNew) {
- point.setPosition(virtualInfo.virtualPosition)
- }
- // 新建墙
- else {
- this.createWallForMoveWall(pointId, wallId, virtualInfo.virtualPosition)
- this.needUpdateRoom = true
- }
- } else {
- /*
- 不新建墙:
- 1. 更新坐标(一种是当pointId的parent是2个,另一种是三个,但是wallId对应的两堵墙接近180°)
- 2. 拆分墙
- 3. 吸附邻居墙的另一个端点
- 新建墙:
- */
- // 不新建墙
- if (!needNew) {
- if (!virtualInfo.adsorb) {
- // 只更新坐标
- if (Object.keys(point.parent).length == 2) {
- point.setPosition(virtualInfo.virtualPosition)
- } else {
- const info = wallService.wallIdForMinAngle(pointId, wallId)
- const angle = wallService.AngleForWall(info.min0.wallId, info.min1.wallId)
- // 只更新坐标
- if (Object.keys(point.parent).length == 3 && angle > (Constant.maxAngle / 180) * Math.PI) {
- point.setPosition(virtualInfo.virtualPosition)
- }
- // 拆分墙
- else {
- const dir = wallService.getDirction(pointId, wallId)
- // 先断开链接
- wallService.subtraWallFromIntersect(pointId, wallId)
- const newPointId = wall.getPointId(dir)
- const newPoint = floorplanService.getPoint(newPointId)
- // 更新新坐标
- newPoint.setPosition(virtualInfo.virtualPosition)
- // 拆分
- wallService.splitWall(limitWallId, newPointId, dir)
- this.needUpdateRoom = true
- }
- }
- }
- // 吸附邻居墙的另一个端点。
- else {
- wallService.moveTo(pointId, virtualInfo.adsorbPointId)
- this.needUpdateRoom = true
- }
- }
- // 新建墙
- else {
- this.createWallForMoveWall(pointId, wallId, virtualInfo.virtualPosition)
- this.needUpdateRoom = true
- }
- }
- }
- //
- createWallForMoveWall(pointId, wallId, newPosition) {
- const wall = floorplanService.getWall(wallId)
- const dir = wallService.getDirction(pointId, wallId)
- // 第一步是断开连接
- wallService.subtraWallFromIntersect(pointId, wallId)
- // 第二步更新端点坐标
- const newPointId = wall.getPointId(dir)
- const newPoint = floorplanService.getPoint(newPointId)
- newPoint.setPosition(newPosition)
- // 第三步先新建墙
- wallService.createWall(pointId, newPointId)
- // 还缺少wall和newWall相交,这需要等另一头的point完成后最后处理
- }
- deleteWallForLinked(wallId) {
- const wall = floorplanService.getWall(wallId)
- wallService.subtraWallFromIntersect(wall.start, wallId)
- wallService.subtraWallFromIntersect(wall.end, wallId)
- floorplanService.deleteWall(wallId)
- }
- clear(){
- this.needUpdateRoom = false
- this.startMoving = false
- this.moveFlag = false
- this.adsorbPointWalls = {}
- this.splitWallId = null
- }
- }
- const moveWall = new MoveWall()
- export { moveWall }
|