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

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 = [] helpLines = []
wall wall
ridges = []
hips = []
constructor(points, options, canvas) { constructor(points, options, canvas) {
/*if (points.length !== 4 && points.length !== 6) { /*if (points.length !== 4 && points.length !== 6) {
@ -672,11 +674,111 @@ export default class QPolygon extends fabric.Group {
} }
#drawHelpLineInOctagon(chon) { #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( this.lines.forEach(
(value, index) => { (value, index) => {
if (index === 0) { if (index === 0) {
@ -689,52 +791,139 @@ export default class QPolygon extends fabric.Group {
if (index === this.lines.length - 1) { if (index === this.lines.length - 1) {
nextLine = this.lines[0] nextLine = this.lines[0]
} else if (index === this.lines.length) { } else if (index === this.lines.length) {
nextLine = this.lines[0] nextLine = this.lines[1]
} else { } else {
nextLine = this.lines[index + 1] nextLine = this.lines[index + 1]
} }
// point = this.getPointBetweenLine(currentLine, nextLine) if (!this.isAlreadyHip(currentLine)) {
this.ridges.forEach(ridge => {
this.getRoofRidge(prevLine, currentLine, nextLine) 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)) { 추녀마루(hip) 중복방지를 위해 마루와 함께 그려진 추녀마루를 확인한다
console.log(this.getLineDirection(prevLine), this.getLineDirection(currentLine), this.getLineDirection(nextLine)) */
console.log(currentLine.length) isAlreadyHip(line) {
if (currentLine.length < prevLine.length && currentLine.length < nextLine.length) { let isAlreadyHip = false
console.log(currentLine.length) 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) { getMaxRidge(length) {
let a1 = 4 let a1 = 4
let d = 2 let d = 2
return ((length - a1) / d) + 1 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) { getDirectionForDegree(line1, line2) {
let degree = this.getLineDirection(line1) + this.getLineDirection(line2) let degree = this.getLineDirection(line1) + this.getLineDirection(line2)
let vector let vector
@ -769,6 +958,9 @@ export default class QPolygon extends fabric.Group {
return vector return vector
} }
/*
현재 라인의 방향을 계산
*/
getLineDirection(line) { getLineDirection(line) {
let x1, x2, y1, y2, xp, yp let x1, x2, y1, y2, xp, yp
x1 = Math.round(line.x1) x1 = Math.round(line.x1)