테스트 중 직각일 경우 지붕 라인 그리기 처리.

This commit is contained in:
Jaeyoung Lee 2024-07-19 20:30:12 +09:00
parent e0a644c84e
commit 01faaead93

View File

@ -27,6 +27,8 @@ export default class QPolygon extends fabric.Group {
helpLines = []
wall
ridges = []
hips = []
constructor(points, options, canvas) {
/*if (points.length !== 4 && points.length !== 6) {
@ -672,11 +674,111 @@ export default class QPolygon extends fabric.Group {
}
#drawHelpLineInOctagon(chon) {
console.log(this.lines)
this.drawRoofRidge()
this.drawHips()
this.connectLinePoint()
}
let prevLine, currentLine, nextLine
let point
/*
외벽의 모양이 돌출된 ㄷ의 형태일때
현재 라인의 외벽길이가 붙어있는 두외벽의 길이보다 짧거나 같다면
지붕의 꼭지점에서 외벽의 꼭지점으로 45 방향으로 선을 그려 만나는 지점이 마루의 시작점이 되고
시작점에서 부터 (가장 긴선 - ( 삼각형의 빗변 에서 직각까지의 수직길이 x 2)) 길이가 마루의 끝점이 된다.
다만 마루의 길이는 나머지 나머지 지붕의 길이중 짧은선의 길이를 넘어갈수 없다.
*/
drawRoofRidge() {
let prevLine, currentLine, nextLine, prevWall, currentWall, nextWall
let startXPoint, startYPoint, endXPoint, endYPoint
let dVector, ridgeMaxLength, ridgeMinLength, ridgeRun
this.lines.forEach(
(value, index) => {
if (index === 0) {
prevLine = this.lines[this.lines.length - 1]
prevWall = this.wall.lines[this.wall.lines.length - 1]
} else {
prevLine = this.lines[index - 1]
prevWall = this.wall.lines[index - 1]
}
currentLine = this.lines[index]
currentWall = this.wall.lines[index]
if (index === this.lines.length - 1) {
nextLine = this.lines[0]
nextWall = this.wall.lines[0]
} else if (index === this.lines.length) {
nextLine = this.lines[1]
nextWall = this.wall.lines[1]
} else {
nextLine = this.lines[index + 1]
nextWall = this.wall.lines[index + 1]
}
if (this.getLineDirection(prevLine) !== this.getLineDirection(nextLine)) {
if (currentWall.length <= prevWall.length && currentWall.length <= nextWall.length) {
ridgeMaxLength = Math.min(prevLine.length, currentLine.length, nextLine.length)
ridgeMinLength = Math.max(prevLine.length, currentLine.length, nextLine.length) - currentLine.length
ridgeRun = ridgeMinLength < ridgeMaxLength ? ridgeMinLength : ridgeMaxLength
dVector = this.getDirectionForDegree(prevLine, currentLine)
switch (dVector) {
case 45:
startXPoint = currentLine.x1 + (currentLine.length / 2)
startYPoint = currentLine.y1 - (currentLine.length / 2)
endXPoint = startXPoint
endYPoint = startYPoint - ridgeRun
break
case 135:
startXPoint = currentLine.x1 + (currentLine.length / 2)
startYPoint = currentLine.y1 + (currentLine.length / 2)
endXPoint = startXPoint + ridgeRun
endYPoint = startYPoint
break
case 225:
startXPoint = currentLine.x1 - (currentLine.length / 2)
startYPoint = currentLine.y1 + (currentLine.length / 2)
endXPoint = startXPoint
endYPoint = startYPoint + ridgeRun
break
case 315:
startXPoint = currentLine.x1 - (currentLine.length / 2)
startYPoint = currentLine.y1 - (currentLine.length / 2)
endXPoint = startXPoint - ridgeRun
endYPoint = startYPoint
break
}
if (this.ridges.length < this.getMaxRidge(this.lines.length)) {
const ridge = new QLine([startXPoint, startYPoint, endXPoint, endYPoint], {
fontSize: this.fontSize,
stroke: 'blue',
strokeWidth: 1,
})
this.addWithUpdate(ridge)
this.ridges.push(ridge)
}
//마루와 연결될 추녀마루을 그려준다.
const leftHip = new QLine([currentLine.x1, currentLine.y1, startXPoint, startYPoint], {
fontSize: this.fontSize,
stroke: 'red',
strokeWidth: 1,
})
const rightHip = new QLine([currentLine.x2, currentLine.y2, startXPoint, startYPoint], {
fontSize: this.fontSize,
stroke: 'red',
strokeWidth: 1,
})
this.addWithUpdate(leftHip)
this.addWithUpdate(rightHip)
this.hips.push(leftHip)
this.hips.push(rightHip)
}
}
},
)
this.canvas.renderAll()
}
drawHips() {
let prevLine, currentLine, nextLine, endXPoint, endYPoint
this.lines.forEach(
(value, index) => {
if (index === 0) {
@ -689,52 +791,139 @@ export default class QPolygon extends fabric.Group {
if (index === this.lines.length - 1) {
nextLine = this.lines[0]
} else if (index === this.lines.length) {
nextLine = this.lines[0]
nextLine = this.lines[1]
} else {
nextLine = this.lines[index + 1]
}
// point = this.getPointBetweenLine(currentLine, nextLine)
this.getRoofRidge(prevLine, currentLine, nextLine)
if (!this.isAlreadyHip(currentLine)) {
this.ridges.forEach(ridge => {
if (Math.abs(currentLine.x1 - ridge.x1) === Math.abs(currentLine.y1 - ridge.y1)) {
endXPoint = ridge.x1
endYPoint = ridge.y1
}
if (Math.abs(currentLine.x1 - ridge.x2) === Math.abs(currentLine.y1 - ridge.y2)) {
endXPoint = ridge.x2
endYPoint = ridge.y2
}
// TODO [ljyoung] : 마루와 만나지 않는 hip 계산
})
const hip = new QLine([currentLine.x1, currentLine.y1, endXPoint, endYPoint], {
fontSize: this.fontSize,
stroke: 'red',
strokeWidth: 1,
})
this.addWithUpdate(hip)
this.hips.push(hip)
}
},
)
this.canvas.renderAll()
}
getRoofRidge(prevLine, currentLine, nextLine) {
if (this.getLineDirection(prevLine) !== this.getLineDirection(nextLine)) {
console.log(this.getLineDirection(prevLine), this.getLineDirection(currentLine), this.getLineDirection(nextLine))
console.log(currentLine.length)
if (currentLine.length < prevLine.length && currentLine.length < nextLine.length) {
console.log(currentLine.length)
/*
추녀마루(hip) 중복방지를 위해 마루와 함께 그려진 추녀마루를 확인한다
*/
isAlreadyHip(line) {
let isAlreadyHip = false
this.hips.forEach(hip => {
if (line.x1 === hip.x1 && line.y1 === hip.y1) {
isAlreadyHip = true
}
}
})
return isAlreadyHip
}
/*
3 이상 이어지지 않은 라인 포인트 계산
모임지붕에서 point는 3 이상의 라인과 접해야 .
*/
connectLinePoint() {
let missedPoints = []
let missedLine = []
this.ridges.forEach(ridge => {
if (this.findConnectionLineCount(ridge.x1, ridge.y1) < 2) {
missedPoints.push({ x: ridge.x1, y: ridge.y1 })
}
if (this.findConnectionLineCount(ridge.x2, ridge.y2) < 2) {
missedPoints.push({ x: ridge.x2, y: ridge.y2 })
}
})
console.log(missedPoints)
missedPoints.forEach(p1 => {
let nearX, nearY, diffX, diffY, diffMinX, diffMinY
//가장 가까운 포인트를 확인
missedPoints.forEach(p2 => {
diffX = Math.abs(p1.x - p2.x)
diffY = Math.abs(p1.y - p2.y)
if (diffMinX === undefined && diffMinY === undefined && diffX > 0 && diffY > 0) {
diffMinX = diffX
diffMinY = diffY
}
console.log(nearX, nearY, diffX, diffY, diffMinX, diffMinY)
if (diffX !== 0 && diffY !== 0 && (diffX === diffY)
&& diffX <= diffMinX && diffY <= diffMinY) {
nearX = p2.x
nearY = p2.y
diffMinX = Math.abs(p1.x - p2.x)
diffMinY = Math.abs(p1.y - p2.y)
}
})
console.log(nearX, nearY)
if (nearX !== undefined && nearY !== undefined) {
if (p1.x < nearX && p1.y < nearY) {
missedLine.push({ x1: p1.x, y1: p1.y, x2: nearX, y2: nearY })
} else if (p1.x > nearX && p1.y < nearY) {
missedLine.push({ x1: nearX, y1: p1.y, x2: p1.x, y2: nearY })
} else if (p1.x > nearX && p1.y > nearY) {
missedLine.push({ x1: nearX, y1: nearY, x2: p1.x, y2: p1.y })
} else if (p1.x < nearX && p1.y > nearY) {
missedLine.push({ x1: nearX, y1: nearY, x2: p1.x, y2: p1.y })
}
}
})
// TODO [ljyoung] : 중복라인제거
console.log(missedLine)
missedLine.forEach(p => {
const line = new QLine([p.x1, p.y1, p.x2, p.y2], {
fontSize: this.fontSize,
stroke: 'green',
strokeWidth: 1,
})
this.addWithUpdate(line)
})
this.canvas.renderAll()
}
/*
hip은 항상 마루에 연결되고 마루에는 2 이상의 hip이 연결된다.
hip의 시작은 처마꼭지점이며 끝은 마루이기 때문에 힙의 좌표와 비교한다.
*/
findConnectionLineCount(x, y) {
let count = 0
this.hips.forEach((hip, index) => {
if (x === hip.x2 && y === hip.y2) {
count++
}
})
return count
}
/*
최대 생성 마루 갯수
*/
getMaxRidge(length) {
let a1 = 4
let d = 2
return ((length - a1) / d) + 1
}
getPointBetweenLine(line1, line2) {
let dVector = this.getDirectionForDegree(line1, line2)
let xp = line1.x2, yp = line1.y2
console.log(xp, yp)
// let alpha = 45.0 * Math.PI / 180
// let a = c * Math.sin(alpha)
switch (dVector) {
case 45:
break
}
return 'a'
}
/*
라인의 사잇각 계산
*/
getDirectionForDegree(line1, line2) {
let degree = this.getLineDirection(line1) + this.getLineDirection(line2)
let vector
@ -769,6 +958,9 @@ export default class QPolygon extends fabric.Group {
return vector
}
/*
현재 라인의 방향을 계산
*/
getLineDirection(line) {
let x1, x2, y1, y2, xp, yp
x1 = Math.round(line.x1)