Merge branch 'feature/jaeyoung' of https://git.hanasys.jp/qcast3/qcast-front into feature/jaeyoung

This commit is contained in:
hyojun.choi 2025-05-13 15:22:19 +09:00
commit a3b25c3403

View File

@ -821,8 +821,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
let { x1, y1, x2, y2 } = currentLine let { x1, y1, x2, y2 } = currentLine
if (currentAngle !== prevAngle) { if (currentAngle !== prevAngle || (currentAngle === prevAngle && currentLine.attributes.type !== prevLine.attributes.type)) {
if (currentAngle === nextAngle) { if (currentAngle === nextAngle && currentLine.attributes.type === nextLine.attributes.type) {
let nextIndex = baseLines.findIndex((line) => line === nextLine) let nextIndex = baseLines.findIndex((line) => line === nextLine)
while (nextIndex !== index) { while (nextIndex !== index) {
const checkNextLine = baseLines[(nextIndex + 1 + baseLines.length) % baseLines.length] const checkNextLine = baseLines[(nextIndex + 1 + baseLines.length) % baseLines.length]
@ -840,6 +840,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} }
}) })
console.log('drawBaseLines : ', drawBaseLines)
/** baseLine을 기준으로 확인용 polygon 작성 */ /** baseLine을 기준으로 확인용 polygon 작성 */
const checkWallPolygon = new QPolygon(baseLinePoints, {}) const checkWallPolygon = new QPolygon(baseLinePoints, {})
@ -1035,6 +1037,43 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const currentMidX = Big(x1).plus(Big(x2)).div(2).plus(Big(prevVectorX).times(currentLine.attributes.offset)) const currentMidX = Big(x1).plus(Big(x2)).div(2).plus(Big(prevVectorX).times(currentLine.attributes.offset))
const currentMidY = Big(y1).plus(Big(y2)).div(2).plus(Big(prevVectorY).times(currentLine.attributes.offset)) const currentMidY = Big(y1).plus(Big(y2)).div(2).plus(Big(prevVectorY).times(currentLine.attributes.offset))
/** 마루 반대 좌표*/
let oppositeMidX = currentMidX,
oppositeMidY = currentMidY
if (prevAngle === beforePrevAngle || nextAngle === afterNextAngle) {
console.log('지붕선 분할 : start')
const checkLine1 = new fabric.Line([prevLine.x1, prevLine.y1, prevLine.x2, prevLine.y2], {
stroke: 'red',
strokeWidth: 4,
parentId: roofId,
name: 'checkLine',
})
const checkLine2 = new fabric.Line([nextLine.x1, nextLine.y1, nextLine.x2, nextLine.y2], {
stroke: 'blue',
strokeWidth: 4,
parentId: roofId,
name: 'checkLine',
})
const checkPoint = new fabric.Circle({
left: currentMidX.toNumber(),
top: currentMidY.toNumber(),
radius: 5,
fill: 'red',
parentId: roofId,
name: 'checkPoint',
})
canvas.add(checkLine1)
canvas.add(checkLine2)
canvas.add(checkPoint)
canvas.renderAll()
if (currentVectorX === 0) {
} else {
}
console.log('지붕선 분할 : end')
} else {
if (beforePrevBaseLine === afterNextBaseLine) { if (beforePrevBaseLine === afterNextBaseLine) {
const afterNextMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2) const afterNextMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2)
const afterNextMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2) const afterNextMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2)
@ -1093,7 +1132,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const intersection1 = findRoofIntersection(roof, checkHip1, { x: oppositeMidX.plus(addOppositeX1), y: oppositeMidY.plus(addOppositeY1) }) const intersection1 = findRoofIntersection(roof, checkHip1, { x: oppositeMidX.plus(addOppositeX1), y: oppositeMidY.plus(addOppositeY1) })
const intersection2 = findRoofIntersection(roof, checkHip2, { x: oppositeMidX.plus(addOppositeX2), y: oppositeMidY.plus(addOppositeY2) }) const intersection2 = findRoofIntersection(roof, checkHip2, { x: oppositeMidX.plus(addOppositeX2), y: oppositeMidY.plus(addOppositeY2) })
const afterNextDegree = afterNextLine.attributes.pitch > 0 ? getDegreeByChon(afterNextLine.attributes.pitch) : afterNextLine.attributes.degree const afterNextDegree =
afterNextLine.attributes.pitch > 0 ? getDegreeByChon(afterNextLine.attributes.pitch) : afterNextLine.attributes.degree
if (intersection1) { if (intersection1) {
const hipLine = drawHipLine( const hipLine = drawHipLine(
@ -1152,8 +1192,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} else { } else {
const vectorMidX = Math.sign(Big(nextLine.x2).minus(nextLine.x1)) const vectorMidX = Math.sign(Big(nextLine.x2).minus(nextLine.x1))
const vectorMidY = Math.sign(Big(nextLine.y2).minus(nextLine.y1)) const vectorMidY = Math.sign(Big(nextLine.y2).minus(nextLine.y1))
let oppositeMidX = currentMidX,
oppositeMidY = currentMidY
let prevOppositeMidX, prevOppositeMidY, nextOppositeMidX, nextOppositeMidY let prevOppositeMidX, prevOppositeMidY, nextOppositeMidX, nextOppositeMidY
const beforePrevOffset = const beforePrevOffset =
currentAngle === beforePrevAngle currentAngle === beforePrevAngle
@ -1267,7 +1306,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
if (checkPrevSize.gt(checkNextSize)) { if (checkPrevSize.gt(checkNextSize)) {
if (nextHipCoords) { if (nextHipCoords) {
let intersectPoints = [] let intersectPoints = []
const hipEdge = { vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 }, vertex2: { x: nextHipCoords.x1, y: nextHipCoords.y1 } } const hipEdge = {
vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 },
vertex2: { x: nextHipCoords.x1, y: nextHipCoords.y1 },
}
/** 외벽선에서 라인 겹치는 경우에 대한 확인*/ /** 외벽선에서 라인 겹치는 경우에 대한 확인*/
roof.lines.forEach((line) => { roof.lines.forEach((line) => {
@ -1278,7 +1320,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
Math.sign(nextHipCoords.x2 - nextHipCoords.x1) === Math.sign(nextHipCoords.x2 - intersection.x) && Math.sign(nextHipCoords.x2 - nextHipCoords.x1) === Math.sign(nextHipCoords.x2 - intersection.x) &&
Math.sign(nextHipCoords.y2 - nextHipCoords.y1) === Math.sign(nextHipCoords.y2 - intersection.y) Math.sign(nextHipCoords.y2 - nextHipCoords.y1) === Math.sign(nextHipCoords.y2 - intersection.y)
) { ) {
const intersectEdge = { vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 }, vertex2: { x: intersection.x, y: intersection.y } } const intersectEdge = {
vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 },
vertex2: { x: intersection.x, y: intersection.y },
}
const is = edgesIntersection(intersectEdge, lineEdge) const is = edgesIntersection(intersectEdge, lineEdge)
if (!is.isIntersectionOutside) { if (!is.isIntersectionOutside) {
const intersectSize = Big(nextHipCoords.x2) const intersectSize = Big(nextHipCoords.x2)
@ -1323,7 +1368,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} else { } else {
if (prevHipCoords) { if (prevHipCoords) {
let intersectPoints = [] let intersectPoints = []
const hipEdge = { vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 }, vertex2: { x: prevHipCoords.x1, y: prevHipCoords.y1 } } const hipEdge = {
vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 },
vertex2: { x: prevHipCoords.x1, y: prevHipCoords.y1 },
}
/** 외벽선에서 라인 겹치는 경우에 대한 확인*/ /** 외벽선에서 라인 겹치는 경우에 대한 확인*/
roof.lines.forEach((line) => { roof.lines.forEach((line) => {
@ -1334,7 +1382,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
Math.sign(prevHipCoords.x2 - prevHipCoords.x1) === Math.sign(prevHipCoords.x2 - intersection.x) && Math.sign(prevHipCoords.x2 - prevHipCoords.x1) === Math.sign(prevHipCoords.x2 - intersection.x) &&
Math.sign(prevHipCoords.y2 - prevHipCoords.y1) === Math.sign(prevHipCoords.y2 - intersection.y) Math.sign(prevHipCoords.y2 - prevHipCoords.y1) === Math.sign(prevHipCoords.y2 - intersection.y)
) { ) {
const intersectEdge = { vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 }, vertex2: { x: intersection.x, y: intersection.y } } const intersectEdge = {
vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 },
vertex2: { x: intersection.x, y: intersection.y },
}
const is = edgesIntersection(intersectEdge, lineEdge) const is = edgesIntersection(intersectEdge, lineEdge)
if (!is.isIntersectionOutside) { if (!is.isIntersectionOutside) {
const intersectSize = Big(prevHipCoords.x2) const intersectSize = Big(prevHipCoords.x2)
@ -1378,7 +1429,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
oppositeMidY = prevOppositeMidY oppositeMidY = prevOppositeMidY
oppositeMidX = prevOppositeMidX oppositeMidX = prevOppositeMidX
} }
}
if (baseRidgeCount < getMaxRidge(baseLines.length)) { if (baseRidgeCount < getMaxRidge(baseLines.length)) {
/** 마루가 맞은편 외벽선에 닿는 경우 해당 부분까지로 한정한다. */ /** 마루가 맞은편 외벽선에 닿는 경우 해당 부분까지로 한정한다. */
const ridgeEdge = { const ridgeEdge = {
@ -2430,9 +2481,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} else { } else {
if (currentAngle !== beforePrevAngle && currentAngle !== afterNextAngle && beforePrevLine !== afterNextLine) { if (currentAngle !== beforePrevAngle && currentAngle !== afterNextAngle && beforePrevLine !== afterNextLine) {
console.log('4각 아님') console.log('4각 아님')
// console.log('currentLine : ', currentLine.attributes.planeSize)
// console.log('beforePrevLine : ', beforePrevLine)
// console.log('afterNextLine : ', afterNextLine)
const beforePrevX1 = beforePrevLine.x1, const beforePrevX1 = beforePrevLine.x1,
beforePrevY1 = beforePrevLine.y1, beforePrevY1 = beforePrevLine.y1,
beforePrevX2 = beforePrevLine.x2, beforePrevX2 = beforePrevLine.x2,
@ -2707,6 +2755,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
/** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/ /** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/
if (intersectPoints && intersectPoints.intersection) { if (intersectPoints && intersectPoints.intersection) {
console.log('prevDegree', prevDegree, 'currentDegree', currentDegree)
prevHipLine = drawHipLine( prevHipLine = drawHipLine(
[intersectPoints.intersection.x, intersectPoints.intersection.y, prevEndPoint.x.toNumber(), prevEndPoint.y.toNumber()], [intersectPoints.intersection.x, intersectPoints.intersection.y, prevEndPoint.x.toNumber(), prevEndPoint.y.toNumber()],
canvas, canvas,
@ -2803,8 +2853,53 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} }
} }
// console.log('prevHipLine : ', prevHipLine) console.log('prevHipLine : ', prevHipLine)
// console.log('nextHipLine : ', nextHipLine) console.log('nextHipLine : ', nextHipLine)
/** 두 선이 교차하면 해당 포인트까지로 선 조정*/
if (prevHipLine !== undefined && nextHipLine !== undefined) {
const prevEdge = { vertex1: { x: prevHipLine.x1, y: prevHipLine.y1 }, vertex2: { x: prevHipLine.x2, y: prevHipLine.y2 } }
const nextEdge = { vertex1: { x: nextHipLine.x1, y: nextHipLine.y1 }, vertex2: { x: nextHipLine.x2, y: nextHipLine.y2 } }
const intersection = edgesIntersection(prevEdge, nextEdge)
console.log('intersection : ', intersection)
if (intersection) {
const checkPoint = new fabric.Circle({
left: intersection.x,
top: intersection.y,
radius: 4,
fill: 'yellow',
parentId: roofId,
name: 'checkPoint',
})
canvas.add(checkPoint)
canvas.renderAll()
/** 포인트 조정*/
baseHipLines
.filter((line) => line.line === prevHipLine || line.line === nextHipLine)
.forEach((line) => {
line.x2 = intersection.x
line.y2 = intersection.y
line.line.set({ x2: intersection.x, y2: intersection.y })
})
prevHipLine.x2 = intersection.x
prevHipLine.y2 = intersection.y
const prevSize = reCalculateSize(prevHipLine)
prevHipLine.attributes.planeSize = prevSize.planeSize
prevHipLine.attributes.actualSize = prevSize.actualSize
prevHipLine.fire('modified')
nextHipLine.x2 = intersection.x
nextHipLine.y2 = intersection.y
const nextSize = reCalculateSize(nextHipLine)
nextHipLine.attributes.planeSize = nextSize.planeSize
nextHipLine.attributes.actualSize = nextSize.actualSize
nextHipLine.fire('modified')
canvas.renderAll()
}
}
/** 두 추녀마루가 한점에서 만나는 경우 해당 점을 기점으로 마루를 작성한다.*/ /** 두 추녀마루가 한점에서 만나는 경우 해당 점을 기점으로 마루를 작성한다.*/
if ( if (
prevHipLine !== undefined && prevHipLine !== undefined &&
@ -2812,9 +2907,80 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
Big(prevHipLine.x2).minus(Big(nextHipLine.x2)).abs().lte(1) && Big(prevHipLine.x2).minus(Big(nextHipLine.x2)).abs().lte(1) &&
Big(prevHipLine.y2).minus(Big(nextHipLine.y2)).abs().lte(1) Big(prevHipLine.y2).minus(Big(nextHipLine.y2)).abs().lte(1)
) { ) {
console.log('마루 작성')
const startPoint = { x: prevHipLine.x2, y: prevHipLine.y2 } const startPoint = { x: prevHipLine.x2, y: prevHipLine.y2 }
let ridgeSize = 0
const currentMidX = Big(currentLine.x2).plus(Big(currentLine.x1)).div(2)
const currentMidY = Big(currentLine.y2).plus(Big(currentLine.y1)).div(2)
const xVector = Big(currentMidX).minus(Big(startPoint.x)).round(0, Big.roundDown)
const yVector = Big(currentMidY).minus(Big(startPoint.y)).round(0, Big.roundDown)
console.log('beforePrevLine', beforePrevLine)
if (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) {
console.log('박공지붕 확인 후 마루 작성 ')
const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line
const oppositeAngle = calculateAngle(oppositeLine.startPoint, oppositeLine.endPoint)
console.log('currentAngle', currentAngle, 'oppositeAngle', oppositeAngle)
let checkEdge
if (Math.sign(oppositeLine.x1 - oppositeLine.x2) === 0) {
checkEdge = { vertex1: startPoint, vertex2: { x: oppositeLine.x1, y: startPoint.y } }
} else {
checkEdge = { vertex1: startPoint, vertex2: { x: startPoint.x, y: oppositeLine.y1 } }
}
if (currentAngle === oppositeAngle) {
const oppositeEdge = { vertex1: { x: oppositeLine.x1, y: oppositeLine.y1 }, vertex2: { x: oppositeLine.x2, y: oppositeLine.y2 } }
const intersection = edgesIntersection(oppositeEdge, checkEdge)
console.log('intersection', intersection)
if (intersection) {
ridgeSize = Big(intersection.x)
.minus(Big(startPoint.x))
.pow(2)
.plus(Big(intersection.y).minus(Big(startPoint.y)).pow(2))
.sqrt()
}
console.log('aaa')
} else {
const intersectPoints = []
roof.lines
.filter(
(line) =>
Math.sign(oppositeLine.x1 - oppositeLine.x2) === Math.sign(line.x1 - line.x2) &&
Math.sign(oppositeLine.y1 - oppositeLine.y2) === Math.sign(line.y1 - line.y2),
)
.forEach((line) => {
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
const intersection = edgesIntersection(lineEdge, checkEdge)
console.log('intersection', intersection)
if (intersection) {
const checkPoint = new fabric.Circle({
left: intersection.x,
top: intersection.y,
radius: 4,
fill: 'red',
parentId: roofId,
name: 'checkPoint',
})
canvas.add(checkPoint)
canvas.renderAll()
const size = Big(startPoint.x)
.minus(Big(intersection.x))
.pow(2)
.plus(Big(startPoint.y).minus(Big(intersection.y)).pow(2))
.sqrt()
.toNumber()
intersectPoints.push({ intersection, size })
}
})
intersectPoints.sort((a, b) => a.size - b.size)
console.log('intersectPoints', intersectPoints)
if (intersectPoints.length > 0) {
ridgeSize = Big(intersectPoints[0].size)
}
console.log('bbb')
}
} else {
console.log('마루 작성')
// baseLines에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산 // baseLines에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산
let minX = Infinity let minX = Infinity
let maxX = -Infinity let maxX = -Infinity
@ -2841,12 +3007,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.plus(Big(maxY).minus(Big(minY)).pow(2)) .plus(Big(maxY).minus(Big(minY)).pow(2))
.sqrt() .sqrt()
const currentMidX = Big(currentLine.x2).plus(Big(currentLine.x1)).div(2)
const currentMidY = Big(currentLine.y2).plus(Big(currentLine.y1)).div(2)
const xVector = Big(currentMidX).minus(Big(startPoint.x)).round(0, Big.roundDown)
const yVector = Big(currentMidY).minus(Big(startPoint.y)).round(0, Big.roundDown)
const checkEdges = { const checkEdges = {
vertex1: { x: startPoint.x, y: startPoint.y }, vertex1: { x: startPoint.x, y: startPoint.y },
vertex2: { vertex2: {
@ -2855,15 +3015,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
}, },
} }
const checkLine = new fabric.Line([checkEdges.vertex1.x, checkEdges.vertex1.y, checkEdges.vertex2.x, checkEdges.vertex2.y], {
stroke: 'purple',
strokeWidth: 2,
parentId: roof.id,
name: 'checkLine',
})
canvas.add(checkLine)
canvas.renderAll()
/** 맞은편 벽 까지의 길이 판단을 위한 교차되는 line*/ /** 맞은편 벽 까지의 길이 판단을 위한 교차되는 line*/
const intersectBaseLine = [] const intersectBaseLine = []
baseLines baseLines
@ -2912,21 +3063,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
const intersection = edgesIntersection(checkEdges, lineEdge) const intersection = edgesIntersection(checkEdges, lineEdge)
if (intersection) { if (intersection) {
/* const intersectPoint = new fabric.Circle({
left: intersection.x - 2,
top: intersection.y - 2,
radius: 4,
fill: 'green',
parentId: roof.id,
})
canvas.add(intersectPoint)
canvas.renderAll()*/
intersectBaseLine.push({ intersection, line }) intersectBaseLine.push({ intersection, line })
} }
}) })
// console.log('intersectBaseLine : ', intersectBaseLine)
/** 맞은편 라인 */ /** 맞은편 라인 */
const oppositeLine = intersectBaseLine.reduce((prev, current) => { const oppositeLine = intersectBaseLine.reduce((prev, current) => {
const prevDistance = Big(prev.intersection.x) const prevDistance = Big(prev.intersection.x)
@ -2942,8 +3082,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
return prevDistance < currentDistance ? prev : current return prevDistance < currentDistance ? prev : current
}, intersectBaseLine[0]) }, intersectBaseLine[0])
console.log('oppositeLine : ', oppositeLine)
/** 맞은편 라인까지의 길이 = 전체 길이 - 현재라인의 길이 */ /** 맞은편 라인까지의 길이 = 전체 길이 - 현재라인의 길이 */
const oppositeSize = oppositeLine const oppositeSize = oppositeLine
? Big(oppositeLine.intersection.x) ? Big(oppositeLine.intersection.x)
@ -2955,22 +3093,15 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.round(1) .round(1)
: Infinity : Infinity
// console.log('startPoint : ', startPoint, 'currentSize : ', currentSize.toNumber())
/** 이전, 다음 라인중 길이가 짧은 길이*/ /** 이전, 다음 라인중 길이가 짧은 길이*/
/*const lineMinSize =
prevLine.attributes.planeSize < nextLine.attributes.planeSize
? Big(prevLine.attributes.planeSize).div(10)
: Big(nextLine.attributes.planeSize).div(10)*/
const lineMinSize = prevBaseLine.size < nextBaseLine.size ? Big(prevBaseLine.size).div(10) : Big(nextBaseLine.size).div(10) const lineMinSize = prevBaseLine.size < nextBaseLine.size ? Big(prevBaseLine.size).div(10) : Big(nextBaseLine.size).div(10)
/** 마루의 길이는 이전 다음 라인중 짧은것의 길이와 현재라인부터 맞은편 라인까지의 길이에서 현재 라인의 길이를 뺀 것중 짧은 길이 */ /** 마루의 길이는 이전 다음 라인중 짧은것의 길이와 현재라인부터 맞은편 라인까지의 길이에서 현재 라인의 길이를 뺀 것중 짧은 길이 */
const ridgeSize = Big(Math.min(oppositeSize, lineMinSize)) ridgeSize = Big(Math.min(oppositeSize, lineMinSize))
}
// console.log('oppositeSize : ', oppositeSize, 'lineMinSize : ', lineMinSize.toNumber(), 'ridgeSize : ', ridgeSize.toNumber())
console.log('ridgeSize', ridgeSize)
if (ridgeSize.gt(0) && baseRidgeCount < getMaxRidge(baseLines.length)) { if (ridgeSize.gt(0) && baseRidgeCount < getMaxRidge(baseLines.length)) {
// console.log('baseRidgeCount : ', baseRidgeCount)
const points = [ const points = [
startPoint.x, startPoint.x,
startPoint.y, startPoint.y,
@ -2996,16 +3127,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
return return
} }
/* const checkMidLine = new fabric.Line(points, {
stroke: 'blue',
strokeWidth: 2,
parentId: roof.id,
})
canvas.add(checkMidLine)
canvas.renderAll()*/
// console.log('points : ', points)
const ridgeLine = drawRidgeLine(points, canvas, roof, textMode) const ridgeLine = drawRidgeLine(points, canvas, roof, textMode)
if (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) {
baseGableRidgeLines.push(ridgeLine)
} else {
baseRidgeLines.push(ridgeLine) baseRidgeLines.push(ridgeLine)
}
baseRidgeCount = baseRidgeCount + 1 baseRidgeCount = baseRidgeCount + 1
/** 포인트 조정*/ /** 포인트 조정*/
@ -3014,13 +3141,234 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.forEach((line) => { .forEach((line) => {
line.x2 = points[0] line.x2 = points[0]
line.y2 = points[1] line.y2 = points[1]
line.line.set({ x2: points[0], y2: points[1] })
// line.line.fire('modified')
}) })
prevHipLine.x2 = points[0] prevHipLine.x2 = points[0]
prevHipLine.y2 = points[1] prevHipLine.y2 = points[1]
const prevSize = reCalculateSize(prevHipLine)
prevHipLine.attributes.planeSize = prevSize.planeSize
prevHipLine.attributes.actualSize = prevSize.actualSize
prevHipLine.fire('modified')
nextHipLine.x2 = points[0] nextHipLine.x2 = points[0]
nextHipLine.y2 = points[1] nextHipLine.y2 = points[1]
prevHipLine.fire('modified') const nextSize = reCalculateSize(nextHipLine)
nextHipLine.attributes.planeSize = nextSize.planeSize
nextHipLine.attributes.actualSize = nextSize.actualSize
nextHipLine.fire('modified') nextHipLine.fire('modified')
canvas.renderAll()
if (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) {
const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line
const oppositeAngle = calculateAngle(oppositeLine.startPoint, oppositeLine.endPoint)
if (Math.sign(ridgeLine.x1 - ridgeLine.x2) === 0) {
const gableVector = Math.sign(ridgeLine.x1 - oppositeLine.x1)
const prevVector = ridgeLine.x1 === prevHipLine.x1 ? Math.sign(ridgeLine.x1 - prevHipLine.x2) : Math.sign(ridgeLine.x2 - prevHipLine.x1)
const nextVector = ridgeLine.x1 === nextHipLine.x1 ? Math.sign(ridgeLine.x1 - nextHipLine.x2) : Math.sign(ridgeLine.x2 - nextHipLine.x1)
const firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine
const firstDegree =
gableVector === Math.sign(ridgeLine.x1 - prevLine.x1)
? prevLine.attributes.pitch > 0
? getDegreeByChon(prevLine.attributes.pitch)
: prevLine.attributes.degree
: nextLine.attributes.pitch > 0
? getDegreeByChon(nextLine.attributes.pitch)
: nextLine.attributes.degree
const oppositeRoofPoints = [
ridgeLine.x2,
ridgeLine.y2,
ridgeLine.x1 === firstHipLine.x1 ? firstHipLine.x2 : firstHipLine.x1,
ridgeLine.y2,
]
const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, null, firstDegree, firstDegree)
baseHipLines.push({
x1: oppositeRoofLine.x1,
y1: oppositeRoofLine.y1,
x2: oppositeRoofLine.x2,
y2: oppositeRoofLine.y2,
line: oppositeRoofLine,
})
const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
if (ridgeLine.x1 === firstHipLine.x1) {
connectRoofPoints.push(firstHipLine.x2, firstHipLine.y2)
} else {
connectRoofPoints.push(firstHipLine.x1, firstHipLine.y1)
}
const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
baseHipLines.push({
x1: connectRoofLine.x1,
y1: connectRoofLine.y1,
x2: connectRoofLine.x2,
y2: connectRoofLine.y2,
line: connectRoofLine,
})
/** 다른 방향의 추녀마루 */
const secondHipLine = gableVector === prevVector ? nextHipLine : prevHipLine
const secondDegree =
gableVector === Math.sign(ridgeLine.x1 - prevLine.x1)
? nextLine.attributes.pitch > 0
? getDegreeByChon(nextLine.attributes.pitch)
: nextLine.attributes.degree
: prevLine.attributes.pitch > 0
? getDegreeByChon(prevLine.attributes.pitch)
: prevLine.attributes.degree
const intersections = []
const checkEdge = {
vertex1: { x: ridgeLine.x2, y: ridgeLine.y2 },
vertex2: { x: ridgeLine.x1 === secondHipLine.x1 ? secondHipLine.x2 : secondHipLine.x1, y: ridgeLine.y2 },
}
baseGableRidgeLines
.filter((ridge) => ridge !== ridgeLine)
.forEach((ridge) => {
const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
const intersection = edgesIntersection(ridgeEdge, checkEdge)
if (intersection && !intersections.includes(intersection)) {
const size = Big(intersection.x)
.minus(Big(ridgeLine.x2))
.pow(2)
.plus(Big(intersection.y).minus(Big(ridgeLine.y2)).pow(2))
.sqrt()
.toNumber()
intersections.push({ intersection, size, ridge })
}
})
intersections.sort((a, b) => a.size - b.size)
if (intersections.length > 0) {
const intersection = intersections[0].intersection
const intersectRidge = intersections[0].ridge
const oppositeRoofPoints = [ridgeLine.x2, ridgeLine.y2, intersection.x, intersection.y]
const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, null, secondDegree, secondDegree)
baseHipLines.push({ x1: oppositeLine.x1, y1: oppositeLine.y1, x2: oppositeLine.x2, y2: oppositeLine.y2, line: oppositeRoofLine })
const ridgeVector = Math.sign(ridgeLine.y1 - ridgeLine.y2)
const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
if (ridgeVector === Math.sign(oppositeRoofLine.y1 - intersectRidge.y2)) {
connectRoofPoints.push(intersectRidge.x2, intersectRidge.y2)
} else {
connectRoofPoints.push(intersectRidge.x1, intersectRidge.y1)
}
const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
baseHipLines.push({
x1: connectRoofLine.x1,
y1: connectRoofLine.y1,
x2: connectRoofLine.x2,
y2: connectRoofLine.y2,
line: connectRoofLine,
})
}
} else {
const gableVector = Math.sign(ridgeLine.y1 - oppositeLine.y1)
const prevVector = ridgeLine.y1 === prevHipLine.y1 ? Math.sign(ridgeLine.y1 - prevHipLine.y2) : Math.sign(ridgeLine.y1 - prevHipLine.y1)
const nextVector = ridgeLine.y1 === nextHipLine.y1 ? Math.sign(ridgeLine.y1 - nextHipLine.y2) : Math.sign(ridgeLine.y1 - nextHipLine.y1)
/** 마루와 박공지붕을 연결하기위한 추녀마루 라인 */
const firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine
const firstDegree =
gableVector === Math.sign(ridgeLine.y1 - prevLine.y1)
? prevLine.attributes.pitch > 0
? getDegreeByChon(prevLine.attributes.pitch)
: prevLine.attributes.degree
: nextLine.attributes.pitch > 0
? getDegreeByChon(nextLine.attributes.pitch)
: nextLine.attributes.degree
const oppositeRoofPoints = [
ridgeLine.x2,
ridgeLine.y2,
ridgeLine.x2,
ridgeLine.y1 === firstHipLine.y1 ? firstHipLine.y2 : firstHipLine.y1,
]
const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, null, firstDegree, firstDegree)
baseHipLines.push({
x1: oppositeRoofLine.x1,
y1: oppositeRoofLine.y1,
x2: oppositeRoofLine.x2,
y2: oppositeRoofLine.y2,
line: oppositeRoofLine,
})
const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
if (ridgeLine.y1 === firstHipLine.y1) {
connectRoofPoints.push(firstHipLine.x2, firstHipLine.y2)
} else {
connectRoofPoints.push(firstHipLine.x1, firstHipLine.y1)
}
const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
baseHipLines.push({
x1: connectRoofLine.x1,
y1: connectRoofLine.y1,
x2: connectRoofLine.x2,
y2: connectRoofLine.y2,
line: connectRoofLine,
})
/** 다른 방향의 추녀마루 */
const secondHipLine = gableVector === prevVector ? nextHipLine : prevHipLine
const secondDegree =
gableVector === Math.sign(ridgeLine.y1 - prevLine.y1)
? nextLine.attributes.pitch > 0
? getDegreeByChon(nextLine.attributes.pitch)
: nextLine.attributes.degree
: prevLine.attributes.pitch > 0
? getDegreeByChon(prevLine.attributes.pitch)
: prevLine.attributes.degree
const intersections = []
const checkEdge = {
vertex1: { x: ridgeLine.x2, y: ridgeLine.y2 },
vertex2: { x: ridgeLine.x2, y: ridgeLine.y1 === secondHipLine.y1 ? secondHipLine.y2 : secondHipLine.y1 },
}
baseGableRidgeLines
.filter((ridge) => ridge !== ridgeLine)
.forEach((ridge) => {
const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } }
const intersection = edgesIntersection(ridgeEdge, checkEdge)
if (intersection && !intersections.includes(intersection)) {
const size = Big(intersection.x)
.minus(Big(ridgeLine.x2))
.pow(2)
.plus(Big(intersection.y).minus(Big(ridgeLine.y2)).pow(2))
.sqrt()
.toNumber()
intersections.push({ intersection, size, ridge })
}
})
intersections.sort((a, b) => a.size - b.size)
if (intersections.length > 0) {
const intersection = intersections[0].intersection
const intersectRidge = intersections[0].ridge
const oppositeRoofPoints = [ridgeLine.x2, ridgeLine.y2, intersection.x, intersection.y]
const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, null, secondDegree, secondDegree)
baseHipLines.push({ x1: oppositeLine.x1, y1: oppositeLine.y1, x2: oppositeLine.x2, y2: oppositeLine.y2, line: oppositeRoofLine })
const ridgeVector = Math.sign(ridgeLine.x1 - ridgeLine.x2)
const connectRoofPoints = [oppositeRoofLine.x2, oppositeRoofLine.y2]
if (ridgeVector === Math.sign(oppositeRoofLine.x1 - intersectRidge.x2)) {
connectRoofPoints.push(intersectRidge.x2, intersectRidge.y2)
} else {
connectRoofPoints.push(intersectRidge.x1, intersectRidge.y1)
}
const connectRoofLine = drawRoofLine(connectRoofPoints, canvas, roof, textMode)
baseHipLines.push({
x1: connectRoofLine.x1,
y1: connectRoofLine.y1,
x2: connectRoofLine.x2,
y2: connectRoofLine.y2,
line: connectRoofLine,
})
}
}
}
} }
} }
@ -3956,6 +4304,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
/** hip이 짝수개가 맞다아있는데 마루와 연결되지 않는 포인트를 찾는다. 그려지지 않은 마루를 찾기 위함.*/ /** hip이 짝수개가 맞다아있는데 마루와 연결되지 않는 포인트를 찾는다. 그려지지 않은 마루를 찾기 위함.*/
let noRidgeHipPoints = baseHipLines let noRidgeHipPoints = baseHipLines
.filter((current) => current.x1 !== current.x2 && current.y1 !== current.y2)
.filter((current) => { .filter((current) => {
const lines = baseHipLines const lines = baseHipLines
.filter((line) => line !== current) .filter((line) => line !== current)
@ -3966,43 +4315,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
.filter( .filter(
(current) => (current) =>
baseRidgeLines.filter((line) => (line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2)) baseRidgeLines.filter((line) => (line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2))
.length === 0 &&
baseGableRidgeLines.filter((line) => (line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2))
.length === 0, .length === 0,
) )
noRidgeHipPoints.forEach((current) => { noRidgeHipPoints.forEach((current) => {
/* const checkPoint = new fabric.Circle({
left: current.x2,
top: current.y2,
radius: 4,
fill: 'green',
parentId: roofId,
name: 'checkPoint',
})
canvas.add(checkPoint)
canvas.renderAll()
console.log('noRidgeHipPoints current : ', current.x1, current.y1, current.x2, current.y2)*/
const orthogonalPoints = noRidgeHipPoints.filter((point) => { const orthogonalPoints = noRidgeHipPoints.filter((point) => {
/*const checkPoint1 = new fabric.Circle({
left: point.x2,
top: point.y2,
radius: 4,
fill: 'blue',
parentId: roofId,
name: 'checkPoint',
})
canvas.add(checkPoint1)
canvas.renderAll()
console.log(' orthogonalPoints : ', point.x1, point.y1, point.x2, point.y2)
console.log(
'same point :',
point !== current,
'y point 다름',
current.x2 === point.x2 && current.y2 !== point.y2,
'x point 다름',
current.x2 !== point.x2 && current.y2 === point.y2,
)
canvas.remove(checkPoint1)
canvas.renderAll()*/
if (point !== current && ((current.x2 === point.x2 && current.y2 !== point.y2) || (current.x2 !== point.x2 && current.y2 === point.y2))) { if (point !== current && ((current.x2 === point.x2 && current.y2 !== point.y2) || (current.x2 !== point.x2 && current.y2 === point.y2))) {
return true return true
} }
@ -4017,8 +4336,6 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
const points = [current.x2, current.y2, orthogonalPoints[0].x2, orthogonalPoints[0].y2] const points = [current.x2, current.y2, orthogonalPoints[0].x2, orthogonalPoints[0].y2]
const ridgeLine = drawRidgeLine(points, canvas, roof, textMode) const ridgeLine = drawRidgeLine(points, canvas, roof, textMode)
baseRidgeLines.push(ridgeLine) baseRidgeLines.push(ridgeLine)
/** array에서 object 삭제*/
// noRidgeHipPoints = noRidgeHipPoints.filter((point) => point !== current && point !== orthogonalPoints[0])
} }
}) })
@ -4112,8 +4429,18 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
} }
}) })
console.log('noRidgeHipPoints : ', noRidgeHipPoints)
/** 마루를 그릴수 있는지 찾는다. */ /** 마루를 그릴수 있는지 찾는다. */
noRidgeHipPoints.forEach((hipPoint) => { noRidgeHipPoints.forEach((hipPoint) => {
const checkLine = new fabric.Line([hipPoint.x2, hipPoint.y2, hipPoint.x1, hipPoint.y1], {
stroke: 'red',
strokeWidth: 4,
parentId: roofId,
name: 'checkLine',
})
canvas.add(checkLine)
canvas.renderAll()
const ridgePoints = [] const ridgePoints = []
intersectPoints intersectPoints
.filter( .filter(
@ -4229,11 +4556,13 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
if (distanceX < distanceY) { if (distanceX < distanceY) {
linePoints.push({ intersection: intersectX, intersectPoint }) linePoints.push({ intersection: intersectX, intersectPoint })
} else { }
if (distanceX > distanceY) {
linePoints.push({ intersection: intersectY, intersectPoint }) linePoints.push({ intersection: intersectY, intersectPoint })
} }
}) })
console.log('linePoints : ', linePoints)
const linePoint = linePoints.reduce((prev, current) => { const linePoint = linePoints.reduce((prev, current) => {
const prevDistance = Big(prev.intersection.x) const prevDistance = Big(prev.intersection.x)
.minus(Big(hipPoint.x2)) .minus(Big(hipPoint.x2))
@ -4836,6 +5165,45 @@ const drawRidgeLine = (points, canvas, roof, textMode) => {
return ridge return ridge
} }
/**
* 지붕선을 그린다.
* @param points
* @param canvas
* @param roof
* @param textMode
* @returns {*}
*/
const drawRoofLine = (points, canvas, roof, textMode) => {
const ridge = new QLine(points, {
parentId: roof.id,
fontSize: roof.fontSize,
stroke: '#1083E3',
strokeWidth: 2,
name: LINE_TYPE.SUBLINE.HIP,
textMode: textMode,
attributes: {
roofId: roof.id,
planeSize: calcLinePlaneSize({
x1: points[0],
y1: points[1],
x2: points[2],
y2: points[3],
}),
actualSize: calcLinePlaneSize({
x1: points[0],
y1: points[1],
x2: points[2],
y2: points[3],
}),
},
})
canvas.add(ridge)
ridge.bringToFront()
canvas.renderAll()
return ridge
}
/** /**
* 벡터를 정규화(Normalization)하는 함수 * 벡터를 정규화(Normalization)하는 함수
* @param v * @param v
@ -7701,3 +8069,31 @@ const getSortedPoint = (points) => {
} }
return sortedPoints return sortedPoints
} }
const reCalculateSize = (line) => {
const oldPlaneSize = line.attributes.planeSize
const oldActualSize = line.attributes.actualSize
const theta = Big(Math.acos(Big(oldPlaneSize).div(oldActualSize)))
.times(180)
.div(Math.PI)
console.log('theta : ', theta.toNumber())
const planeSize = calcLinePlaneSize({
x1: line.x1,
y1: line.y1,
x2: line.x2,
y2: line.y2,
})
const actualSize =
planeSize === oldActualSize
? 0
: calcLineActualSize(
{
x1: line.x1,
y1: line.y1,
x2: line.x2,
y2: line.y2,
},
theta,
)
return { planeSize, actualSize }
}