diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 4ed06608..47a923a3 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -712,7 +712,7 @@ export const drawShedRoof = (roofId, canvas) => { export const drawRidgeRoof = (roofId, canvas) => { const roof = canvas?.getObjects().find((object) => object.id === roofId) - const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) + const hasNonParallelLines = roof.lines.filter((line) => Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1) if (hasNonParallelLines.length > 0) { alert('대각선이 존재합니다.') return @@ -721,6 +721,7 @@ export const drawRidgeRoof = (roofId, canvas) => { drawHips(roof, canvas) connectLinePoint(roof, canvas) modifyRidge(roof, canvas) + drawCenterLine(roof, canvas) } /** @@ -1532,7 +1533,8 @@ const changeEavesRoof = (currentRoof, canvas) => { line.name !== LINE_TYPE.SUBLINE.RIDGE && line.name !== LINE_TYPE.SUBLINE.HIP && line.name !== LINE_TYPE.SUBLINE.VALLEY && - line.name !== OUTER_LINE_TYPE.OUTER_LINE, + line.name !== OUTER_LINE_TYPE.OUTER_LINE && + line.name !== 'wallLine', ) .forEach((line) => { roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id) @@ -1704,7 +1706,8 @@ const changeGableRoof = (currentRoof, canvas) => { line.name !== LINE_TYPE.SUBLINE.RIDGE && line.name !== LINE_TYPE.SUBLINE.HIP && line.name !== LINE_TYPE.SUBLINE.VALLEY && - line.name !== OUTER_LINE_TYPE.OUTER_LINE, + line.name !== OUTER_LINE_TYPE.OUTER_LINE && + line.name !== 'wallLine', ) .forEach((line) => { roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id) @@ -1890,7 +1893,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { line.name !== LINE_TYPE.SUBLINE.RIDGE && line.name !== LINE_TYPE.SUBLINE.HIP && line.name !== LINE_TYPE.SUBLINE.VALLEY && - line.name !== OUTER_LINE_TYPE.OUTER_LINE, + line.name !== OUTER_LINE_TYPE.OUTER_LINE && + line.name !== 'wallLine', ) .forEach((line) => { roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id) @@ -2127,7 +2131,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { line.name !== LINE_TYPE.SUBLINE.RIDGE && line.name !== LINE_TYPE.SUBLINE.HIP && line.name !== LINE_TYPE.SUBLINE.VALLEY && - line.name !== OUTER_LINE_TYPE.OUTER_LINE, + line.name !== OUTER_LINE_TYPE.OUTER_LINE && + line.name !== 'wallLine', ) .forEach((line) => { roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id) @@ -2407,7 +2412,8 @@ const changeWallRoof = (currentRoof, canvas) => { line.name !== LINE_TYPE.SUBLINE.RIDGE && line.name !== LINE_TYPE.SUBLINE.HIP && line.name !== LINE_TYPE.SUBLINE.VALLEY && - line.name !== OUTER_LINE_TYPE.OUTER_LINE, + line.name !== OUTER_LINE_TYPE.OUTER_LINE && + line.name !== 'wallLine', ) .forEach((line) => { roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id) @@ -2702,6 +2708,187 @@ const reDrawPolygon = (polygon, canvas) => { return newPolygon } +const drawCenterLine = (roof, canvas) => { + const roofLines = roof.lines + roofLines.forEach((currentRoof) => { + const hips = roof.innerLines.filter( + (line) => (currentRoof.x1 === line.x1 && currentRoof.y1 === line.y1) || (currentRoof.x2 === line.x1 && currentRoof.y2 === line.y1), + ) + const ridge = roof.innerLines + .filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE) + .filter((line) => { + if (currentRoof.x1 === currentRoof.x2) { + if (line.x1 === line.x2) { + return line + } + } else { + if (line.y1 === line.y2) { + return line + } + } + }) + .reduce((prev, current) => { + let currentDistance, prevDistance + if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) { + currentDistance = Math.abs(currentRoof.y1 - current.y1) + prevDistance = prev ? Math.abs(currentRoof.y1 - prev.y1) : Infinity + } else { + currentDistance = Math.abs(currentRoof.y1 - current.y2) + prevDistance = prev ? Math.abs(currentRoof.y1 - current.y2) : Infinity + } + return prevDistance < currentDistance ? prev : current + }, null) + let points = [] + if (hips.length === 2 && Math.abs(hips[0].x2 - hips[1].x2) < 1 && Math.abs(hips[0].y2 - hips[1].y2) < 1) { + // console.log('삼각') + const x1 = (currentRoof.x1 + currentRoof.x2) / 2 + const y1 = (currentRoof.y1 + currentRoof.y2) / 2 + points.push(x1, y1, hips[0].x2, hips[0].y2) + } else { + // console.log('삼각 아님') + if ( + ((ridge.x1 === hips[0].x2 && ridge.y1 === hips[0].y2) || (ridge.x2 === hips[0].x2 && ridge.y2 === hips[0].y2)) && + ((ridge.x1 === hips[1].x2 && ridge.y1 === hips[1].y2) || (ridge.x2 === hips[1].x2 && ridge.y2 === hips[1].y2)) + ) { + //사각이면 마루와 현재 라인 사이에 길이를 구한다 + // console.log('사각') + if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) { + const yPoints = [currentRoof.y1, currentRoof.y2, ridge.y1, ridge.y2].sort((a, b) => a - b) + const x1 = (currentRoof.x1 + currentRoof.x2) / 2 + const x2 = (ridge.x1 + ridge.x2) / 2 + const y = (yPoints[1] + yPoints[2]) / 2 + if ( + ((currentRoof.y1 <= y && y <= currentRoof.y2) || (currentRoof.y2 <= y && y <= currentRoof.y1)) && + ((ridge.y1 <= y && y <= ridge.y2) || (ridge.y2 <= y && y <= ridge.y1)) + ) { + points.push(x1, y, x2, y) + } + } else { + const xPoints = [currentRoof.x1, currentRoof.x2, ridge.x1, ridge.x2].sort((a, b) => a - b) + const y1 = (currentRoof.y1 + currentRoof.y2) / 2 + const y2 = (ridge.y1 + ridge.y2) / 2 + const x = (xPoints[1] + xPoints[2]) / 2 + if ( + ((currentRoof.x1 <= x && x <= currentRoof.x2) || (currentRoof.x2 <= x && x <= currentRoof.x1)) && + ((ridge.x1 <= x && x <= ridge.x2) || (ridge.x2 <= x && x <= ridge.x1)) + ) { + points.push(x, y1, x, y2) + } + } + } else { + //사각 아님 + if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) { + let xPoints = [] + xPoints.push(ridge?.x1, ridge?.x2) + hips.forEach((hip) => { + xPoints.push(hip.x2) + }) + let maxPoint = xPoints.reduce((prev, current) => { + const currentDistance = Math.abs(currentRoof.x1 - current) + const prevDistance = prev ? Math.abs(currentRoof.x1 - prev) : 0 + return prevDistance > currentDistance ? prev : current + }, null) + + xPoints = xPoints.filter((point) => point === maxPoint) + + let oppositeLine + if (xPoints.length === 1) { + if (ridge?.x1 === xPoints[0] || ridge?.x2 === xPoints[0]) { + oppositeLine = ridge + } + if (oppositeLine === undefined) { + oppositeLine = hips.find((hip) => hip.x2 === xPoints[0]) + } + points.push(currentRoof.x1, oppositeLine.y2, oppositeLine.x2, oppositeLine.y2) + } else if (xPoints.length > 1) { + xPoints = [...new Set(xPoints)] // 중복제거 + if (ridge.length > 0) { + let boolX1 = xPoints.some((x) => x === ridge.x1) + let boolX2 = xPoints.some((x) => x === ridge.x2) + if (boolX1 && boolX2) { + oppositeLine = ridge + } + if (oppositeLine) { + const sortPoints = [currentRoof.y1, currentRoof.y2, oppositeLine.y1, oppositeLine.y2].sort((a, b) => a - b) + const y = (sortPoints[1] + sortPoints[2]) / 2 + if ( + ((currentRoof.y1 <= y && y <= currentRoof.y2) || (currentRoof.y2 <= y && y <= currentRoof.y1)) && + ((oppositeLine.y1 <= y && y <= oppositeLine.y2) || (oppositeLine.y2 <= y && y <= oppositeLine.y1)) + ) { + points.push(currentRoof.x1, y, oppositeLine.x1, y) + } + } + } + } + } else { + let yPoints = [] + yPoints.push(ridge?.y1, ridge?.y2) + hips.forEach((hip) => { + yPoints.push(hip.y2) + }) + const maxPoint = yPoints.reduce((prev, current) => { + const currentDistance = Math.abs(currentRoof.y1 - current) + const prevDistance = prev ? Math.abs(currentRoof.y1 - prev) : 0 + return prevDistance > currentDistance ? prev : current + }) + yPoints = yPoints.filter((y) => y === maxPoint) + + let oppositeLine + if (yPoints.length === 1) { + if (ridge?.y1 === yPoints[0] || ridge?.y2 === yPoints[0]) { + oppositeLine = ridge + } + if (oppositeLine === undefined) { + oppositeLine = hips.find((hip) => hip.y2 === yPoints[0]) + } + points.push(oppositeLine.x2, currentRoof.y1, oppositeLine.x2, oppositeLine.y2) + } else if (yPoints.length > 1) { + let boolY1 = yPoints.some((y) => y === ridge.y1) + let boolY2 = yPoints.some((y) => y === ridge.y2) + if (boolY1 && boolY2) { + oppositeLine = ridge + } + if (oppositeLine) { + const sortPoints = [currentRoof.x1, currentRoof.x2, oppositeLine.x1, oppositeLine.x2].sort((a, b) => a - b) + const x = (sortPoints[1] + sortPoints[2]) / 2 + if ( + ((currentRoof.x1 <= x && x <= currentRoof.x2) || (currentRoof.x2 <= x && x <= currentRoof.x1)) && + ((oppositeLine.x1 <= x && x <= oppositeLine.x2) || (oppositeLine.x2 <= x && x <= oppositeLine.x1)) + ) { + points.push(x, currentRoof.y1, x, oppositeLine.y1) + } + } + } + } + } + } + if (points !== null) { + const pitchSizeLine = new QLine(points, { + stroke: '#000000', + strokeWidth: 2, + strokeDashArray: [5, 5], + selectable: false, + fontSize: roof.fontSize, + attributes: { + roofId: roof.id, + type: 'pitchSizeLine', + }, + }) + canvas.add(pitchSizeLine) + canvas.renderAll() + + const adjust = Math.sqrt( + Math.pow(Math.round(Math.abs(pitchSizeLine.x1 - pitchSizeLine.x2) * 10), 2) + + Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), + ) + const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree + const height = Math.tan(currentDegree * (Math.PI / 180)) * adjust + const lengthText = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2))) + pitchSizeLine.setLengthText(lengthText) + } + }) +} + function createRoofMarginPolygon(polygon, lines, arcSegments = 0) { const offsetEdges = []