Merge branch 'dev' into dev-yj

This commit is contained in:
yjnoh 2024-11-14 17:35:46 +09:00
commit b872930043
7 changed files with 293 additions and 287 deletions

View File

@ -445,11 +445,22 @@ export default function Roof2(props) {
{ x: 113, y: 371.9 }, { x: 113, y: 371.9 },
{ x: 762, y: 371.9 }, { x: 762, y: 371.9 },
{ x: 762, y: 818.7 }, { x: 762, y: 818.7 },
{ x: 1468.6, y: 818.7 }, { x: 1478.6, y: 818.7 },
{ x: 1468.6, y: 114.9 }, { x: 1478.6, y: 114.9 },
] ]
const polygon = new QPolygon(type2, { const test3 = [
{ x: 100, y: 100 },
{ x: 100, y: 600 },
{ x: 600, y: 600 },
{ x: 600, y: 100 },
{ x: 500, y: 100 },
{ x: 500, y: 200 },
{ x: 200, y: 200 },
{ x: 200, y: 100 },
]
const polygon = new QPolygon(eightPoint4, {
fill: 'transparent', fill: 'transparent',
stroke: 'green', stroke: 'green',
strokeWidth: 1, strokeWidth: 1,

View File

@ -272,9 +272,11 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.texts = [] this.texts = []
points.forEach((start, i) => { points.forEach((start, i) => {
const end = points[(i + 1) % points.length] const end = points[(i + 1) % points.length]
// planeSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10,
// actualSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10,
const dx = end.x - start.x const dx = end.x - start.x
const dy = end.y - start.y const dy = end.y - start.y
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10 const length = Math.round(Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2))) * 10
let midPoint let midPoint

View File

@ -569,7 +569,7 @@ export default function StuffDetail() {
form.setValue('remarks', managementState.remarks) form.setValue('remarks', managementState.remarks)
}) })
} }
}, [managementState, session]) }, [managementState])
// //
const onChangeHonorificCode = (key) => { const onChangeHonorificCode = (key) => {

View File

@ -155,7 +155,6 @@ export default function StuffSearchCondition() {
handleClear1() // handleClear1() //
resetStuffRecoil() resetStuffRecoil()
setStuffSearch({ setStuffSearch({
...stuffSearch,
schSelSaleStoreId: '', schSelSaleStoreId: '',
schOtherSelSaleStoreId: '', schOtherSelSaleStoreId: '',
}) })

View File

@ -1510,7 +1510,7 @@ export function useMode() {
polygon.lines.forEach((line, index) => { polygon.lines.forEach((line, index) => {
line.attributes = { line.attributes = {
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
offset: 40, offset: 50,
width: 50, width: 50,
pitch: 4, pitch: 4,
sleeve: true, sleeve: true,

View File

@ -675,6 +675,57 @@ export const usePolygon = () => {
const roofs = [] const roofs = []
//polygonLines를 순회하며 innerLines와 교차하는 점을 line의 속성에 배열로 저장한다. //polygonLines를 순회하며 innerLines와 교차하는 점을 line의 속성에 배열로 저장한다.
polygonLines.forEach((line) => {
let startPoint // 시작점
let endPoint // 끝점
if (line.x1 < line.x2) {
startPoint = { x: line.x1, y: line.y1 }
endPoint = { x: line.x2, y: line.y2 }
} else if (line.x1 > line.x2) {
startPoint = { x: line.x2, y: line.y2 }
endPoint = { x: line.x1, y: line.y1 }
} else {
if (line.y1 < line.y2) {
startPoint = { x: line.x1, y: line.y1 }
endPoint = { x: line.x2, y: line.y2 }
} else {
startPoint = { x: line.x2, y: line.y2 }
endPoint = { x: line.x1, y: line.y1 }
}
}
line.startPoint = startPoint
line.endPoint = endPoint
})
innerLines.forEach((line) => {
let startPoint // 시작점
let endPoint // 끝점
if (line.x1 < line.x2) {
startPoint = { x: line.x1, y: line.y1 }
endPoint = { x: line.x2, y: line.y2 }
} else if (line.x1 > line.x2) {
startPoint = { x: line.x2, y: line.y2 }
endPoint = { x: line.x1, y: line.y1 }
} else {
if (line.y1 < line.y2) {
startPoint = { x: line.x1, y: line.y1 }
endPoint = { x: line.x2, y: line.y2 }
} else {
startPoint = { x: line.x2, y: line.y2 }
endPoint = { x: line.x1, y: line.y1 }
}
}
line.startPoint = startPoint
line.endPoint = endPoint
})
polygonLines.forEach((line) => {
line.set({ strokeWidth: 10 })
canvas.add(line)
})
canvas.renderAll()
polygonLines.forEach((line) => { polygonLines.forEach((line) => {
const intersections = [] const intersections = []
innerLines.forEach((innerLine) => { innerLines.forEach((innerLine) => {
@ -685,7 +736,7 @@ export const usePolygon = () => {
intersections.push(innerLine.startPoint) intersections.push(innerLine.startPoint)
} }
if (isPointOnLine(line, innerLine.endPoint)) { if (isPointOnLine(line, innerLine.endPoint)) {
if (isSamePoint(line.startPoint, innerLine.endPoint) || isSamePoint(line.startPoint, innerLine.endPoint)) { if (isSamePoint(line.startPoint, innerLine.endPoint) || isSamePoint(line.endPoint, innerLine.endPoint)) {
return return
} }
intersections.push(innerLine.endPoint) intersections.push(innerLine.endPoint)
@ -696,6 +747,7 @@ export const usePolygon = () => {
const divideLines = polygonLines.filter((line) => line.intersections.length > 0) const divideLines = polygonLines.filter((line) => line.intersections.length > 0)
let newLines = [] let newLines = []
divideLines.forEach((line) => { divideLines.forEach((line) => {
const { intersections, startPoint, endPoint } = line const { intersections, startPoint, endPoint } = line

View File

@ -1249,8 +1249,6 @@ export const drawShedRoof = (roofId, canvas) => {
const eaves = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) const eaves = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
const gables = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.GABLE) const gables = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.GABLE)
console.log('gable', gables)
let shedDegree = sheds[0].attributes.degree || 0 let shedDegree = sheds[0].attributes.degree || 0
const shedChon = sheds[0].attributes.pitch || 0 const shedChon = sheds[0].attributes.pitch || 0
@ -1311,265 +1309,194 @@ const drawRidge = (roof, canvas) => {
// 지붕의 길이가 짧은 순으로 정렬 // 지붕의 길이가 짧은 순으로 정렬
ridgeRoof.sort((a, b) => a.length - b.length) ridgeRoof.sort((a, b) => a.length - b.length)
console.log('ridgeRoof', ridgeRoof)
ridgeRoof.forEach((item) => { ridgeRoof.forEach((item) => {
if (getMaxRidge(roofLines.length) > roof.ridges.length) { if (getMaxRidge(roofLines.length) > roof.ridges.length) {
let index = item.index, const index = item.index,
beforePrevRoof, currentRoof = item.roof
prevRoof, const prevRoof = index === 0 ? roofLines[wallLines.length - 1] : roofLines[index - 1]
currentRoof = item.roof, const nextRoof = index === roofLines.length - 1 ? roofLines[0] : index === roofLines.length ? roofLines[1] : roofLines[index + 1]
nextRoof, // const beforePrevRoof = index <= 1 ? roofLines[roofLines.length - 2 + index] : roofLines[index - 2]
afterNextRoof // const afterNextRoof = index >= roofLines.length - 2 ? roofLines[(index + 2) % roofLines.length] : roofLines[index + 2]
let startXPoint, startYPoint, endXPoint, endYPoint let startXPoint, startYPoint, endXPoint, endYPoint
prevRoof = index === 0 ? roofLines[wallLines.length - 1] : roofLines[index - 1] // console.log('currentRoof : ', currentRoof.direction, currentRoof.attributes.planeSize)
nextRoof = index === roofLines.length - 1 ? roofLines[0] : index === roofLines.length ? roofLines[1] : roofLines[index + 1]
beforePrevRoof = index <= 1 ? roofLines[roofLines.length - 2 + index] : roofLines[index - 2] let wallLine = wallLines.filter((w) => w.id === currentRoof.attributes.wallLine)
afterNextRoof = index >= roofLines.length - 2 ? roofLines[(index + 2) % roofLines.length] : roofLines[index + 2] if (wallLine.length > 0) {
wallLine = wallLine[0]
}
const anotherRoof = roofLines.filter((roof) => roof !== currentRoof && roof !== prevRoof && roof !== nextRoof) const anotherRoof = roofLines.filter((roof) => roof !== currentRoof && roof !== prevRoof && roof !== nextRoof)
let xEqualInnerLines = anotherRoof.filter((roof) => roof.x1 === roof.x2 && isInnerLine(prevRoof, currentRoof, nextRoof, roof)), //x가 같은 내부선 let currentX1 = currentRoof.x1,
yEqualInnerLines = anotherRoof.filter((roof) => roof.y1 === roof.y2 && isInnerLine(prevRoof, currentRoof, nextRoof, roof)) //y가 같은 내부선 currentY1 = currentRoof.y1,
currentX2 = currentRoof.x2,
currentY2 = currentRoof.y2
let ridgeMaxLength = Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize) / 10
let ridgeMinLength = Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize) / 10
let ridgeBaseLength = Math.round(currentRoof.attributes.planeSize / 2), // 지붕의 기반 길이 const currentAngle = Math.atan2(currentY2 - currentY1, currentX2 - currentX1) * (180 / Math.PI)
ridgeMaxLength = Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize), // 지붕의 최대 길이. 이전, 다음 벽 중 짧은 길이 anotherRoof
ridgeAcrossLength = Math.abs(Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize) - currentRoof.attributes.planeSize) // 맞은편 벽까지의 길이 - 지붕의 기반 길이 .filter((roof) => isInnerLine(prevRoof, currentRoof, nextRoof, roof))
.forEach((innerRoof) => {
const vector1 = { x: currentRoof.x2 - currentRoof.x1, y: currentRoof.y2 - currentRoof.y1 }
const vector2 = { x: innerRoof.x2 - innerRoof.x1, y: innerRoof.y2 - innerRoof.y1 }
console.log('ridgeBaseLength', ridgeBaseLength, 'ridgeMaxLength', ridgeMaxLength, 'ridgeAcrossLength', ridgeAcrossLength) const dotProduct = vector1.x * vector2.x + vector1.y * vector2.y
let acrossRoof = anotherRoof const magnitude1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y)
.filter((roof) => { const magnitude2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y)
const angle1 = calculateAngle(currentRoof.startPoint, currentRoof.endPoint) const angle = (Math.acos(dotProduct / (magnitude1 * magnitude2)) * 180) / Math.PI
const angle2 = calculateAngle(roof.startPoint, roof.endPoint)
if (Math.abs(angle1 - angle2) === 180) { // console.log('innerRoof', innerRoof)
return roof // console.log('현재라인', currentRoof, '현재라인의 각도 : ', currentAngle, 'inner 라인과의 각도:', angle)
//현재 지붕선과 직각인 선
if (Math.abs(angle) === 90) {
const innerBefore = roofLines.find((line) => innerRoof.x1 === line.x2 && innerRoof.y1 === line.y2)
const ibAngle = Math.atan2(innerBefore.y2 - innerBefore.y1, innerBefore.x2 - innerBefore.x1) * (180 / Math.PI)
// console.log('현재라인과 직각인 선의 이전라인', innerBefore, '각도', ibAngle)
if (Math.abs(currentAngle - ibAngle) === 180) {
// console.log('currentRoof 의 x2,y2 좌표에서 연결된 라인')
if (currentAngle === 0 || currentAngle === 180) {
currentX2 = innerRoof.x1
ridgeMinLength =
Math.round(
Math.sqrt(
Math.pow(Math.round(Math.abs(nextRoof.x1 - nextRoof.x2) * 10), 2) +
Math.pow(Math.round(Math.abs(nextRoof.y1 - innerRoof.y2) * 10), 2),
),
) / 10
}
if (currentAngle === 90 || currentAngle === 270) {
currentY2 = innerRoof.y1
ridgeMinLength =
Math.round(
Math.sqrt(
Math.pow(Math.round(Math.abs(nextRoof.x1 - innerRoof.x2) * 10), 2) +
Math.pow(Math.round(Math.abs(nextRoof.y1 - nextRoof.y2) * 10), 2),
),
) / 10
}
}
if (Math.abs(currentAngle - ibAngle) === 0) {
// console.log('currentRoof 의 x1,y1 좌표에서 연결된 라인', currentAngle)
if (currentAngle === 0 || currentAngle === 180) {
currentX1 = innerRoof.x2
ridgeMinLength =
Math.round(
Math.sqrt(
Math.pow(Math.round(Math.abs(prevRoof.x1 - prevRoof.x2) * 10), 2) +
Math.pow(Math.round(Math.abs(prevRoof.y1 - innerRoof.y1) * 10), 2),
),
) / 10
}
if (currentAngle === 90 || currentAngle === 270) {
currentY1 = innerRoof.y2
ridgeMinLength =
Math.round(
Math.sqrt(
Math.pow(Math.round(Math.abs(prevRoof.x1 - innerRoof.x1) * 10), 2) +
Math.pow(Math.round(Math.abs(prevRoof.y1 - prevRoof.y2) * 10), 2),
),
) / 10
}
}
}
//현재 지붕선과 반대인 선
if (Math.abs(angle) === 180) {
// console.log('현재라인과 반대인 선')
if (currentAngle === 0 || currentAngle === 180) {
}
if (currentAngle === 90 || currentAngle === 270) {
}
} }
}) })
.reduce((prev, current) => {
let hasBetweenRoof = false
if (current.x1 === current.x2) {
hasBetweenRoof = roofLines
.filter((roof) => roof !== current)
.some((line) => {
let currentY2 = currentRoof.y2
if (yEqualInnerLines.length > 0) {
yEqualInnerLines.forEach((line) => {
currentY2 = Math.abs(currentRoof.y1 - currentY2) < Math.abs(currentRoof.y1 - line.y1) ? currentY2 : line.y1
})
}
const isY1Between = (line.y1 > currentRoof.y1 && line.y1 < currentY2) || (line.y1 > currentY2 && line.y1 < currentRoof.y1)
const isY2Between = (line.y2 > currentRoof.y1 && line.y2 < currentY2) || (line.y2 > currentY2 && line.y2 < currentRoof.y1)
const isX1Between = (line.x1 > currentRoof.x1 && line.x1 < current.x1) || (line.x1 > currentRoof.x1 && line.x1 < current.x1)
const isX2Between = (line.x2 > currentRoof.x1 && line.x2 < current.x1) || (line.x2 > currentRoof.x1 && line.x2 < current.x1)
return isY1Between && isY2Between && isX1Between && isX2Between const midX = (currentX1 + currentX2) / 2 // 지붕의 X 중심
}) const midY = (currentY1 + currentY2) / 2 // 지붕의 Y 중심
} const alpha = (currentRoof.x1 + currentRoof.x2) / 2 - (wallLine.x1 + wallLine.x2) / 2 // 벽과 지붕의 X 거리
if (current.y1 === current.y2) { const beta = (currentRoof.y1 + currentRoof.y2) / 2 - (wallLine.y1 + wallLine.y2) / 2 // 벽과 지붕의 Y 거리
hasBetweenRoof = roofLines const hypotenuse = Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) // 벽과 지붕의 거리
.filter((roof) => roof !== current)
.some((line) => {
let currentX2 = currentRoof.x2
if (xEqualInnerLines.length > 0) {
xEqualInnerLines.forEach((line) => {
currentX2 = Math.abs(currentRoof.x1 - currentX2) < Math.abs(currentRoof.x1 - line.x1) ? currentX2 : line.x1
})
}
const isX1Between = (line.x1 > currentRoof.x1 && line.x1 < currentX2) || (line.x1 > currentX2 && line.x1 < currentRoof.x1)
const isX2Between = (line.x2 > currentRoof.x1 && line.x2 < currentX2) || (line.x2 > currentX2 && line.x2 < currentRoof.x1)
const isY1Between = (line.y1 > currentRoof.y1 && line.y1 < current.y1) || (line.y1 > currentRoof.y1 && line.y1 < current.y1)
const isY2Between = (line.y2 > currentRoof.y1 && line.y2 < current.y1) || (line.y2 > currentRoof.y1 && line.y2 < current.y1)
return isX1Between && isX2Between && isY1Between && isY2Between const currentPlaneSize = Math.sqrt(
}) Math.pow(Math.round(Math.abs(currentX1 - currentX2) * 10), 2) + Math.pow(Math.round(Math.abs(currentY1 - currentY2) * 10), 2),
} )
let ridgeBaseLength = Math.round(currentPlaneSize / 2) / 10 // 지붕의 기반 길이
startXPoint = Math.round(midX + (-1 * (alpha / hypotenuse) * (currentPlaneSize / 2)) / 10)
startYPoint = Math.round(midY + (-1 * (beta / hypotenuse) * (currentPlaneSize / 2)) / 10)
const checkEndXPoint = Math.round(startXPoint + Math.sign(alpha) * -1 * (ridgeMaxLength + ridgeBaseLength))
const checkEndYPoint = Math.round(startYPoint + Math.sign(beta) * -1 * (ridgeMaxLength + ridgeBaseLength))
const checkLine = new QLine([startXPoint, startYPoint, checkEndXPoint, checkEndYPoint], {
fontSize: roof.fontSize,
stroke: 'red',
strokeWidth: 1,
name: LINE_TYPE.SUBLINE.HIP,
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
})
const intersectLines = []
roofLines.forEach((line) => {
const intersection = edgesIntersection(
{ vertex1: { x: checkLine.x1, y: checkLine.y1 }, vertex2: { x: checkLine.x2, y: checkLine.y2 } },
{ vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
)
if (intersection && !intersection.isIntersectionOutside) {
intersectLines.push({ x: intersection.x, y: intersection.y, line: line })
}
})
if (intersectLines.length > 0) {
intersectLines.reduce((prev, current) => {
if (prev !== undefined) { if (prev !== undefined) {
if (currentRoof.x1 === currentRoof.x2) { const prevDistance = Math.sqrt(Math.pow(prev.x - startXPoint, 2) + Math.pow(prev.y - startYPoint, 2))
return Math.abs(currentRoof.y1 - prev.y1) > Math.abs(currentRoof.y1 - current.y1) ? prev : current const currentDistance = Math.sqrt(Math.pow(current.x - startXPoint, 2) + Math.pow(current.y - startYPoint, 2))
} return prevDistance > currentDistance ? current : prev
if (currentRoof.y1 === currentRoof.y2) {
return Math.abs(currentRoof.x1 - prev.x1) > Math.abs(currentRoof.x1 - current.x1) ? prev : current
}
} else { } else {
if (!hasBetweenRoof) { return current
if (currentRoof.x1 === currentRoof.x2) {
return Math.sign(currentRoof.y1 - currentRoof.y2) !== Math.sign(current.y1 - current.y2) ? current : undefined
}
if (currentRoof.y1 === currentRoof.y2) {
return Math.sign(currentRoof.x1 - currentRoof.x2) !== Math.sign(current.x1 - current.x2) ? current : undefined
}
return undefined
} else {
return undefined
}
} }
}, undefined) }, undefined)
if (acrossRoof !== undefined) {
if (currentRoof.x1 === currentRoof.x2) {
if (ridgeAcrossLength < Math.abs(currentRoof.x1 - acrossRoof.x1)) {
ridgeAcrossLength = Math.round(Math.round(Math.abs(currentRoof.x1 - acrossRoof.x1) * 10) - currentRoof.attributes.planeSize)
}
}
if (currentRoof.y1 === currentRoof.y2) {
if (ridgeAcrossLength < Math.abs(currentRoof.y1 - acrossRoof.y1)) {
ridgeAcrossLength = Math.round(Math.round(Math.abs(currentRoof.y1 - acrossRoof.y1) * 10) - currentRoof.attributes.planeSize)
}
}
} }
ridgeBaseLength = ridgeBaseLength / 10 if (intersectLines.length > 0) {
ridgeMaxLength = ridgeMaxLength / 10 const intersectLine = intersectLines[0]
ridgeAcrossLength = ridgeAcrossLength / 10 const diffX = Math.round(intersectLine.x - startXPoint)
const diffY = Math.round(intersectLine.y - startYPoint)
endXPoint = Math.sign(diffX) * Math.round(Math.abs(diffX) - ridgeBaseLength) + startXPoint
endYPoint = Math.sign(diffY) * Math.round(Math.abs(diffY) - ridgeBaseLength) + startYPoint
console.log('ridgeBaseLength', ridgeBaseLength, 'ridgeMaxLength', ridgeMaxLength, 'ridgeAcrossLength', ridgeAcrossLength) const hypo = Math.sqrt(Math.pow(Math.abs(startXPoint - endXPoint), 2) + Math.pow(Math.abs(startYPoint - endYPoint), 2))
if (ridgeBaseLength > 0 && ridgeMaxLength > 0 && ridgeAcrossLength > 0) { const intersectLength = Math.sqrt(Math.pow(Math.abs(midX - intersectLine.x), 2) + Math.pow(Math.abs(midY - intersectLine.y), 2))
let ridgeLength = Math.min(ridgeMaxLength, ridgeAcrossLength) console.log('intersect 좌표까지의 거리 : ', intersectLength)
if (currentRoof.x1 === currentRoof.x2) { console.log('hypotenuse', hypo, 'ridgeMinLength', ridgeMinLength)
startXPoint = currentRoof.x1 + (nextRoof.direction === 'right' ? 1 : -1) * ridgeBaseLength if (intersectLength < prevRoof.attributes.planeSize / 10 && intersectLength < nextRoof.attributes.planeSize / 10) {
startYPoint = currentRoof.y1 + (currentRoof.direction === 'top' ? -1 : 1) * ridgeBaseLength
endXPoint = startXPoint + (nextRoof.direction === 'right' ? 1 : -1) * ridgeLength
endYPoint = startYPoint
let adjustY
if (currentRoof.direction === 'top') {
if (afterNextRoof.direction === 'bottom' && beforePrevRoof.direction === 'bottom') {
adjustY =
Math.abs(currentRoof.x1 - afterNextRoof.x1) < Math.abs(currentRoof.x1 - beforePrevRoof.x1) ? afterNextRoof.y2 : beforePrevRoof.y1
} else if (afterNextRoof.direction === 'bottom' && afterNextRoof.y2 > currentRoof.y2 && afterNextRoof.y2 < currentRoof.y1) {
adjustY = afterNextRoof.y2
} else if (beforePrevRoof.direction === 'bottom' && beforePrevRoof.y1 > currentRoof.y2 && beforePrevRoof.y1 < currentRoof.y1) {
adjustY = beforePrevRoof.y1
}
if (adjustY) {
startYPoint = currentRoof.y1 - Math.abs(currentRoof.y1 - adjustY) / 2
endYPoint = startYPoint
}
}
if (currentRoof.direction === 'bottom') {
if (afterNextRoof.direction === 'top' && beforePrevRoof.direction === 'top') {
adjustY =
Math.abs(currentRoof.x1 - afterNextRoof.x1) < Math.abs(currentRoof.x1 - beforePrevRoof.x1) ? afterNextRoof.y2 : beforePrevRoof.y1
} else if (afterNextRoof.direction === 'top' && afterNextRoof.y2 < currentRoof.y2 && afterNextRoof.y2 > currentRoof.y1) {
adjustY = afterNextRoof.y2
} else if (beforePrevRoof.direction === 'top' && beforePrevRoof.y1 < currentRoof.y2 && beforePrevRoof.y1 > currentRoof.y1) {
adjustY = beforePrevRoof.y1
}
if (adjustY) {
startYPoint = currentRoof.y1 + Math.abs(currentRoof.y1 - adjustY) / 2
endYPoint = startYPoint
}
}
if (yEqualInnerLines.length > 0) {
yEqualInnerLines.reduce((prev, current) => {
if (prev !== undefined) {
return Math.abs(currentRoof.y1 - prev.y1) < Math.abs(currentRoof.y1 - current.y1) ? prev : current
} else {
return current
}
}, undefined)
startYPoint =
Math.abs(currentRoof.y1 - startYPoint) * 2 <= Math.abs(currentRoof.y1 - yEqualInnerLines[0].y1)
? startYPoint
: Math.abs(currentRoof.y1 - yEqualInnerLines[0].y1)
endYPoint = startYPoint
ridgeAcrossLength = Math.max(prevRoof.length, nextRoof.length) - Math.abs(currentRoof.y1 - startYPoint) * 2
if (
//yEqualInnerLines 이 다음 벽보다 안쪽에 있을때
Math.abs(currentRoof.y1 - yEqualInnerLines[0].y1) <= Math.abs(currentRoof.y1 - nextRoof.y1) &&
Math.abs(currentRoof.x1 - yEqualInnerLines[0].x2) >= Math.abs(currentRoof.x1 - nextRoof.x2)
) {
ridgeMaxLength = Math.round(Math.abs(currentRoof.x1 - yEqualInnerLines[0].x2) * 10) / 10
}
ridgeLength = Math.min(ridgeMaxLength, ridgeAcrossLength)
startXPoint = currentRoof.x1 + (nextRoof.direction === 'right' ? 1 : -1) * Math.abs(currentRoof.y1 - startYPoint)
endXPoint = startXPoint + (nextRoof.direction === 'right' ? 1 : -1) * ridgeLength
}
}
if (currentRoof.y1 === currentRoof.y2) {
startXPoint = currentRoof.x1 + (currentRoof.direction === 'left' ? -1 : 1) * ridgeBaseLength
startYPoint = currentRoof.y1 + (nextRoof.direction === 'bottom' ? 1 : -1) * ridgeBaseLength
endXPoint = startXPoint endXPoint = startXPoint
endYPoint = startYPoint + (nextRoof.direction === 'bottom' ? 1 : -1) * ridgeLength endYPoint = startYPoint
} else {
let adjustX if (ridgeMinLength < hypo) {
if (currentRoof.direction === 'right') { endXPoint = Math.round(startXPoint + Math.sign(diffX) * ridgeMinLength)
if (afterNextRoof.direction === 'left' && beforePrevRoof.direction === 'left') { endYPoint = Math.round(startYPoint + Math.sign(diffY) * ridgeMinLength)
adjustX =
Math.abs(currentRoof.y1 - afterNextRoof.y1) < Math.abs(currentRoof.y1 - beforePrevRoof.y1) ? afterNextRoof.x2 : beforePrevRoof.x1
} else if (afterNextRoof.direction === 'left' && afterNextRoof.x2 < currentRoof.x2 && afterNextRoof.x2 > currentRoof.x1) {
adjustX = afterNextRoof.x2
} else if (beforePrevRoof.direction === 'left' && beforePrevRoof.x1 < currentRoof.x2 && beforePrevRoof.x1 > currentRoof.x1) {
adjustX = beforePrevRoof.x1
}
if (adjustX) {
startXPoint = currentRoof.x1 + Math.abs(currentRoof.x1 - adjustX) / 2
endXPoint = startXPoint
}
}
if (currentRoof.direction === 'left') {
if (afterNextRoof.direction === 'right' && beforePrevRoof.direction === 'right') {
adjustX =
Math.abs(currentRoof.y1 - afterNextRoof.y1) < Math.abs(currentRoof.y1 - beforePrevRoof.y1) ? afterNextRoof.x2 : beforePrevRoof.x1
} else if (afterNextRoof.direction === 'right' && afterNextRoof.x2 > currentRoof.x2 && afterNextRoof.x2 < currentRoof.x1) {
adjustX = afterNextRoof.x2
} else if (beforePrevRoof.direction === 'right' && beforePrevRoof.x1 > currentRoof.x2 && beforePrevRoof.x1 < currentRoof.x1) {
adjustX = beforePrevRoof.x1
}
if (adjustX) {
startXPoint = currentRoof.x1 - Math.abs(currentRoof.x1 - adjustX) / 2
endXPoint = startXPoint
}
}
if (xEqualInnerLines.length > 0) {
xEqualInnerLines.reduce((prev, current) => {
if (prev !== undefined) {
return Math.abs(currentRoof.x1 - prev.x1) < Math.abs(currentRoof.x1 - current.x1) ? prev : current
} else {
return current
}
}, undefined)
startXPoint =
Math.abs(currentRoof.x1 - startXPoint) * 2 <= Math.abs(currentRoof.x1 - xEqualInnerLines[0].x1)
? startXPoint
: Math.abs(currentRoof.x1 - xEqualInnerLines[0].x1)
endXPoint = startXPoint
ridgeAcrossLength = Math.max(prevRoof.length, nextRoof.length) - Math.abs(currentRoof.x1 - startXPoint) * 2
if (
//xEqualInnerLines 이 다음 벽보다 안쪽에 있을때
Math.abs(currentRoof.x1 - xEqualInnerLines[0].x1) <= Math.abs(currentRoof.x1 - nextRoof.x1) &&
Math.abs(currentRoof.y1 - xEqualInnerLines[0].y2) >= Math.abs(currentRoof.y1 - nextRoof.y2)
) {
ridgeMaxLength = Math.round(Math.abs(currentRoof.y1 - xEqualInnerLines[0].y2) * 10) / 10
}
ridgeLength = Math.min(ridgeMaxLength, ridgeAcrossLength)
startYPoint = currentRoof.y1 + (nextRoof.direction === 'bottom' ? 1 : -1) * Math.abs(currentRoof.x1 - startXPoint)
endYPoint = startYPoint + (nextRoof.direction === 'bottom' ? 1 : -1) * ridgeLength
} }
} }
} else {
endXPoint = Math.round(startXPoint + Math.sign(alpha) * -1 * ridgeMinLength)
endYPoint = Math.round(startYPoint + Math.sign(beta) * -1 * ridgeMinLength)
} }
console.log('startXPoint', startXPoint, 'startYPoint', startYPoint, 'endXPoint', endXPoint, 'endYPoint', endYPoint)
// 마루 그리기 const ridge = new QLine([startXPoint, startYPoint, endXPoint, endYPoint], {
if (startXPoint !== undefined && startYPoint !== undefined && endXPoint !== undefined && endYPoint !== undefined) { fontSize: roof.fontSize,
startXPoint = Math.round(startXPoint * 10) / 10 stroke: 'blue',
startYPoint = Math.round(startYPoint * 10) / 10 strokeWidth: 1,
endXPoint = Math.round(endXPoint * 10) / 10 name: LINE_TYPE.SUBLINE.RIDGE,
endYPoint = Math.round(endYPoint * 10) / 10 attributes: { roofId: roof.id },
const ridge = new QLine( })
[Math.min(startXPoint, endXPoint), Math.min(startYPoint, endYPoint), Math.max(startXPoint, endXPoint), Math.max(startYPoint, endYPoint)],
{
fontSize: roof.fontSize,
stroke: 'blue',
strokeWidth: 1,
name: LINE_TYPE.SUBLINE.RIDGE,
attributes: { roofId: roof.id },
},
)
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
if (ridge.attributes.planeSize > 0) {
canvas.add(ridge) canvas.add(ridge)
roof.ridges.push(ridge) roof.ridges.push(ridge)
roof.innerLines.push(ridge) roof.innerLines.push(ridge)
@ -1682,39 +1609,52 @@ const drawHips = (roof, canvas) => {
const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
const ridgeCoordinate = currentRoof.attributes.ridgeCoordinate const ridgeCoordinate = currentRoof.attributes.ridgeCoordinate
const hip1 = new QLine([currentRoof.x1, currentRoof.y1, ridgeCoordinate.x1, ridgeCoordinate.y1], {
fontSize: roof.fontSize,
stroke: 'red',
strokeWidth: 1,
name: LINE_TYPE.SUBLINE.HIP,
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
})
canvas.add(hip1)
const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
const hip1Height = Math.round(hip1Base / Math.tan(((90 - currentDegree) * Math.PI) / 180))
hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10
if (prevDegree === currentDegree) {
hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2)))
}
roof.hips.push(hip1)
roof.innerLines.push(hip1)
const hip2 = new QLine([currentRoof.x2, currentRoof.y2, ridgeCoordinate.x1, ridgeCoordinate.y1], { const vectorX1 = ridgeCoordinate.x1 - currentRoof.x1
fontSize: roof.fontSize, const vectorY1 = ridgeCoordinate.y1 - currentRoof.y1
stroke: 'red', const angle1 = Math.atan2(vectorY1, vectorX1) * (180 / Math.PI)
strokeWidth: 1, console.log('angle1', Math.abs(Math.round(angle1)) % 45)
name: LINE_TYPE.SUBLINE.HIP, if (Math.abs(Math.round(angle1)) % 45 === 0) {
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, const hip1 = new QLine([currentRoof.x1, currentRoof.y1, ridgeCoordinate.x1, ridgeCoordinate.y1], {
}) fontSize: roof.fontSize,
canvas.add(hip2) stroke: 'red',
const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 strokeWidth: 1,
const hip2Height = Math.round(hip2Base / Math.tan(((90 - currentDegree) * Math.PI) / 180)) name: LINE_TYPE.SUBLINE.HIP,
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
if (nextDegree === currentDegree) { })
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas.add(hip1)
const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
const hip1Height = Math.round(hip1Base / Math.tan(((90 - currentDegree) * Math.PI) / 180))
hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10
if (prevDegree === currentDegree) {
hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2)))
}
roof.hips.push(hip1)
roof.innerLines.push(hip1)
}
const vectorX2 = ridgeCoordinate.x1 - currentRoof.x2
const vectorY2 = ridgeCoordinate.y1 - currentRoof.y2
const angle2 = Math.atan2(vectorY2, vectorX2) * (180 / Math.PI)
console.log('angle2', Math.abs(Math.round(angle2)) % 45)
if (Math.abs(Math.round(angle2)) % 45 === 0) {
const hip2 = new QLine([currentRoof.x2, currentRoof.y2, ridgeCoordinate.x1, ridgeCoordinate.y1], {
fontSize: roof.fontSize,
stroke: 'red',
strokeWidth: 1,
name: LINE_TYPE.SUBLINE.HIP,
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
})
canvas.add(hip2)
const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
const hip2Height = Math.round(hip2Base / Math.tan(((90 - currentDegree) * Math.PI) / 180))
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10
if (nextDegree === currentDegree) {
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2)))
}
roof.hips.push(hip2)
roof.innerLines.push(hip2)
} }
roof.hips.push(hip2)
roof.innerLines.push(hip2)
}) })
const hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roof.id) const hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roof.id)
@ -1772,7 +1712,7 @@ const drawHips = (roof, canvas) => {
if (ridgePoints !== undefined) { if (ridgePoints !== undefined) {
const hip = new QLine([currentRoof.x1, currentRoof.y1, ridgePoints.x, ridgePoints.y], { const hip = new QLine([currentRoof.x1, currentRoof.y1, ridgePoints.x, ridgePoints.y], {
fontSize: roof.fontSize, fontSize: roof.fontSize,
stroke: 'red', stroke: 'yellow',
strokeWidth: 1, strokeWidth: 1,
name: LINE_TYPE.SUBLINE.HIP, name: LINE_TYPE.SUBLINE.HIP,
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 }, attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
@ -2186,10 +2126,8 @@ const changeEavesRoof = (currentRoof, canvas) => {
const alpha = midX - midWallX // 벽과 지붕의 X 거리 const alpha = midX - midWallX // 벽과 지붕의 X 거리
const beta = midY - midWallY // 벽과 지붕의 Y 거리 const beta = midY - midWallY // 벽과 지붕의 Y 거리
const hypotenuse = Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) // 벽과 지붕의 거리 const hypotenuse = Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) // 벽과 지붕의 거리
const addHipX2 = Math.sign(midX - midWallX) * (alpha / hypotenuse) * (currentRoof.length / 2) // 추녀마루의 X 너비 const hipX2 = Math.round(midX + -1 * (alpha / hypotenuse) * (currentRoof.length / 2))
const addHipY2 = Math.sign(midY - midWallY) * (beta / hypotenuse) * (currentRoof.length / 2) // 추녀마루의 Y 너비 const hipY2 = Math.round(midY + -1 * (beta / hypotenuse) * (currentRoof.length / 2))
let hipX2 = 0
let hipY2 = 0
const innerLines = canvas const innerLines = canvas
?.getObjects() ?.getObjects()
@ -2265,28 +2203,27 @@ const changeEavesRoof = (currentRoof, canvas) => {
if (ridgeLines.length > 0) { if (ridgeLines.length > 0) {
const ridge = ridgeLines[0] const ridge = ridgeLines[0]
console.log(currentRoof.attributes.ridgeCoordinate)
console.log('ridge.x1 : ', ridge.x1, 'ridge.y1 : ', ridge.y1, 'ridge.x2 : ', ridge.x2, 'ridge.y2 : ', ridge.y2)
if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) { if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) {
ridge.set({ ridge.set({
x1: midX + addHipX2, x1: hipX2,
y1: midY + addHipY2, y1: hipY2,
x2: ridge.x2, x2: ridge.x2,
y2: ridge.y2, y2: ridge.y2,
}) })
currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 } currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 }
hipX2 = midX + addHipX2
hipY2 = midY + addHipY2
} }
if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) { if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) {
ridge.set({ ridge.set({
x1: ridge.x1, x1: ridge.x1,
y1: ridge.y1, y1: ridge.y1,
x2: midX - addHipX2, x2: hipX2,
y2: midY - addHipY2, y2: hipY2,
}) })
currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
hipX2 = midX - addHipX2
hipY2 = midY - addHipY2
} }
console.log('ridge.x1 : ', ridge.x1, 'ridge.y1 : ', ridge.y1, 'ridge.x2 : ', ridge.x2, 'ridge.y2 : ', ridge.y2)
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
} }
@ -2296,6 +2233,8 @@ const changeEavesRoof = (currentRoof, canvas) => {
canvas.remove(hip) canvas.remove(hip)
}) })
canvas?.renderAll()
const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
@ -2484,7 +2423,7 @@ const changeGableRoof = (currentRoof, canvas) => {
const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180))
hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10
hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2)))
roof.innerLines.push(hip1) // roof.innerLines.push(hip1)
let hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX, midY], { let hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX, midY], {
fontSize: roof.fontSize, fontSize: roof.fontSize,
@ -2503,7 +2442,11 @@ const changeGableRoof = (currentRoof, canvas) => {
const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180))
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2)))
roof.innerLines.push(hip2) // roof.innerLines.push(hip2)
hip1.set({ visible: false })
hip1.setViewLengthText(false)
hip2.set({ visible: false })
hip2.setViewLengthText(false)
canvas?.renderAll() canvas?.renderAll()
} }
} }
@ -2949,7 +2892,6 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10
gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10
canvas?.add(gable3) canvas?.add(gable3)
// roof.innerLines.push(gable3) // roof.innerLines.push(gable3)
const hip1 = new QLine([currentRoof.x1, currentRoof.y1, gable1.x1, gable1.y1], { const hip1 = new QLine([currentRoof.x1, currentRoof.y1, gable1.x1, gable1.y1], {