From 8f421d08dab72ac4b24c7eca44ed38842456a4f9 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Mon, 5 Jan 2026 15:11:53 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EB=B3=80=EB=B3=84=EB=A1=9C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=8B=9C=20=EC=9A=A9=EB=A7=88=EB=A3=A8=20=ED=95=98?= =?UTF-8?q?=EB=8B=A8=EC=A7=80=EB=B6=95=20=ED=8C=8C=EC=83=9D=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B8=20=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 1 + src/components/fabric/QPolygon.js | 17 +- .../roofcover/useRoofAllocationSetting.js | 172 +- src/util/qpolygon-utils.js | 7494 +---------------- 4 files changed, 127 insertions(+), 7557 deletions(-) diff --git a/src/common/common.js b/src/common/common.js index 76632014..0b824039 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -222,6 +222,7 @@ export const SAVE_KEY = [ 'skeletonLines', 'skeleton', 'viewportTransform', + 'adjustRoofLines', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype] diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 8d173bc6..b6c299d0 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -36,6 +36,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.separatePolygon = [] this.toFixed = options.toFixed ?? 1 this.baseLines = [] + this.adjustRoofLines = [] // this.colorLines = [] // 소수점 전부 제거 @@ -134,7 +135,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.setCoords() }) - this.on('modified', (e) => { + this.on('modified', () => { this.initLines() this.addLengthText() this.setCoords() @@ -223,7 +224,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { calculateDegree() { const degrees = [] // polygon.lines를 순회하며 각도를 구해 출력 - this.lines.forEach((line, idx) => { + this.lines.forEach((line) => { const dx = line.x2 - line.x1 const dy = line.y2 - line.y1 const rad = Math.atan2(dy, dx) @@ -258,6 +259,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { ) .forEach((obj) => this.canvas.remove(obj)) this.innerLines = [] + this.adjustRoofLines = [] this.canvas.renderAll() let textMode = 'plane' @@ -339,18 +341,17 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { if (types.every((type) => type === LINE_TYPE.WALLLINE.EAVES)) { // 용마루 -- straight-skeleton - console.log('용마루 지붕') - ///drawRidgeRoof(this.id, this.canvas, textMode) + // console.log('용마루 지붕') drawSkeletonRidgeRoof(this.id, this.canvas, textMode) } else if (isGableRoof(types)) { // A형, B형 박공 지붕 - console.log('패턴 지붕') + // console.log('패턴 지붕') drawGableRoof(this.id, this.canvas, textMode) } else if (isShedRoof(types, this.lines)) { - console.log('한쪽흐름 지붕') + // console.log('한쪽흐름 지붕') drawShedRoof(this.id, this.canvas, textMode) } else { - console.log('변별로 설정') + // console.log('변별로 설정') drawRoofByAttribute(this.id, this.canvas, textMode) } }, @@ -404,7 +405,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { const degree = Big(Math.atan2(dy.toNumber(), dx.toNumber())).times(180).div(Math.PI).toNumber() - // Create new text object if it doesn't exist + // Create a new text object if it doesn't exist const text = new fabric.Text(length.toString(), { left: midPoint.x, top: midPoint.y, diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js index 4bb3d8ca..54e2b7aa 100644 --- a/src/hooks/roofcover/useRoofAllocationSetting.js +++ b/src/hooks/roofcover/useRoofAllocationSetting.js @@ -30,7 +30,6 @@ import { QcastContext } from '@/app/QcastProvider' import { usePlan } from '@/hooks/usePlan' import { roofsState } from '@/store/roofAtom' import { useText } from '@/hooks/useText' -import { processEaveHelpLines } from '@/util/skeleton-utils' import { QLine } from '@/components/fabric/QLine' export function useRoofAllocationSetting(id) { @@ -114,10 +113,10 @@ export function useRoofAllocationSetting(id) { */ const fetchBasicSettings = async (planNo) => { try { - const response = await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}` }); - - let roofsArray = []; - + const response = await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}` }) + + let roofsArray = [] + // API에서 데이터를 성공적으로 가져온 경우 if (response && response.length > 0) { roofsArray = response.map((item, index) => ({ @@ -133,16 +132,16 @@ export function useRoofAllocationSetting(id) { roofPitch: item.roofPitch, roofAngle: item.roofAngle, selected: index === 0, // 첫 번째 항목을 기본 선택으로 설정 - index: index - })); - } + index: index, + })) + } // API에서 데이터가 없고 기존 roofList가 있는 경우 else if (roofList && roofList.length > 0) { roofsArray = roofList.map((roof, index) => ({ ...roof, - selected: index === 0 // 첫 번째 항목을 기본 선택으로 설정 - })); - } + selected: index === 0, // 첫 번째 항목을 기본 선택으로 설정 + })) + } // 둘 다 없는 경우 기본값 설정 else { roofsArray = [ @@ -156,64 +155,62 @@ export function useRoofAllocationSetting(id) { roofHajebichi: 0, roofGap: 'HEI_455', roofLayout: 'P', - roofPitch: 4, - roofAngle: 21.8, - }, - ] + roofPitch: 4, + roofAngle: 21.8, + }, + ] + } + + /** + * 데이터 설정 + */ + const selectRoofs = [] + for (let i = 0; i < roofsArray.length; i++) { + roofMaterials?.map((material) => { + if (material.roofMatlCd === roofsArray[i].roofMatlCd) { + selectRoofs.push({ + ...material, + selected: roofsArray[i].roofApply, + index: roofsArray[i].roofSeq, + id: roofsArray[i].roofMatlCd, + width: roofsArray[i].roofWidth, + length: roofsArray[i].roofHeight, + hajebichi: roofsArray[i].roofHajebichi, + raft: roofsArray[i].roofGap, + layout: roofsArray[i].roofLayout, + pitch: roofsArray[i].roofPitch, + angle: roofsArray[i].roofAngle, + }) } - - - /** - * 데이터 설정 - */ - const selectRoofs = [] - for (let i = 0; i < roofsArray.length; i++) { - roofMaterials?.map((material) => { - if (material.roofMatlCd === roofsArray[i].roofMatlCd) { - selectRoofs.push({ - ...material, - selected: roofsArray[i].roofApply, - index: roofsArray[i].roofSeq, - id: roofsArray[i].roofMatlCd, - width: roofsArray[i].roofWidth, - length: roofsArray[i].roofHeight, - hajebichi: roofsArray[i].roofHajebichi, - raft: roofsArray[i].roofGap, - layout: roofsArray[i].roofLayout, - pitch: roofsArray[i].roofPitch, - angle: roofsArray[i].roofAngle, - }) - } - }) - } - - const firstRes = Array.isArray(res) && res.length > 0 ? res[0] : null - - setBasicSetting({ - ...basicSetting, - planNo: firstRes?.planNo ?? planNo, - roofSizeSet: firstRes?.roofSizeSet ?? 0, - roofAngleSet: firstRes?.roofAngleSet ?? 0, - roofsData: roofsArray, - selectedRoofMaterial: selectRoofs.find((roof) => roof.selected), }) + } - setBasicInfo({ - planNo: '' + (firstRes?.planNo ?? planNo), - roofSizeSet: '' + (firstRes?.roofSizeSet ?? 0), - roofAngleSet: '' + (firstRes?.roofAngleSet ?? 0), - }) - // 데이터 동기화: 렌더링용 필드 기본값 보정 - const normalizedRoofs = selectRoofs.map((roof) => ({ - ...roof, - width: roof.width ?? '', - length: roof.length ?? '', - hajebichi: roof.hajebichi ?? '', - pitch: roof.pitch ?? '', - angle: roof.angle ?? '', - })) - setCurrentRoofList(normalizedRoofs) + const firstRes = Array.isArray(res) && res.length > 0 ? res[0] : null + setBasicSetting({ + ...basicSetting, + planNo: firstRes?.planNo ?? planNo, + roofSizeSet: firstRes?.roofSizeSet ?? 0, + roofAngleSet: firstRes?.roofAngleSet ?? 0, + roofsData: roofsArray, + selectedRoofMaterial: selectRoofs.find((roof) => roof.selected), + }) + + setBasicInfo({ + planNo: '' + (firstRes?.planNo ?? planNo), + roofSizeSet: '' + (firstRes?.roofSizeSet ?? 0), + roofAngleSet: '' + (firstRes?.roofAngleSet ?? 0), + }) + // 데이터 동기화: 렌더링용 필드 기본값 보정 + const normalizedRoofs = selectRoofs.map((roof) => ({ + ...roof, + width: roof.width ?? '', + length: roof.length ?? '', + hajebichi: roof.hajebichi ?? '', + pitch: roof.pitch ?? '', + angle: roof.angle ?? '', + })) + setCurrentRoofList(normalizedRoofs) } catch (error) { console.error('Data fetching error:', error) } @@ -467,7 +464,6 @@ export function useRoofAllocationSetting(id) { const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL) roofBases.forEach((roofBase) => { try { - const roofEaveHelpLines = canvas.getObjects().filter((obj) => obj.lineName === 'eaveHelpLine' && obj.roofId === roofBase.id) if (roofEaveHelpLines.length > 0) { if (roofBase.lines) { @@ -475,19 +471,19 @@ export function useRoofAllocationSetting(id) { const existingEaveLineIds = new Set(roofBase.lines.map((line) => line.id)) const newEaveLines = roofEaveHelpLines.filter((line) => !existingEaveLineIds.has(line.id)) // Filter out lines from roofBase.lines that share any points with newEaveLines - const linesToKeep = roofBase.lines.filter(roofLine => { - return !newEaveLines.some(eaveLine => { + const linesToKeep = roofBase.lines.filter((roofLine) => { + return !newEaveLines.some((eaveLine) => { // Check if any endpoint of roofLine matches any endpoint of eaveLine return ( // Check if any endpoint of roofLine matches any endpoint of eaveLine (Math.abs(roofLine.x1 - eaveLine.x1) < 0.1 && Math.abs(roofLine.y1 - eaveLine.y1) < 0.1) || // p1 matches p1 - (Math.abs(roofLine.x2 - eaveLine.x2) < 0.1 && Math.abs(roofLine.y2 - eaveLine.y2) < 0.1) // p2 matches p2 - ); - }); - }); + (Math.abs(roofLine.x2 - eaveLine.x2) < 0.1 && Math.abs(roofLine.y2 - eaveLine.y2) < 0.1) // p2 matches p2 + ) + }) + }) -// Combine remaining lines with newEaveLines - roofBase.lines = [...linesToKeep, ...newEaveLines]; + // Combine remaining lines with newEaveLines + roofBase.lines = [...linesToKeep, ...newEaveLines] } else { roofBase.lines = [...roofEaveHelpLines] } @@ -496,6 +492,34 @@ export function useRoofAllocationSetting(id) { } } + if (roofBase.adjustRoofLines.length > 0) { + const newRoofLines = [] + let lineIndex = 1 + roofBase.lines.forEach((line, idx) => { + const adjustLines = roofBase.adjustRoofLines.filter((adjustLine) => adjustLine.roofIdx === line.idx) + if (adjustLines.length === 0) { + line.idx = lineIndex + newRoofLines.push(line) + lineIndex++ + } else { + adjustLines.forEach(({ point, roofIdx }) => { + const newLine = new QLine(point, { + idx: lineIndex, + selectable: false, + parentId: line.parentId, + parent: line.parent, + fontSize: line.fontSize, + stroke: line.stroke, + strokeWidth: line.strokeWidth, + attributes: line.attributes, + }) + newRoofLines.push(newLine) + lineIndex++ + }) + } + }) + roofBase.lines = newRoofLines + } if (roofBase.separatePolygon.length > 0) { splitPolygonWithSeparate(roofBase.separatePolygon) } else { diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 82ad62df..abcd66ce 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -3,7 +3,6 @@ import { QLine } from '@/components/fabric/QLine' import { getAdjacent, getDegreeByChon, isPointOnLine, isPointOnLineNew } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' -import * as turf from '@turf/turf' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import Big from 'big.js' @@ -490,14 +489,6 @@ export const isSamePoint = (a, b) => { return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 2 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 2 } -/** - * 용마루 지붕 - * @param roofId - * @param canvas - * @param textMode - */ -export const drawEavesRoof = (roofId, canvas, textMode) => {} - /** * 박공지붕(A,B 패턴) * @param roofId @@ -509,7 +500,7 @@ export const drawGableRoof = (roofId, canvas, textMode) => { const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId) const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0) - const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 })) + // const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 })) const eavesLines = baseLines.filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES) @@ -1492,164 +1483,6 @@ export const drawShedRoof = (roofId, canvas, textMode) => { canvas.renderAll() } -const getInwardNormal = (v1, v2, isCCW) => { - const dx = v2.x - v1.x - const dy = v2.y - v1.y - const length = Math.sqrt(dx * dx + dy * dy) - - if (length === 0) return { x: 0, y: 0 } - - if (isCCW) { - return { x: -dy / length, y: dx / length } - } else { - return { x: dy / length, y: -dx / length } - } -} - -const isCounterClockwise = (vertices) => { - let sum = 0 - for (let i = 0; i < vertices.length; i++) { - const v1 = vertices[i] - const v2 = vertices[(i + 1) % vertices.length] - sum += (v2.x - v1.x) * (v2.y + v1.y) - } - return sum < 0 -} - -const isPointInPolygon = (point, polygon) => { - let inside = false - - for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { - const xi = polygon[i].x, - yi = polygon[i].y - const xj = polygon[j].x, - yj = polygon[j].y - - const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi - - if (intersect) inside = !inside - } - - return inside -} - -const calculateAngleBisector = (prevVertex, currentVertex, nextVertex, polygonVertices) => { - const isCCW = isCounterClockwise(polygonVertices) - - // 이전 변의 내향 법선 - const norm1 = getInwardNormal(prevVertex, currentVertex, isCCW) - - // 다음 변의 내향 법선 - const norm2 = getInwardNormal(currentVertex, nextVertex, isCCW) - - // 이등분선 계산 - let bisectorX = norm1.x + norm2.x - let bisectorY = norm1.y + norm2.y - - const length = Math.sqrt(bisectorX * bisectorX + bisectorY * bisectorY) - - if (length < 1e-10) { - // 180도인 경우 - bisectorX = norm1.x - bisectorY = norm1.y - } else { - bisectorX /= length - bisectorY /= length - } - - const testPoint = { - x: currentVertex.x + bisectorX * 0.1, - y: currentVertex.y + bisectorY * 0.1, - } - - if (isPointInPolygon(testPoint, polygonVertices)) { - // 방향이 외부를 향하면 반전 - bisectorX = -bisectorX - bisectorY = -bisectorY - } - - return { x: bisectorX, y: bisectorY } -} - -const lineSegmentIntersection = (p1, p2, p3, p4) => { - const x1 = p1.x, - y1 = p1.y - const x2 = p2.x, - y2 = p2.y - const x3 = p3.x, - y3 = p3.y - const x4 = p4.x, - y4 = p4.y - - const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4) - - if (Math.abs(denom) < EPSILON) { - return null // 평행 - } - - const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom - const u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom - - if (t >= 0 && t <= 1 && u >= 0 && u <= 1) { - return { - x: Number((x1 + t * (x2 - x1)).toFixed(1)), - y: Number((y1 + t * (y2 - y1)).toFixed(1)), - } - } - - return null -} - -/** - * 두 점 사이의 거리 계산 - */ -const distanceBetweenPoints = (p1, p2) => { - const dx = p2.x - p1.x - const dy = p2.y - p1.y - return Math.sqrt(dx * dx + dy * dy) -} - -const findIntersectionPoint = (startPoint, direction, polygonVertices, divisionLines) => { - const rayEnd = { - x: startPoint.x + direction.x * 10000, - y: startPoint.y + direction.y * 10000, - } - - let closestIntersection = null - let minDistance = Infinity - - // 다각형 변과의 교점 - for (let i = 0; i < polygonVertices.length; i++) { - const v1 = polygonVertices[i] - const v2 = polygonVertices[(i + 1) % polygonVertices.length] - - const intersection = lineSegmentIntersection(startPoint, rayEnd, v1, v2) - - if (intersection) { - const dist = distanceBetweenPoints(startPoint, intersection) - if (dist > 0.1 && dist < minDistance) { - minDistance = dist - closestIntersection = intersection - } - } - } - - // 분할선분과의 교점 - for (const divLine of divisionLines) { - const intersection = lineSegmentIntersection(startPoint, rayEnd, { x: divLine.x1, y: divLine.y1 }, { x: divLine.x2, y: divLine.y2 }) - - if (intersection) { - const dist = distanceBetweenPoints(startPoint, intersection) - if (dist > 0.1 && dist < minDistance) { - minDistance = dist - closestIntersection = intersection - } - } - } - - return closestIntersection -} - /** * 변별로 설정된 지붕을 그린다. * @param roofId @@ -2340,7 +2173,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const tolerance = 1 const dx = Big(roofLine.x2).minus(Big(roofLine.x1)).toNumber() const dy = Big(roofLine.y2).minus(Big(roofLine.y1)).toNumber() - const length = Math.sqrt(dx * dx + dy * dy) const angleDegree = (Math.atan2(dy, dx) * 180) / Math.PI const normalizedAngle = Math.abs((Math.atan2(dy, dx) * 180) / Math.PI) % 180 let isHorizontal = false, @@ -2452,7 +2284,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } }) - const currentVector = { x: Math.sign(clamp01(currentLine.x1 - currentLine.x2)), y: Math.sign(clamp01(currentLine.y1 - currentLine.y2)) } const prevLineVector = { x: Math.sign(prevLine.x1 - prevLine.x2), y: Math.sign(prevLine.y1 - prevLine.y2) } const nextLineVector = { x: Math.sign(nextLine.x1 - nextLine.x2), y: Math.sign(nextLine.y1 - nextLine.y2) } //반절마루 생성불가이므로 지붕선만 추가하고 끝냄 @@ -2688,10 +2519,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { let proceedEaves = [] // left: 이전, right:다음, point:그려지는 포인트, length:길이 let proceedRidges = [] // left: 이전, right:다음, point:그려지는 포인트, length:길이 - let hipLines = [] ridgeEaves.forEach((currentLine) => { - /*const checkLine = createArrow(currentLine, 'blue', roofId) - canvas.add(checkLine).renderAll()*/ let prevLine, nextLine, currentI, prevI, nextI baseLines.forEach((baseLine, index) => { if (baseLine === currentLine) { @@ -2714,7 +2542,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { }) const analyze = analyzeLine(currentLine) - const currentDegree = getDegreeByChon(currentLine.attributes.pitch) let pHipVector = getHalfAngleVector(currentLine, prevLine) let nHipVector = getHalfAngleVector(currentLine, nextLine) const pCheckPoint = { @@ -2736,10 +2563,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const prevCheckPoint = [currentLine.x1, currentLine.y1, currentLine.x1 + pHipVector.x * 1000, currentLine.y1 + pHipVector.y * 1000] const nextCheckPoint = [currentLine.x2, currentLine.y2, currentLine.x2 + nHipVector.x * 1000, currentLine.y2 + nHipVector.y * 1000] - /*const checkLine1 = new fabric.Line(prevCheckPoint, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' }) - const checkLine2 = new fabric.Line(nextCheckPoint, { stroke: 'green', strokeWidth: 4, parentID: roofId, name: 'check' }) - canvas.add(checkLine1, checkLine2).renderAll()*/ - const findRoofPoints = (points) => { const hipEdge = { vertex1: { x: points[0], y: points[1] }, vertex2: { x: points[2], y: points[3] } } const hipForwardVector = { x: Math.sign(hipEdge.vertex1.x - hipEdge.vertex2.x), y: Math.sign(hipEdge.vertex1.y - hipEdge.vertex2.y) } @@ -3095,7 +2918,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } if (hipPoint) { - const hipLength = Math.sqrt((hipPoint.x2 - hipPoint.x1) ** 2 + (hipPoint.y2 - hipPoint.y1) ** 2) const alreadyLine = proceedEaves.filter((line) => almostEqual(line.point.x1, hipPoint.x1) && almostEqual(line.point.y1, hipPoint.y1)) //겹쳐지는 라인이 있는경우 조정한다. if (alreadyLine.length === 0) { @@ -3435,19 +3257,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { y: (currentLine.y1 + currentLine.y2) / 2 + Math.sign(nextLine.y2 - nextLine.y1), } - /* const checkCurrLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], { - stroke: 'cyan', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkCurrLine) - canvas.renderAll()*/ - //좌우 라인이 서로 다른방향일때 if ((prevLineVector.x !== nextLineVector.x || prevLineVector.y !== nextLineVector.y) && checkWallPolygon.inPolygon(inPolygonPoint)) { const analyze = analyzeLine(currentLine) - const roofLine = analyze.roofLine let beforePrevLine, afterNextLine baseLines.forEach((baseLine, index) => { @@ -3487,7 +3299,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } - console.log('isOverlap : ', isOverlap) if (isOverlap) { const oppLine = isOverlapBefore ? beforePrevLine : afterNextLine const cMidX = (currentLine.x1 + currentLine.x2) / 2 @@ -3601,7 +3412,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } } - let stdDistance = nextDistance <= prevDistance ? prevDistance : nextDistance const stdAnalyze = analyzeLine(stdLine) let stdPoints = [] @@ -3683,11 +3493,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } } - console.log('stdAdjustVector', stdAdjustVector) } else { const stdAddPrevVector = { x: Math.sign(clamp01(stdLine.x1 - stdLine.x2)), y: Math.sign(clamp01(stdLine.y1 - stdLine.y2)) } const stdAddNextVector = { x: Math.sign(clamp01(stdLine.x2 - stdLine.x1)), y: Math.sign(clamp01(stdLine.y2 - stdLine.y1)) } - console.log('stdAddPrevVector', stdAddPrevVector) stdPoints = [ stdLine.x1 + stdAddPrevVector.x * stdPrevLine.attributes.offset, stdLine.y1 + stdAddPrevVector.y * stdPrevLine.attributes.offset, @@ -3695,19 +3503,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { stdLine.y2 + stdAddNextVector.y * stdNextLine.attributes.offset, ] } - /*const checkLine = new fabric.Line([stdLine.x1, stdLine.y1, stdLine.x2, stdLine.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - const checkLine2 = new fabric.Line(stdPoints, { - stroke: 'green', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkLine, checkLine2).renderAll()*/ //기준지붕선의 반대쪽선 const oppositeLine = [] @@ -3715,7 +3510,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const endX = Math.max(stdLine.x1, stdLine.x2) const startY = Math.min(stdLine.y1, stdLine.y2) const endY = Math.max(stdLine.y1, stdLine.y2) - console.log('stdFindOppVector', stdFindOppVector) baseLines .filter((line) => line !== stdLine && line !== currentLine && line.attributes.type !== LINE_TYPE.WALLLINE.SHED) .filter((line) => { @@ -3768,26 +3562,14 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { if (oppositeLine.length > 0) { const ridgePoints = [] - //지붕선 출발 지점 확인을 위한 기준 포인트 - let ridgeStdPoint = { x: (currentLine.x1 + currentLine.x2) / 2, y: (currentLine.y1 + currentLine.y2) / 2 } oppositeLine.sort((a, b) => a.distance - b.distance) oppositeLine.forEach((opposite) => { const oppLine = opposite.line - /*const checkOppLine = new fabric.Line([oppLine.x1, oppLine.y1, oppLine.x2, oppLine.y2], { - stroke: 'yellow', - strokeWidth: 6, - parentId: roofId, - name: 'check', - }) - canvas.add(checkOppLine) - canvas.renderAll()*/ - const oppIndex = baseLines.findIndex((line) => line === oppLine) //마주하는 라인의 이전 다음 라인. const oppPrevLine = baseLines[(oppIndex - 1 + baseLines.length) % baseLines.length] const oppNextLine = baseLines[(oppIndex + 1) % baseLines.length] - const oppAnalyze = analyzeLine(oppLine) const oppVector = { x: Math.sign(oppLine.x2 - oppLine.x1), y: Math.sign(oppLine.y2 - oppLine.y1) } let ridgePoint @@ -3829,13 +3611,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { ridgePoint[2] = (stdLine.x2 + oppLine.x2) / 2 } - // 지붕선 출발 지점과의 거리를 통해 가까운쪽이 start point로 처리. - /*const distRidgeStandard1 = Math.sqrt(Math.pow(ridgeStdPoint.x - ridgePoint[0], 2) + Math.pow(ridgeStdPoint.y - ridgePoint[1], 2)) - const distRidgeStandard2 = Math.sqrt(Math.pow(ridgeStdPoint.x - ridgePoint[2], 2) + Math.pow(ridgeStdPoint.y - ridgePoint[3], 2)) - if (distRidgeStandard1 > distRidgeStandard2) { - ridgePoint = [ridgePoint[2], ridgePoint[3], ridgePoint[0], ridgePoint[1]] - }*/ - if ( (oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES || oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) && !(oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) @@ -4029,10 +3804,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } - /* const checkLine1 = new fabric.Line(stdPoints, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' }) - const checkLine2 = new fabric.Line(ridgePoint, { stroke: 'cyan', strokeWidth: 4, parentId: roofId, name: 'check' }) - canvas.add(checkLine1, checkLine2).renderAll()*/ - const stdMinX = Math.min(stdPoints[0], stdPoints[2]) const stdMaxX = Math.max(stdPoints[0], stdPoints[2]) const stdMinY = Math.min(stdPoints[1], stdPoints[3]) @@ -4183,21 +3954,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { if (prevLineVector.x === nextLineVector.x && prevLineVector.y === nextLineVector.y) { const analyze = analyzeLine(currentLine) const roofLine = analyze.roofLine - /*const checkRoof = new fabric.Line([roofLine.x1, roofLine.y1, roofLine.x2, roofLine.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkRoof) - const checkLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], { - stroke: 'blue', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkLine) - canvas.renderAll()*/ const checkVector = { x: Math.sign(prevLine.y2 - prevLine.y1), y: Math.sign(prevLine.x1 - prevLine.x2) } const checkEdge = { vertex1: { x: roofLine.x1, y: roofLine.y1 }, vertex2: { x: roofLine.x2, y: roofLine.y2 } } @@ -4211,33 +3967,14 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { return line !== roofLine && line !== prevRoofLine && line !== nextRoofLine }) .forEach((line) => { - /*const checkLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkLine).renderAll()*/ const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } const intersect = edgesIntersection(lineEdge, checkEdge) - /* if (intersect) { - const checkCircle = new fabric.Circle({ - left: intersect.x, - top: intersect.y, - radius: 5, - fill: 'blue', - parentId: roofId, - name: 'check', - }) - console.log('isPointOnLineNew(line, intersect)', isPointOnLineNew(line, intersect)) - canvas.add(checkCircle).renderAll() - }*/ + if (intersect && isPointOnLineNew(line, intersect)) { intersect.x = almostEqual(intersect.x, roofLine.x1) ? roofLine.x1 : intersect.x intersect.y = almostEqual(intersect.y, roofLine.y1) ? roofLine.y1 : intersect.y const distance = Math.sqrt(Math.pow(intersect.x - roofLine.x1, 2) + Math.pow(intersect.y - roofLine.y1, 2)) const vector = { x: Math.sign(intersect.x - roofLine.x1), y: Math.sign(intersect.y - roofLine.y1) } - console.log('vector', vector, 'checkVector', checkVector) if (distance > maxDistance && vector.x === checkVector.x && vector.y === checkVector.y) { maxDistance = distance correctPoint = intersect @@ -4274,19 +4011,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const MAX_ITERATIONS = 1000 //무한루프 방지 let iterations = 0 - console.log('baseLines', baseLines) - console.log('linesAnalysis', linesAnalysis) - while (linesAnalysis.length > 0 && iterations < MAX_ITERATIONS) { iterations++ - /*linesAnalysis.forEach((line) => { - const point = { x1: line.start.x, y1: line.start.y, x2: line.end.x, y2: line.end.y } - const checkLine = createArrow(point, 'red', roofId) - canvas.add(checkLine).renderAll() - // canvas.remove(checkLine).renderAll() - })*/ - const intersections = [] linesAnalysis.forEach((currLine, i) => { let minDistance = Infinity @@ -4294,14 +4021,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { let linePoint = null let partner = null - /*const checkCLine = new fabric.Line([currLine.start.x, currLine.start.y, currLine.end.x, currLine.end.y], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkCLine).renderAll()*/ - const cLength = Math.sqrt(Math.pow(currLine.end.x - currLine.start.x, 2) + Math.pow(currLine.end.y - currLine.start.y, 2)) //남은 길이가 0이면 무시 if (cLength < EPSILON) return @@ -4312,18 +4031,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { if (i === j) return if (currLine.type === TYPES.GABLE_LINE && nextLine.type === TYPES.GABLE_LINE && currLine.gableId === nextLine.gableId) return if (nextLine.type === TYPES.GABLE_LINE && nextLine.connectCnt > 1) return - /*const checkNLine = new fabric.Line([nextLine.start.x, nextLine.start.y, nextLine.end.x, nextLine.end.y], { - stroke: 'green', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkNLine).renderAll()*/ const intersect = lineIntersection(currLine.start, currLine.end, nextLine.start, nextLine.end, canvas) if (intersect) { - /*const checkCircle = new fabric.Circle({ left: intersect.x, top: intersect.y, radius: 5, fill: 'blue', parentId: roofId, name: 'check' }) - canvas.add(checkCircle).renderAll()*/ let distance1 = Math.sqrt(Math.pow(intersect.x - currLine.start.x, 2) + Math.pow(intersect.y - currLine.start.y, 2)) let distance2 = Math.sqrt(Math.pow(intersect.x - nextLine.start.x, 2) + Math.pow(intersect.y - nextLine.start.y, 2)) let point = [currLine.start.x, currLine.start.y, intersect.x, intersect.y] @@ -4348,20 +4058,15 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { partner = j } } - // canvas.remove(checkCircle).renderAll() } - // canvas.remove(checkNLine).renderAll() }) - // canvas.remove(checkCLine).renderAll() if (intersectPoint) { intersections.push({ index: i, intersect: intersectPoint, linePoint, partner }) } }) - console.log('intersections', intersections) const intersectPoints = intersections .map((item) => item.intersect) .filter((point, index, self) => self.findIndex((p) => almostEqual(p.x, point.x) && almostEqual(p.y, point.y)) === index) - console.log('intersectPoints', intersectPoints) if (intersectPoints.length === 1 && intersections.length > 1) { intersections[0].partner = intersections[1].index @@ -4488,7 +4193,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } if (cLine.type === TYPES.GABLE_LINE || pLine.type === TYPES.GABLE_LINE) { relationBaseLines = [cLine.left, cLine.right, pLine.left, pLine.right] - console.log('gableLine newAnalyze start') const gableLine = cLine.type === TYPES.GABLE_LINE ? cLine : pLine gableLine.connectCnt++ @@ -4530,7 +4234,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } } - console.log('gableLine newAnalyze end') } else { const uniqueBaseLines = [...new Set(relationBaseLines)] // 연결점에서 새로운 가선분을 생성 @@ -4544,16 +4247,13 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { .filter(([_, count]) => count === 1) .map(([line, _]) => line) - console.log('uniqueLines', uniqueLines) if (uniqueLines.length === 2) { // 두 변의 이등분선 방향 계산 // uniqueLines.sort((a, b) => a - b) - console.log('uniqueLines : ', uniqueLines) const baseLine1 = baseLines[uniqueLines[0]] const baseLine2 = baseLines[uniqueLines[1]] let bisector - console.log('isParallel(baseLine1, baseLine2)', isParallel(baseLine1, baseLine2)) if (isParallel(baseLine1, baseLine2)) { let cPoint = [cLine.start.x, cLine.start.y, cLine.end.x, cLine.end.y] let pPoint = [pLine.start.x, pLine.start.y, pLine.end.x, pLine.end.y] @@ -4601,14 +4301,12 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } }) intersectionsByRoof.sort((a, b) => a.distance - b.distance) - console.log('intersectionsByRoof : ', intersectionsByRoof) //기 존재하는 analyze 라인이 있으면 newAnalyzeLine을 생성하지 않고 교체한다. const otherIs = intersections.filter( (is) => !processed.has(is.index) && almostEqual(is.intersect.x, intersect.x) && almostEqual(is.intersect.y, intersect.y), ) - console.log('otherIs', otherIs) if (otherIs.length > 0) { const analyze = linesAnalysis[otherIs[0].index] processed.add(otherIs[0].index) @@ -4636,20 +4334,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const prevLine = checkVector.x === vector1.x && checkVector.y === vector1.y ? line2 : line1 const nextLine = checkVector.x === vector1.x && checkVector.y === vector1.y ? line1 : line2 - /*const checkPrevLine = new fabric.Line([prevLine.x1, prevLine.y1, prevLine.x2, prevLine.y2], { - stroke: 'yellow', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - const checkNextLine = new fabric.Line([nextLine.x1, nextLine.y1, nextLine.x2, nextLine.y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'check', - }) - canvas.add(checkPrevLine, checkNextLine).renderAll()*/ - if (!isDiagonal) { const drivePoint = getRidgeDrivePoint(linePoint, prevLine, nextLine, baseLines) if (drivePoint !== null) { @@ -4659,8 +4343,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } } } - // const checkNewLine = new fabric.Line(linePoint, { stroke: 'cyan', strokeWidth: 4, parentId: roofId, name: 'check' }) - // canvas.add(checkNewLine).renderAll() newAnalysis.push({ start: { x: linePoint[0], y: linePoint[1] }, @@ -4685,7 +4367,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { // 처리된 가선분 제외 linesAnalysis = newAnalysis.concat(linesAnalysis.filter((_, index) => !processed.has(index))) - console.log('lineAnalysis: ', linesAnalysis) canvas .getObjects() @@ -4795,7 +4476,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { .forEach((line) => { const startOnLine = roof.lines.find((l) => isPointOnLineNew(l, line.start)) const endOnLine = roof.lines.find((l) => isPointOnLineNew(l, line.end)) - console.log('startOnLine, endOnLine: ', startOnLine, endOnLine) const allLinesPoints = [] innerLines.forEach((innerLine) => { allLinesPoints.push({ x: innerLine.x1, y: innerLine.y1 }, { x: innerLine.x2, y: innerLine.y2 }) @@ -4823,7 +4503,9 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { //케라바에서 파생된 하단 지붕 라인처리 const downRoofGable = [] //처마에서 파생된 하단 지붕 라인 처리 - let downRoofEaves = [] + const downRoofEaves = [] + //roof lines에 조정해야하는 라인 처리 + // const adjustRoofLines = [] baseLines.forEach((baseLine, index) => { const nextLine = baseLines[(index + 1) % baseLines.length] const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length] @@ -4992,7 +4674,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { //1. 현재 라인을 기준으로 지붕선 추가. //1-1 stdPoint을 현재라인의 지붕 출폭 만큼 조정 const currOffset = currLine.attributes.offset - const noGableLine = gableLine === prevLine ? nextLine : prevLine let roofLinePoint = stdPoint if (currVector.x === 0) { @@ -5273,9 +4954,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { const vector = Math.sign(currLine.y1 - originPoint.y1) isFlowInside = isTopIn ? vector < 0 : vector > 0 } - console.log('isFlowInside', isFlowInside) const roofCheckPoint = { x: roofLine.x2 + roofVector.x, y: roofLine.y2 + roofVector.y } - console.log('roofCheck : ', roof.inPolygon(roofCheckPoint)) let otherLine = roof.inPolygon(roofCheckPoint) ? baseLines[nextIndex] : baseLines[prevIndex] //상단 지붕 @@ -5300,7 +4979,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { }) }) - const upDegree = getDegreeByChon(upLine.attributes.pitch) const upAnalyze = analyzeLine(upLine) const upRoofLine = upAnalyze.roofLine const addUpOffset = flowDistance //상단 지붕선의 추가길이 @@ -5340,10 +5018,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { downHipStartPoint = { x: downRoofPoint[0], y: downRoofPoint[1] } } - const checkUpLine = new fabric.Line(upRoofPoint, { stroke: 'red', strokeWidth: 4, parentId: roofId, name: 'check' }) - const checkDownLine = new fabric.Line(downRoofPoint, { stroke: 'yellow', strokeWidth: 4, parentId: roofId, name: 'check' }) - canvas.add(checkUpLine, checkDownLine).renderAll() - //상단지붕선과 만나는 innerLines 조정 const upRoofEdge = { vertex1: { x: upRoofPoint[0], y: upRoofPoint[1] }, vertex2: { x: upRoofPoint[2], y: upRoofPoint[3] } } @@ -5429,11 +5103,16 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { } downRoofLines.push(drawHipLine(upHipPoint, canvas, roof, textMode, hipDegree, hipDegree)) //각도 있는 처마지붕선 downRoofLines.push(drawRoofLine([connectPoint.x, connectPoint.y, intersectJoin.x, intersectJoin.y], canvas, roof, textMode)) //각도 없는 처마지붕선 + + roof.adjustRoofLines.push({ point: upHipPoint, roofIdx: upRoofLine.idx }) + roof.adjustRoofLines.push({ point: [connectPoint.x, connectPoint.y, intersectJoin.x, intersectJoin.y], roofIdx: upRoofLine.idx }) } else { downRoofLines.push(drawRoofLine([upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], canvas, roof, textMode)) + roof.adjustRoofLines.push({ point: [upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], roofIdx: upRoofLine.idx }) } } else { downRoofLines.push(drawRoofLine([upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], canvas, roof, textMode)) + roof.adjustRoofLines.push({ point: [upHipStartPoint.x, upHipStartPoint.y, intersectJoin.x, intersectJoin.y], roofIdx: upRoofLine.idx }) } //하단지붕선 추가. @@ -5461,6 +5140,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => { downRoofLines.push( drawHipLine([intersectDownJoin.x, intersectDownJoin.y, joinEndPoint.x, joinEndPoint.y], canvas, roof, textMode, downDegree, downDegree), ) + roof.adjustRoofLines.push({ point: downRoofPoint, roofIdx: downRoofLine.idx }) } } }) @@ -5632,24 +5312,6 @@ const clamp01 = (t) => { return t } -/** - * 실제 각도를 계산한다 대각선인 경우 각도 조정 - * @param points - * @param degree - */ -const getRealDegree = (points, degree) => { - const deltaX = Math.abs(points[2] - points[0]) - const deltaY = Math.abs(points[3] - points[1]) - if (deltaX < 1 || deltaY < 1) { - return degree - } - - const hypotenuse = Math.sqrt(deltaX ** 2 + deltaY ** 2) - const adjacent = Math.sqrt(Math.pow(hypotenuse, 2) / 2) - const height = adjacent * Math.tan((degree * Math.PI) / 180) - return Math.atan2(height, hypotenuse) * (180 / Math.PI) -} - /** * 두 라인이 평행한지 확인한다. * @param line1 @@ -5807,7050 +5469,6 @@ const alreadyPoints = (lines, points) => { return has } -/** - * 마루가 있는 지붕을 그린다. - * @param roofId - * @param canvas - * @param textMode - */ -export const drawRidgeRoof = (roofId, canvas, textMode) => { - let roof = canvas?.getObjects().find((object) => object.id === roofId) - const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId) - - const hasNonParallelLines = roof.lines.filter((line) => Big(line.x1).minus(Big(line.x2)).gt(1) && Big(line.y1).minus(Big(line.y2)).gt(1)) - if (hasNonParallelLines.length > 0) { - return - } - - const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE] - const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD] - - /** 외벽선 */ - const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0) - const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 })) - - /** 벽취합이 있는 경우 소매가 있다면 지붕 형상을 변경해야 한다. */ - baseLines - .filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.WALL && line.attributes.offset > 0) - .forEach((currentLine) => { - const prevLine = baseLines.find((line) => line.x2 === currentLine.x1 && line.y2 === currentLine.y1) - const nextLine = baseLines.find((line) => line.x1 === currentLine.x2 && line.y1 === currentLine.y2) - - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2).toNumber() - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2).toNumber() - const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1) - const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1) - - /** 현재 라인의 지붕 라인을 찾는다. */ - const intersectionRoofs = [] - let currentRoof - if (currentVectorX === 0) { - const checkEdge = { - vertex1: { x: prevLine.x1, y: currentMidY }, - vertex2: { x: currentMidX, y: currentMidY }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: currentMidX, y: prevLine.y1 }, - vertex2: { x: currentMidX, y: currentMidY }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } - if (intersectionRoofs.length > 0) { - currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line - } - if (currentRoof) { - const prevRoof = roof.lines.find((line) => line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1) - const nextRoof = roof.lines.find((line) => line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2) - - const prevOffset = prevLine.attributes.offset - const nextOffset = nextLine.attributes.offset - - currentRoof.set({ x1: currentLine.x1, y1: currentLine.y1, x2: currentLine.x2, y2: currentLine.y2 }) - - if (prevLine.attributes.type !== LINE_TYPE.WALLLINE.WALL && prevOffset > 0) { - const addPoint1 = [] - const addPoint2 = [] - if (Math.sign(prevLine.y2 - prevLine.y1) === 0) { - addPoint1.push(prevRoof.x2, prevRoof.y2, prevRoof.x2, currentRoof.y1) - addPoint2.push(addPoint1[2], addPoint1[3], currentRoof.x1, currentRoof.y1) - } else { - addPoint1.push(prevRoof.x2, prevRoof.y2, currentRoof.x1, prevRoof.y2) - addPoint2.push(addPoint1[2], addPoint1[3], currentRoof.x1, currentRoof.y1) - } - const addRoofLine1 = new QLine(addPoint1, { - name: 'addRoofLine', - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - textMode: textMode, - attributes: { - roofId: roofId, - type: LINE_TYPE.WALLLINE.ETC, - planeSize: calcLinePlaneSize({ - x1: addPoint1[0], - y1: addPoint1[1], - x2: addPoint1[2], - y2: addPoint1[3], - }), - actualSize: calcLinePlaneSize({ - x1: addPoint1[0], - y1: addPoint1[1], - x2: addPoint1[2], - y2: addPoint1[3], - }), - }, - }) - - const addRoofLine2 = new QLine(addPoint2, { - name: 'addRoofLine', - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - textMode: textMode, - attributes: { - roofId: roofId, - type: LINE_TYPE.WALLLINE.ETC, - planeSize: calcLinePlaneSize({ - x1: addPoint2[0], - y1: addPoint2[1], - x2: addPoint2[2], - y2: addPoint2[3], - }), - actualSize: calcLinePlaneSize({ - x1: addPoint2[0], - y1: addPoint2[1], - x2: addPoint2[2], - y2: addPoint2[3], - }), - }, - }) - canvas.add(addRoofLine1, addRoofLine2) - canvas.renderAll() - - const prevIndex = roof.lines.indexOf(prevRoof) - if (prevIndex === roof.lines.length - 1) { - roof.lines.unshift(addRoofLine1, addRoofLine2) - } else { - roof.lines.splice(prevIndex + 1, 0, addRoofLine1, addRoofLine2) - } - } else if (prevLine.attributes.type === LINE_TYPE.WALLLINE.WALL || prevOffset === 0) { - prevRoof.set({ x2: currentLine.x1, y2: currentLine.y1 }) - } - if (nextLine.attributes.type !== LINE_TYPE.WALLLINE.WALL && nextOffset > 0) { - const addPoint1 = [] - const addPoint2 = [] - if (Math.sign(nextLine.y2 - nextLine.y1) === 0) { - addPoint1.push(currentRoof.x2, currentRoof.y2, nextRoof.x1, currentRoof.y2) - addPoint2.push(addPoint1[2], addPoint1[3], nextRoof.x1, nextRoof.y1) - } else { - addPoint1.push(currentRoof.x2, currentRoof.y2, currentRoof.x2, nextRoof.y1) - addPoint2.push(addPoint1[2], addPoint1[3], nextRoof.x1, nextRoof.y1) - } - - const addRoofLine1 = new QLine(addPoint1, { - name: 'addRoofLine', - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - textMode: textMode, - attributes: { - roofId: roofId, - type: LINE_TYPE.WALLLINE.ETC, - planeSize: calcLinePlaneSize({ - x1: addPoint1[0], - y1: addPoint1[1], - x2: addPoint1[2], - y2: addPoint1[3], - }), - actualSize: calcLinePlaneSize({ - x1: addPoint1[0], - y1: addPoint1[1], - x2: addPoint1[2], - y2: addPoint1[3], - }), - }, - }) - - const addRoofLine2 = new QLine(addPoint2, { - name: 'addRoofLine', - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - textMode: textMode, - attributes: { - roofId: roofId, - type: LINE_TYPE.WALLLINE.ETC, - planeSize: calcLinePlaneSize({ - x1: addPoint2[0], - y1: addPoint2[1], - x2: addPoint2[2], - y2: addPoint2[3], - }), - actualSize: calcLinePlaneSize({ - x1: addPoint2[0], - y1: addPoint2[1], - x2: addPoint2[2], - y2: addPoint2[3], - }), - }, - }) - canvas.add(addRoofLine1, addRoofLine2) - canvas.renderAll() - - const nextIndex = roof.lines.indexOf(nextRoof) - if (nextIndex === 0) { - roof.lines.push(addRoofLine1, addRoofLine2) - } else { - roof.lines.splice(nextIndex, 0, addRoofLine1, addRoofLine2) - } - } else if (nextLine.attributes.type === LINE_TYPE.WALLLINE.WALL) { - if (Math.sign(nextLine.y2 - nextLine.y1) === 0) { - nextRoof.set({ x1: currentLine.x2, y1: nextRoof.y1 }) - } else { - nextRoof.set({ x1: nextRoof.x1, y1: currentLine.y2 }) - } - currentRoof.set({ x2: nextRoof.x1, y2: nextRoof.y1 }) - } else if (nextOffset === 0) { - nextRoof.set({ x1: currentLine.x2, y1: currentLine.y2 }) - } - - roof = reDrawPolygon(roof, canvas) - } - }) - - /** 모양 판단을 위한 라인 처리. - * 평행한 라인이 나누어져 있는 경우 하나의 선으로 판단 한다. - */ - const drawBaseLines = [] - baseLines.forEach((currentLine, index) => { - let nextLine = baseLines[(index + 1) % baseLines.length] - let prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length] - const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - - let { x1, y1, x2, y2 } = currentLine - - if (currentAngle !== prevAngle || (currentAngle === prevAngle && currentLine.attributes.type !== prevLine.attributes.type)) { - if (currentAngle === nextAngle && currentLine.attributes.type === nextLine.attributes.type) { - let nextIndex = baseLines.findIndex((line) => line === nextLine) - while (nextIndex !== index) { - const checkNextLine = baseLines[(nextIndex + 1 + baseLines.length) % baseLines.length] - const checkAngle = calculateAngle(checkNextLine.startPoint, checkNextLine.endPoint) - if (currentAngle !== checkAngle) { - x2 = checkNextLine.x1 - y2 = checkNextLine.y1 - break - } else { - nextIndex = nextIndex + 1 - } - } - } - drawBaseLines.push({ x1, y1, x2, y2, line: currentLine, size: calcLinePlaneSize({ x1, y1, x2, y2 }) }) - } - }) - - /** baseLine을 기준으로 확인용 polygon 작성 */ - const checkWallPolygon = new QPolygon(baseLinePoints, {}) - - const drawEavesFirstLines = [] - const drawEavesSecondLines = [] - const drawGableRidgeFirst = [] - const drawGableRidgeSecond = [] - const drawGablePolygonFirst = [] - const drawGablePolygonSecond = [] - const drawHipAndGableFirst = [] - const drawWallRidgeLine = [] - - /** 모양을 판단한다. */ - drawBaseLines.forEach((currentBaseLine, index) => { - let prevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] - let nextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length] - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - - // const checkLine = new fabric.Line([currentLine.x1, currentLine.y1, currentLine.x2, currentLine.y2], { - // stroke: 'red', - // strokeWidth: 4, - // parentId: roofId, - // name: 'checkLine', - // }) - // canvas.add(checkLine) - // canvas.renderAll() - - const checkScale = Big(10) - const xVector = Big(nextLine.x2).minus(Big(nextLine.x1)) - const yVector = Big(nextLine.y2).minus(Big(nextLine.y1)) - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2) - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2) - - const checkPoints = { - x: currentMidX.plus(checkScale.times(Math.sign(xVector.toNumber()))).toNumber(), - y: currentMidY.plus(checkScale.times(Math.sign(yVector.toNumber()))).toNumber(), - } - - /** 현재 라인이 처마유형일 경우 */ - if (currentLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) { - if (nextLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) { - /** - * 이전, 다음 라인이 처마일때 라인의 방향이 반대면 ㄷ 모양으로 판단한다. - */ - if (prevLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES && nextLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) { - if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) { - /** - * 다음라인 방향에 포인트를 확인해서 역방향 ㄷ 모양인지 판단한다. - * @type {{x: *, y: *}} - */ - if (checkWallPolygon.inPolygon(checkPoints)) { - drawEavesFirstLines.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } else { - drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - } else { - drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - } else if (eavesType.includes(nextLine.attributes?.type)) { - drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - } else if (gableType.includes(nextLine.attributes?.type) && gableType.includes(prevLine.attributes?.type)) { - if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) { - if (checkWallPolygon.inPolygon(checkPoints)) { - drawGablePolygonFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } else { - drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } else { - if (currentAngle !== prevAngle && currentAngle !== nextAngle) { - drawGablePolygonSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - } - } - } - - if (gableType.includes(currentLine.attributes?.type)) { - if ( - eavesType.includes(prevLine.attributes?.type) && - eavesType.includes(nextLine.attributes?.type) && - Big(prevAngle).minus(Big(nextAngle)).abs().eq(180) - ) { - if (checkWallPolygon.inPolygon(checkPoints)) { - drawGableRidgeFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } else { - drawGableRidgeSecond.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - } - } - - if ( - LINE_TYPE.WALLLINE.HIPANDGABLE === currentLine.attributes?.type && - eavesType.includes(nextLine.attributes?.type) && - eavesType.includes(prevLine.attributes?.type) - ) { - drawHipAndGableFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - - if ( - LINE_TYPE.WALLLINE.WALL === currentLine.attributes?.type && - eavesType.includes(nextLine.attributes?.type) && - eavesType.includes(prevLine.attributes?.type) - ) { - if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180) && checkWallPolygon.inPolygon(checkPoints)) { - drawWallRidgeLine.push({ currentBaseLine, prevBaseLine, nextBaseLine }) - } - } - }) - - drawEavesFirstLines.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size) - drawGableRidgeFirst.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size) - drawGableRidgeSecond.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size) - drawWallRidgeLine.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size) - - /** 추녀마루 */ - let baseHipLines = [] - /** 용마루 */ - let baseRidgeLines = [] - /** 박공지붕 마루*/ - let baseGableRidgeLines = [] - - /** 박공지붕 라인*/ - let baseGableLines = [] - /** 용마루의 갯수*/ - let baseRidgeCount = 0 - - // console.log('drawEavesFirstLines :', drawEavesFirstLines) - // console.log('drawEavesSecondLines :', drawEavesSecondLines) - console.log('drawGableRidgeFirst: ', drawGableRidgeFirst) - console.log('drawGableRidgeSecond:', drawGableRidgeSecond) - console.log('drawGablePolygonFirst :', drawGablePolygonFirst) - console.log('drawGablePolygonSecond :', drawGablePolygonSecond) - // console.log('drawHipAndGableFirst :', drawHipAndGableFirst) - // console.log('drawWallLines :', drawWallRidgeLine) - - /** 박공지붕에서 파생되는 마루를 그린다. ㄷ 형태*/ - drawGableRidgeFirst.forEach((current) => { - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - - if (prevBaseLine.size !== prevLine.attributes.planeSize) { - prevLine.x1 = prevBaseLine.x1 - prevLine.y1 = prevBaseLine.y1 - prevLine.x2 = prevBaseLine.x2 - prevLine.y2 = prevBaseLine.y2 - prevLine.setCoords() - } - if (nextBaseLine.size !== nextLine.attributes.planeSize) { - nextLine.x1 = nextBaseLine.x1 - nextLine.y1 = nextBaseLine.y1 - nextLine.x2 = nextBaseLine.x2 - nextLine.y2 = nextBaseLine.y2 - nextLine.setCoords() - } - - let { x1, x2, y1, y2, size } = currentBaseLine - let beforePrevBaseLine, afterNextBaseLine - - /** 이전 라인의 경사 */ - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - /** 다음 라인의 경사 */ - const nextDegree = getDegreeByChon(nextLine.attributes.pitch) - - /** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */ - drawBaseLines.forEach((line, index) => { - if (line === prevBaseLine) { - beforePrevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] - } - if (line === nextBaseLine) { - afterNextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length] - } - }) - - const beforePrevLine = beforePrevBaseLine?.line - const afterNextLine = afterNextBaseLine?.line - - /** 각 라인의 흐름 방향을 확인한다. */ - const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - const beforePrevAngle = calculateAngle(beforePrevLine.startPoint, beforePrevLine.endPoint) - const afterNextAngle = calculateAngle(afterNextLine.startPoint, afterNextLine.endPoint) - - /** 현재라인의 vector*/ - const currentVectorX = Math.sign(Big(x2).minus(Big(x1)).toNumber()) - const currentVectorY = Math.sign(Big(y2).minus(Big(y1)).toNumber()) - - /** 이전라인의 vector*/ - const prevVectorX = Math.sign(Big(prevLine.x2).minus(Big(prevLine.x1))) - const prevVectorY = Math.sign(Big(prevLine.y2).minus(Big(prevLine.y1))) - - /** 다음라인의 vector*/ - const nextVectorX = Math.sign(Big(nextLine.x2).minus(Big(nextLine.x1))) - const nextVectorY = Math.sign(Big(nextLine.y2).minus(Big(nextLine.y1))) - - /** 현재라인의 기준점*/ - let currentMidX = Big(x1).plus(Big(x2)).div(2).plus(Big(prevVectorX).times(currentLine.attributes.offset)) - let currentMidY = Big(y1).plus(Big(y2)).div(2).plus(Big(prevVectorY).times(currentLine.attributes.offset)) - - /** 마루 반대 좌표*/ - let oppositeMidX = currentMidX, - oppositeMidY = currentMidY - - /** 현재 라인의 지붕 라인을 찾는다. */ - const intersectionRoofs = [] - let currentRoof - if (currentVectorX === 0) { - const checkEdge = { - vertex1: { x: prevLine.x1, y: currentMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } - if (intersectionRoofs.length > 0) { - currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line - } - - /** 현재 라인의 지붕선에서 이전 지붕선, 다음 지붕선으로 향하는 vector*/ - const prevRoofVectorX = Math.sign(currentRoof.x2 - currentRoof.x1) - const prevRoofVectorY = Math.sign(currentRoof.y2 - currentRoof.y1) - const nextRoofVectorX = Math.sign(currentRoof.x1 - currentRoof.x2) - const nextRoofVectorY = Math.sign(currentRoof.y1 - currentRoof.y2) - - /** 한개의 지붕선을 둘로 나누어서 처리 하는 경우 */ - if (prevAngle === beforePrevAngle || nextAngle === afterNextAngle) { - if (currentVectorX === 0) { - const addLength = Big(currentLine.y1).minus(Big(currentLine.y2)).abs().div(2) - const ridgeVector = Math.sign(prevLine.x1 - currentLine.x1) - oppositeMidX = Big(prevLine.x1).plus(Big(addLength).times(ridgeVector)) - - const ridgeEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - - const ridgeVectorX = Math.sign(ridgeEdge.vertex1.x - ridgeEdge.vertex2.x) - roof.lines - .filter((line) => line.x1 === line.x2) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(ridgeEdge, lineEdge) - if (is) { - const isVectorX = Math.sign(ridgeEdge.vertex1.x - is.x) - if ( - isVectorX === ridgeVectorX && - ((line.x1 <= currentMidX && line.x2 >= currentMidX) || (line.x2 <= currentMidX && line.x1 >= currentMidX)) - ) { - currentMidX = Big(is.x) - currentMidY = Big(is.y) - } - } - }) - } else { - const addLength = Big(currentLine.x1).minus(Big(currentLine.x2)).abs().div(2) - const ridgeVector = Math.sign(prevLine.y1 - currentLine.y1) - oppositeMidY = Big(prevLine.y1).plus(addLength.times(ridgeVector)) - - const ridgeEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - const ridgeVectorY = Math.sign(ridgeEdge.vertex1.y - ridgeEdge.vertex2.y) - roof.lines - .filter((line) => line.y1 === line.y2) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(ridgeEdge, lineEdge) - if (is) { - const isVectorY = Math.sign(ridgeEdge.vertex1.y - is.y) - if ( - isVectorY === ridgeVectorY && - ((line.x1 <= currentMidX && line.x2 >= currentMidX) || (line.x2 <= currentMidX && line.x1 >= currentMidX)) - ) { - currentMidX = Big(is.x) - currentMidY = Big(is.y) - } - } - }) - } - - const prevHipEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - vertex2: { x: prevLine.x1, y: prevLine.y1 }, - } - const prevHipVectorX = Math.sign(prevHipEdge.vertex1.x - prevHipEdge.vertex2.x) - const prevHipVectorY = Math.sign(prevHipEdge.vertex1.y - prevHipEdge.vertex2.y) - const prevIsPoints = [] - roof.lines - .filter((line) => (Math.sign(prevLine.x1 - prevLine.x2) === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(prevHipEdge, lineEdge) - if (is) { - const isVectorX = Math.sign(prevHipEdge.vertex1.x - is.x) - const isVectorY = Math.sign(prevHipEdge.vertex1.y - is.y) - if (isVectorX === prevHipVectorX && isVectorY === prevHipVectorY) { - const size = Big(prevHipEdge.vertex1.x) - .minus(Big(is.x)) - .abs() - .pow(2) - .plus(Big(prevHipEdge.vertex1.y).minus(Big(is.y)).abs().pow(2)) - .sqrt() - .toNumber() - prevIsPoints.push({ is, size }) - } - } - }) - - if (prevIsPoints.length > 0) { - const prevIs = prevIsPoints.sort((a, b) => a.size - b.size)[0].is - const prevHipLine = drawHipLine( - [prevIs.x, prevIs.y, oppositeMidX.toNumber(), oppositeMidY.toNumber()], - canvas, - roof, - textMode, - - prevDegree, - prevDegree, - ) - baseHipLines.push({ - x1: prevLine.x1, - y1: prevLine.y1, - x2: oppositeMidX.toNumber(), - y2: oppositeMidY.toNumber(), - line: prevHipLine, - }) - } - - const nextHipEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - vertex2: { x: nextLine.x2, y: nextLine.y2 }, - } - const nextHipVectorX = Math.sign(nextHipEdge.vertex1.x - nextHipEdge.vertex2.x) - const nextHipVectorY = Math.sign(nextHipEdge.vertex1.y - nextHipEdge.vertex2.y) - const nextIsPoints = [] - - roof.lines - .filter((line) => (Math.sign(nextLine.x1 - nextLine.x2) === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(nextHipEdge, lineEdge) - if (is) { - const isVectorX = Math.sign(nextHipEdge.vertex1.x - is.x) - const isVectorY = Math.sign(nextHipEdge.vertex1.y - is.y) - if (isVectorX === nextHipVectorX && isVectorY === nextHipVectorY) { - const size = Big(nextHipEdge.vertex1.x) - .minus(Big(is.x)) - .abs() - .pow(2) - .plus(Big(nextHipEdge.vertex1.y).minus(Big(is.y)).abs().pow(2)) - .sqrt() - .toNumber() - nextIsPoints.push({ is, size }) - } - } - }) - if (nextIsPoints.length > 0) { - const nextIs = nextIsPoints.sort((a, b) => a.size - b.size)[0].is - const nextHipLine = drawHipLine( - [nextIs.x, nextIs.y, oppositeMidX.toNumber(), oppositeMidY.toNumber()], - canvas, - roof, - textMode, - - nextDegree, - nextDegree, - ) - baseHipLines.push({ - x1: nextLine.x2, - y1: nextLine.y2, - x2: oppositeMidX.toNumber(), - y2: oppositeMidY.toNumber(), - line: nextHipLine, - }) - } - const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX)) - const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY)) - - /** 반철처 인 경우 처리 */ - if (currentLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const width = Big(currentLine.attributes.width).div(2) - const degree = getDegreeByChon(currentLine.attributes.pitch) - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - const nextDegree = getDegreeByChon(nextLine.attributes.pitch) - if (vectorOppositeY === 0) { - currentMidX = currentMidX.minus(Big(width).times(vectorOppositeX)) - } else { - currentMidY = currentMidY.minus(Big(width).times(vectorOppositeY)) - } - - /** 현재 라인에서 반철처 부분을 그린다.*/ - let firstHipPoint, secondHipPoint, connectHipPoint, firstRoofPoint, secondRoofPoint - if (vectorOppositeY === 0) { - firstHipPoint = [ - currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(), - currentMidY.minus(Big(width).times(prevRoofVectorY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - - secondHipPoint = [ - currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(), - currentMidY.minus(Big(width).times(nextRoofVectorY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - } else { - firstHipPoint = [ - currentMidX.plus(Big(width).times(prevRoofVectorX)).toNumber(), - currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - - secondHipPoint = [ - currentMidX.plus(Big(width).times(nextRoofVectorX)).toNumber(), - currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - } - connectHipPoint = [firstHipPoint[0], firstHipPoint[1], secondHipPoint[0], secondHipPoint[1]] - firstRoofPoint = [currentRoof.x1, currentRoof.y1, firstHipPoint[0], firstHipPoint[1]] - secondRoofPoint = [currentRoof.x2, currentRoof.y2, secondHipPoint[0], secondHipPoint[1]] - const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, degree, degree) - const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, prevDegree, prevDegree) - const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, degree, degree) - const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, nextDegree, nextDegree) - const connectHipLine = drawRoofLine(connectHipPoint, canvas, roof, textMode) - baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine }) - baseHipLines.push({ x1: firstRoofLine.x1, y1: firstRoofLine.y1, x2: firstRoofLine.x2, y2: firstRoofLine.y2, line: firstRoofLine }) - baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine }) - baseHipLines.push({ x1: secondRoofLine.x1, y1: secondRoofLine.y1, x2: secondRoofLine.x2, y2: secondRoofLine.y2, line: secondRoofLine }) - baseHipLines.push({ x1: connectHipLine.x1, y1: connectHipLine.y1, x2: connectHipLine.x2, y2: connectHipLine.y2, line: connectHipLine }) - } else { - const firstHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX.toNumber(), currentMidY.toNumber()] - const secondHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX.toNumber(), currentMidY.toNumber()] - const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, prevDegree, prevDegree) - const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, nextDegree, nextDegree) - baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine }) - baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine }) - } - - if (baseRidgeCount < getMaxRidge(baseLines.length)) { - const ridgeLine = drawRidgeLine( - [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()], - canvas, - roof, - textMode, - ) - baseGableRidgeLines.push(ridgeLine) - baseRidgeCount++ - } - } else { - if (beforePrevBaseLine === afterNextBaseLine) { - const afterNextMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2) - const afterNextMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2) - const vectorMidX = Math.sign(currentMidX.minus(afterNextMidX)) - const vectorMidY = Math.sign(currentMidY.minus(afterNextMidY)) - - let oppositeMidX, oppositeMidY - if (afterNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - const checkSize = currentMidX - .minus(afterNextMidX) - .pow(2) - .plus(currentMidY.minus(afterNextMidY).pow(2)) - .sqrt() - .minus(Big(afterNextLine.attributes.planeSize).div(20)) - .round(1) - oppositeMidX = currentMidX.plus(checkSize.times(vectorMidX).neg()) - oppositeMidY = currentMidY.plus(checkSize.times(vectorMidY).neg()) - - const xVector1 = Math.sign(Big(oppositeMidX).minus(Big(afterNextLine.x1)).neg().toNumber()) - const yVector1 = Math.sign(Big(oppositeMidY).minus(Big(afterNextLine.y1)).neg().toNumber()) - const xVector2 = Math.sign(Big(oppositeMidX).minus(Big(afterNextLine.x2)).neg().toNumber()) - const yVector2 = Math.sign(Big(oppositeMidY).minus(Big(afterNextLine.y2)).neg().toNumber()) - - let addOppositeX1 = 0, - addOppositeY1 = 0, - addOppositeX2 = 0, - addOppositeY2 = 0 - - if (!checkWallPolygon.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) { - const checkScale = currentMidX.minus(oppositeMidX).pow(2).plus(currentMidY.minus(oppositeMidY).pow(2)).sqrt() - addOppositeX1 = checkScale.times(xVector1).toNumber() - addOppositeY1 = checkScale.times(yVector1).toNumber() - addOppositeX2 = checkScale.times(xVector2).toNumber() - addOppositeY2 = checkScale.times(yVector2).toNumber() - } - - let scale1 = Big(afterNextLine.attributes.offset).pow(2).plus(Big(nextLine.attributes.offset).pow(2)).sqrt() - scale1 = scale1.eq(0) ? Big(1) : scale1 - let scale2 = Big(afterNextLine.attributes.offset).pow(2).plus(Big(prevLine.attributes.offset).pow(2)).sqrt() - scale2 = scale2.eq(0) ? Big(1) : scale2 - - const checkHip1 = { - x1: Big(afterNextLine.x1).plus(scale1.times(xVector1)).toNumber(), - y1: Big(afterNextLine.y1).plus(scale1.times(yVector1)).toNumber(), - x2: oppositeMidX.plus(addOppositeX1).toNumber(), - y2: oppositeMidY.plus(addOppositeY1).toNumber(), - } - - const checkHip2 = { - x1: Big(afterNextLine.x2).plus(scale2.times(xVector2)).toNumber(), - y1: Big(afterNextLine.y2).plus(scale2.times(yVector2)).toNumber(), - x2: oppositeMidX.plus(addOppositeX2).toNumber(), - y2: oppositeMidY.plus(addOppositeY2).toNumber(), - } - - 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 afterNextDegree = getDegreeByChon(afterNextLine.attributes.pitch) - - if (intersection1) { - const hipLine = drawHipLine( - [intersection1.intersection.x, intersection1.intersection.y, oppositeMidX.plus(addOppositeX1), oppositeMidY.plus(addOppositeY1)], - canvas, - roof, - textMode, - - nextDegree, - afterNextDegree, - ) - baseHipLines.push({ - x1: afterNextLine.x1, - y1: afterNextLine.y1, - x2: oppositeMidX.plus(addOppositeX1).toNumber(), - y2: oppositeMidY.plus(addOppositeY1).toNumber(), - line: hipLine, - }) - } - if (intersection2) { - const hipLine = drawHipLine( - [intersection2.intersection.x, intersection2.intersection.y, oppositeMidX.plus(addOppositeX2), oppositeMidY.plus(addOppositeY2)], - canvas, - roof, - textMode, - - prevDegree, - afterNextDegree, - ) - baseHipLines.push({ - x1: afterNextLine.x2, - y1: afterNextLine.y2, - x2: oppositeMidX.plus(addOppositeX2).toNumber(), - y2: oppositeMidY.plus(addOppositeY2).toNumber(), - line: hipLine, - }) - } - } else { - oppositeMidX = Big(afterNextLine.x1).plus(Big(afterNextLine.x2)).div(2).plus(Big(prevVectorX).neg().times(afterNextLine.attributes.offset)) - oppositeMidY = Big(afterNextLine.y1).plus(Big(afterNextLine.y2)).div(2).plus(Big(prevVectorY).neg().times(afterNextLine.attributes.offset)) - } - - const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX)) - const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY)) - - if (vectorMidX === vectorOppositeX && vectorMidY === vectorOppositeY) { - if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) { - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - } - const intersectionPoints = [] - - roof.lines - .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : 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(checkEdge, lineEdge) - if ( - intersection && - ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || - (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) - ) { - const size = Big(intersection.x) - .minus(currentMidX) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) - .sqrt() - .toNumber() - intersectionPoints.push({ intersection, size }) - } - }) - - if (intersectionPoints.length > 0) { - const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection - currentMidX = Big(intersection.x) - currentMidY = Big(intersection.y) - } - } - - if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) { - const checkEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - const intersectionPoints = [] - - roof.lines - .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : 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(checkEdge, lineEdge) - if ( - intersection && - ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || - (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) - ) { - const size = Big(intersection.x) - .minus(oppositeMidX) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)) - .sqrt() - .toNumber() - intersectionPoints.push({ intersection, size }) - } - }) - - if (intersectionPoints.length > 0) { - const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection - oppositeMidX = Big(intersection.x) - oppositeMidY = Big(intersection.y) - } - } - - if (afterNextLine.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) { - const width = afterNextLine.attributes.width - if (vectorOppositeY === 0) { - oppositeMidX = oppositeMidX.plus(Big(width).times(vectorOppositeX)) - } else { - oppositeMidY = oppositeMidY.plus(Big(width).times(vectorOppositeY)) - } - } - - if (afterNextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const width = Big(afterNextLine.attributes.width).div(2).toNumber() - if (vectorOppositeY === 0) { - oppositeMidX = oppositeMidX.plus(Big(width).times(vectorOppositeX)) - } else { - oppositeMidY = oppositeMidY.plus(Big(width).times(vectorOppositeY)) - } - } - - /** 반철처 인 경우 처리 */ - if (currentLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const width = Big(currentLine.attributes.width).div(2) - const degree = getDegreeByChon(currentLine.attributes.pitch) - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - const nextDegree = getDegreeByChon(nextLine.attributes.pitch) - if (vectorMidY === 0) { - currentMidX = currentMidX.minus(Big(width).times(vectorOppositeX)) - } else { - currentMidY = currentMidY.minus(Big(width).times(vectorOppositeY)) - } - - /** 현재 라인에서 반철처 부분을 그린다.*/ - let firstHipPoint, secondHipPoint, connectHipPoint, firstRoofPoint, secondRoofPoint - if (vectorMidY === 0) { - firstHipPoint = [ - currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(), - currentMidY.minus(Big(width).times(prevRoofVectorY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - - secondHipPoint = [ - currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(), - currentMidY.minus(Big(width).times(nextRoofVectorY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - } else { - firstHipPoint = [ - currentMidX.minus(Big(width).times(prevRoofVectorX)).toNumber(), - currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - - secondHipPoint = [ - currentMidX.minus(Big(width).times(nextRoofVectorX)).toNumber(), - currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - } - connectHipPoint = [firstHipPoint[0], firstHipPoint[1], secondHipPoint[0], secondHipPoint[1]] - firstRoofPoint = [currentRoof.x1, currentRoof.y1, firstHipPoint[0], firstHipPoint[1]] - secondRoofPoint = [currentRoof.x2, currentRoof.y2, secondHipPoint[0], secondHipPoint[1]] - const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, degree, degree) - const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, prevDegree, prevDegree) - const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, degree, degree) - const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, nextDegree, nextDegree) - const connectHipLine = drawRoofLine(connectHipPoint, canvas, roof, textMode) - baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine }) - baseHipLines.push({ x1: firstRoofLine.x1, y1: firstRoofLine.y1, x2: firstRoofLine.x2, y2: firstRoofLine.y2, line: firstRoofLine }) - baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine }) - baseHipLines.push({ x1: secondRoofLine.x1, y1: secondRoofLine.y1, x2: secondRoofLine.x2, y2: secondRoofLine.y2, line: secondRoofLine }) - baseHipLines.push({ x1: connectHipLine.x1, y1: connectHipLine.y1, x2: connectHipLine.x2, y2: connectHipLine.y2, line: connectHipLine }) - } else { - const firstHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX.toNumber(), currentMidY.toNumber()] - const secondHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX.toNumber(), currentMidY.toNumber()] - const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, prevDegree, prevDegree) - const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, nextDegree, nextDegree) - baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine }) - baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine }) - } - - if (baseRidgeCount < getMaxRidge(baseLines.length)) { - const ridge = drawRidgeLine( - [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()], - canvas, - roof, - textMode, - ) - baseGableRidgeLines.push(ridge) - baseRidgeCount++ - } - } - } else { - const vectorMidX = Math.sign(Big(nextLine.x2).minus(nextLine.x1)) - const vectorMidY = Math.sign(Big(nextLine.y2).minus(nextLine.y1)) - - let prevOppositeMidX, prevOppositeMidY, nextOppositeMidX, nextOppositeMidY - const beforePrevOffset = - currentAngle === beforePrevAngle - ? Big(beforePrevLine.attributes.offset) - : Big(beforePrevLine.attributes.offset).plus(currentLine.attributes.offset) - const afterNextOffset = - currentAngle === afterNextAngle - ? Big(afterNextLine.attributes.offset) - : Big(afterNextLine.attributes.offset).plus(currentLine.attributes.offset) - const prevSize = Big(calcLinePlaneSize(prevLine)).div(10) - const nextSize = Big(calcLinePlaneSize(nextLine)).div(10) - - let prevHipCoords, nextHipCoords - - /** 다음 라인이 그 다음 라인과의 사이에 추녀마루가 존재 하는지 확인. 처마-처마 인 경우 추녀마루*/ - if (eavesType.includes(afterNextLine.attributes?.type)) { - /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/ - let hipLength = Big(size).div(10).div(2).pow(2).plus(Big(size).div(10).div(2).pow(2)).sqrt() - - const nextHalfVector = getHalfAngleVector(nextLine, afterNextLine) - let nextHipVector = { x: nextHalfVector.x, y: nextHalfVector.y } - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const nextCheckPoint = { - x: Big(nextLine.x2).plus(Big(nextHalfVector.x).times(10)), - y: Big(nextLine.y2).plus(Big(nextHalfVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(nextCheckPoint)) { - nextHipVector = { x: Big(nextHipVector.x).neg().toNumber(), y: Big(nextHipVector.y).neg().toNumber() } - } - - const nextEndPoint = { - x: Big(nextLine.x2).plus(Big(nextHipVector.x).times(hipLength)), - y: Big(nextLine.y2).plus(Big(nextHipVector.y).times(hipLength)), - } - - let ridgeEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { - x: currentMidX.plus(Big(nextVectorX).times(nextBaseLine.size)).toNumber(), - y: currentMidY.plus(Big(nextVectorY).times(nextBaseLine.size)).toNumber(), - }, - } - let hipEdge = { - vertex1: { x: nextLine.x2, y: nextLine.y2 }, - vertex2: { x: nextEndPoint.x, y: nextEndPoint.y }, - } - let intersection = edgesIntersection(ridgeEdge, hipEdge) - if (intersection) { - nextHipCoords = { x1: nextLine.x2, y1: nextLine.y2, x2: intersection.x, y2: intersection.y } - nextOppositeMidY = Big(intersection.y) - nextOppositeMidX = Big(intersection.x) - } - } else { - if (vectorMidX === 0) { - nextOppositeMidY = currentMidY.plus(nextSize.plus(afterNextOffset).times(vectorMidY)) - nextOppositeMidX = currentMidX - } else { - nextOppositeMidX = currentMidX.plus(nextSize.plus(afterNextOffset).times(vectorMidX)) - nextOppositeMidY = currentMidY - } - } - - /** 이전 라인이 그 이전 라인과의 사이에 추녀마루가 존재 하는지 확인. 처마-처마 인 경우 추녀마루*/ - if (eavesType.includes(beforePrevLine.attributes?.type)) { - /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/ - let hipLength = Big(size).div(10).div(2).pow(2).plus(Big(size).div(10).div(2).pow(2)).sqrt() - - const prevHalfVector = getHalfAngleVector(prevLine, beforePrevLine) - let prevHipVector = { x: prevHalfVector.x, y: prevHalfVector.y } - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const prevCheckPoint = { - x: Big(prevLine.x1).plus(Big(prevHalfVector.x).times(10)), - y: Big(prevLine.y1).plus(Big(prevHalfVector.y).times(10)), - } - - if (!checkWallPolygon.inPolygon(prevCheckPoint)) { - prevHipVector = { x: Big(prevHipVector.x).neg().toNumber(), y: Big(prevHipVector.y).neg().toNumber() } - } - - const prevEndPoint = { - x: Big(prevLine.x1).plus(Big(prevHipVector.x).times(hipLength)), - y: Big(prevLine.y1).plus(Big(prevHipVector.y).times(hipLength)), - } - - let ridgeEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { - x: currentMidX.plus(Big(prevVectorX).times(prevBaseLine.size)).toNumber(), - y: currentMidY.plus(Big(prevVectorY).times(prevBaseLine.size)).toNumber(), - }, - } - let hipEdge = { - vertex1: { x: prevLine.x1, y: prevLine.y1 }, - vertex2: { x: prevEndPoint.x, y: prevEndPoint.y }, - } - let intersection = edgesIntersection(ridgeEdge, hipEdge) - if (intersection) { - prevHipCoords = { x1: prevLine.x1, y1: prevLine.y1, x2: intersection.x, y2: intersection.y } - prevOppositeMidY = Big(intersection.y) - prevOppositeMidX = Big(intersection.x) - } - } else { - if (vectorMidX === 0) { - prevOppositeMidY = currentMidY.plus(prevSize.plus(beforePrevOffset).times(vectorMidY)) - prevOppositeMidX = currentMidX - } else { - prevOppositeMidX = currentMidX.plus(prevSize.plus(beforePrevOffset).times(vectorMidX)) - prevOppositeMidY = currentMidY - } - } - - const currentMidEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { - x: currentVectorX === 0 ? nextLine.x2 : currentMidX.toNumber(), - y: currentVectorX === 0 ? currentMidY.toNumber() : nextLine.y2, - }, - } - - let oppositeLines = [] - drawBaseLines - .filter((line, index) => { - const currentLine = line.line - const nextLine = drawBaseLines[(index + 1) % drawBaseLines.length].line - const prevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length].line - const angle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - if (angle === prevAngle || angle === nextAngle) { - const sameAngleLine = angle === prevAngle ? prevLine : nextLine - if (gableType.includes(currentLine.attributes.type) && !gableType.includes(sameAngleLine.attributes.type)) { - switch (currentAngle) { - case 90: - return angle === -90 - case -90: - return angle === 90 - case 0: - return angle === 180 - case 180: - return angle === 0 - } - } - } - return false - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(currentMidEdge, lineEdge) - if (intersection) { - if (line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) { - oppositeLines.push({ - line, - intersection, - size: Big(intersection.x) - .minus(currentMidX) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) - .sqrt() - .toNumber(), - }) - } - } - }) - - if (oppositeLines.length > 0) { - const oppositePoint = oppositeLines.sort((a, b) => a.size - b.size)[0].intersection - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { x: oppositePoint.x, y: oppositePoint.y }, - } - const oppositeRoofPoints = [] - roof.lines - .filter((line) => { - const angle = calculateAngle(line.startPoint, line.endPoint) - switch (currentAngle) { - case 90: - return angle === -90 - case -90: - return angle === 90 - case 0: - return angle === 180 - case 180: - return angle === 0 - } - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if ( - intersection && - ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || - (line.x1 >= intersection.x && line.x2 <= intersection.x && line.y1 >= intersection.y && line.y2 <= intersection.y)) - ) { - oppositeRoofPoints.push({ - line, - intersection, - size: Big(intersection.x) - .minus(currentMidX.toNumber()) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(currentMidY.toNumber()).abs().pow(2)) - .sqrt() - .toNumber(), - }) - } - }) - const oppositeRoofPoint = oppositeRoofPoints.sort((a, b) => a.size - b.size)[0].intersection - oppositeMidX = Big(oppositeRoofPoint.x) - oppositeMidY = Big(oppositeRoofPoint.y) - - const currentRoofPoints = [] - roof.lines - .filter((line) => { - const angle = calculateAngle(line.startPoint, line.endPoint) - return currentAngle === angle - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if ( - intersection && - ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || - (line.x1 >= intersection.x && line.x2 <= intersection.x && line.y1 >= intersection.y && line.y2 <= intersection.y)) - ) { - currentRoofPoints.push({ - line, - intersection, - size: Big(intersection.x) - .minus(currentMidX.toNumber()) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(currentMidY.toNumber()).abs().pow(2)) - .sqrt() - .toNumber(), - }) - } - }) - const currentRoofPoint = currentRoofPoints.sort((a, b) => a.size - b.size)[0].intersection - currentMidX = Big(currentRoofPoint.x) - currentMidY = Big(currentRoofPoint.y) - } else { - const checkPrevSize = currentMidX.minus(prevOppositeMidX).pow(2).plus(currentMidY.minus(prevOppositeMidY).pow(2)).sqrt() - const checkNextSize = currentMidX.minus(nextOppositeMidX).pow(2).plus(currentMidY.minus(nextOppositeMidY).pow(2)).sqrt() - - /** 두 포인트 중에 current와 가까운 포인트를 사용*/ - if (checkPrevSize.gt(checkNextSize)) { - if (nextHipCoords) { - let intersectPoints = [] - const hipEdge = { - vertex1: { x: nextHipCoords.x2, y: nextHipCoords.y2 }, - vertex2: { x: nextHipCoords.x1, y: nextHipCoords.y1 }, - } - - /** 외벽선에서 라인 겹치는 경우에 대한 확인*/ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - Math.sign(nextHipCoords.x2 - nextHipCoords.x1) === Math.sign(nextHipCoords.x2 - intersection.x) && - 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 is = edgesIntersection(intersectEdge, lineEdge) - if (!is.isIntersectionOutside) { - const intersectSize = Big(nextHipCoords.x2) - .minus(Big(intersection.x)) - .pow(2) - .plus(Big(nextHipCoords.y2).minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - line, - }) - } - } - }) - const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0] - if (intersect) { - const degree = getDegreeByChon(intersect.line.attributes.pitch) - const hipLine = drawHipLine( - [intersect.intersection.x, intersect.intersection.y, nextOppositeMidX.toNumber(), nextOppositeMidY.toNumber()], - canvas, - roof, - textMode, - - degree, - degree, - ) - baseHipLines.push({ - x1: nextHipCoords.x1, - y1: nextHipCoords.y1, - x2: nextHipCoords.x2, - y2: nextHipCoords.y2, - line: hipLine, - }) - } - } - oppositeMidY = nextOppositeMidY - oppositeMidX = nextOppositeMidX - } else { - if (prevHipCoords) { - let intersectPoints = [] - const hipEdge = { - vertex1: { x: prevHipCoords.x2, y: prevHipCoords.y2 }, - vertex2: { x: prevHipCoords.x1, y: prevHipCoords.y1 }, - } - - /** 외벽선에서 라인 겹치는 경우에 대한 확인*/ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - Math.sign(prevHipCoords.x2 - prevHipCoords.x1) === Math.sign(prevHipCoords.x2 - intersection.x) && - 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 is = edgesIntersection(intersectEdge, lineEdge) - if (!is.isIntersectionOutside) { - const intersectSize = Big(prevHipCoords.x2) - .minus(Big(intersection.x)) - .pow(2) - .plus(Big(prevHipCoords.y2).minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - line, - }) - } - } - }) - const intersect = intersectPoints.sort((a, b) => a.size - b.size)[0] - - if (intersect) { - const degree = getDegreeByChon(intersect.line.attributes.pitch) - const hipLine = drawHipLine( - [intersect.intersection.x, intersect.intersection.y, prevOppositeMidX.toNumber(), prevOppositeMidY.toNumber()], - canvas, - roof, - textMode, - - degree, - degree, - ) - baseHipLines.push({ - x1: prevHipCoords.x1, - y1: prevHipCoords.y1, - x2: prevHipCoords.x2, - y2: prevHipCoords.y2, - line: hipLine, - }) - } - } - oppositeMidY = prevOppositeMidY - oppositeMidX = prevOppositeMidX - } - } - - /** 포인트가 지붕 밖에 있는 경우 조정 */ - if (!roof.inPolygon({ x: currentMidX.toNumber(), y: currentMidY.toNumber() })) { - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - } - const intersectionPoints = [] - - roof.lines - .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : 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(checkEdge, lineEdge) - if ( - intersection && - ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || - (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) - ) { - const size = Big(intersection.x) - .minus(currentMidX) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) - .sqrt() - .toNumber() - intersectionPoints.push({ intersection, size }) - } - }) - - if (intersectionPoints.length > 0) { - const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection - currentMidX = Big(intersection.x) - currentMidY = Big(intersection.y) - } - } - - if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) { - const checkEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - const intersectionPoints = [] - - roof.lines - .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : 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(checkEdge, lineEdge) - if ( - intersection && - ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || - (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) - ) { - const size = Big(intersection.x) - .minus(oppositeMidX) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)) - .sqrt() - .toNumber() - intersectionPoints.push({ intersection, size }) - } - }) - - if (intersectionPoints.length > 0) { - const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection - oppositeMidX = Big(intersection.x) - oppositeMidY = Big(intersection.y) - } - } - - const vectorOppositeX = Math.sign(currentMidX.minus(oppositeMidX)) - const vectorOppositeY = Math.sign(currentMidY.minus(oppositeMidY)) - - /** 반철처 인 경우 처리 */ - if (currentLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const width = Big(currentLine.attributes.width).div(2) - const degree = getDegreeByChon(currentLine.attributes.pitch) - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - const nextDegree = getDegreeByChon(nextLine.attributes.pitch) - if (vectorOppositeY === 0) { - currentMidX = currentMidX.minus(Big(width).times(vectorOppositeX)) - } else { - currentMidY = currentMidY.minus(Big(width).times(vectorOppositeY)) - } - - /** 현재 라인에서 반철처 부분을 그린다.*/ - let firstHipPoint, secondHipPoint, connectHipPoint, firstRoofPoint, secondRoofPoint - if (vectorOppositeY === 0) { - firstHipPoint = [ - currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(), - currentMidY.minus(Big(width).times(prevRoofVectorY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - - secondHipPoint = [ - currentMidX.plus(Big(width).times(vectorOppositeX)).toNumber(), - currentMidY.minus(Big(width).times(nextRoofVectorY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - } else { - firstHipPoint = [ - currentMidX.minus(Big(width).times(prevRoofVectorX)).toNumber(), - currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - - secondHipPoint = [ - currentMidX.minus(Big(width).times(nextRoofVectorX)).toNumber(), - currentMidY.plus(Big(width).times(vectorOppositeY)).toNumber(), - currentMidX.toNumber(), - currentMidY.toNumber(), - ] - } - connectHipPoint = [firstHipPoint[0], firstHipPoint[1], secondHipPoint[0], secondHipPoint[1]] - firstRoofPoint = [currentRoof.x1, currentRoof.y1, firstHipPoint[0], firstHipPoint[1]] - secondRoofPoint = [currentRoof.x2, currentRoof.y2, secondHipPoint[0], secondHipPoint[1]] - const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, degree, degree) - const firstRoofLine = drawHipLine(firstRoofPoint, canvas, roof, textMode, prevDegree, prevDegree) - const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, degree, degree) - const secondRoofLine = drawHipLine(secondRoofPoint, canvas, roof, textMode, nextDegree, nextDegree) - const connectHipLine = drawRoofLine(connectHipPoint, canvas, roof, textMode) - baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine }) - baseHipLines.push({ x1: firstRoofLine.x1, y1: firstRoofLine.y1, x2: firstRoofLine.x2, y2: firstRoofLine.y2, line: firstRoofLine }) - baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine }) - baseHipLines.push({ x1: secondRoofLine.x1, y1: secondRoofLine.y1, x2: secondRoofLine.x2, y2: secondRoofLine.y2, line: secondRoofLine }) - baseHipLines.push({ x1: connectHipLine.x1, y1: connectHipLine.y1, x2: connectHipLine.x2, y2: connectHipLine.y2, line: connectHipLine }) - } else { - const firstHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX.toNumber(), currentMidY.toNumber()] - const secondHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX.toNumber(), currentMidY.toNumber()] - const firstHipLine = drawHipLine(firstHipPoint, canvas, roof, textMode, prevDegree, prevDegree) - const secondHipLine = drawHipLine(secondHipPoint, canvas, roof, textMode, nextDegree, nextDegree) - baseHipLines.push({ x1: firstHipLine.x1, y1: firstHipLine.y1, x2: firstHipLine.x2, y2: firstHipLine.y2, line: firstHipLine }) - baseHipLines.push({ x1: secondHipLine.x1, y1: secondHipLine.y1, x2: secondHipLine.x2, y2: secondHipLine.y2, line: secondHipLine }) - } - - /** 마루가 맞은편 외벽선에 닿는 경우 해당 부분까지로 한정한다. */ - const ridgeEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - } - const ridgeVectorX = Math.sign(currentMidX.minus(oppositeMidX).toNumber()) - const ridgeVectorY = Math.sign(currentMidY.minus(oppositeMidY).toNumber()) - - roof.lines - .filter((line) => { - const lineVectorX = Math.sign(Big(line.x2).minus(Big(line.x1)).toNumber()) - const lineVectorY = Math.sign(Big(line.y2).minus(Big(line.y1)).toNumber()) - return ( - (lineVectorX === currentVectorX && lineVectorY !== currentVectorY) || (lineVectorX !== currentVectorX && lineVectorY === currentVectorY) - ) - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(ridgeEdge, lineEdge) - if (intersection && !intersection.isIntersectionOutside) { - const isVectorX = Math.sign(Big(currentMidX).minus(intersection.x).toNumber()) - const isVectorY = Math.sign(Big(currentMidY).minus(intersection.y).toNumber()) - if (isVectorX === ridgeVectorX && isVectorY === ridgeVectorY) { - oppositeMidX = Big(intersection.x) - oppositeMidY = Big(intersection.y) - } - } - }) - if (baseRidgeCount < getMaxRidge(baseLines.length)) { - const ridgeLine = drawRidgeLine( - [currentMidX.toNumber(), currentMidY.toNumber(), oppositeMidX.toNumber(), oppositeMidY.toNumber()], - canvas, - roof, - textMode, - ) - baseGableRidgeLines.push(ridgeLine) - baseRidgeCount++ - } - } - } - }) - - /** 박공지붕에서 파생되는 마루를 그린다. 첫번째에서 처리 하지 못한 라인이 있는 경우 */ - drawGableRidgeSecond.forEach((current) => { - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - - /** 이전 라인의 경사 */ - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - /** 다음 라인의 경사 */ - const nextDegree = getDegreeByChon(nextLine.attributes.pitch) - - const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - const currentVectorX = Big(currentLine.x2).minus(currentLine.x1) - const currentVectorY = Big(currentLine.y2).minus(currentLine.y1) - const checkVectorX = Big(nextLine.x2).minus(Big(nextLine.x1)) - const checkVectorY = Big(nextLine.y2).minus(Big(nextLine.y1)) - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2) - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2) - const checkSize = Big(10) - - /** 현재 라인의 지붕선을 찾는다. */ - const intersectionRoofs = [] - if (currentVectorX.eq(0)) { - const checkEdge = { - vertex1: { x: prevLine.x1, y: currentMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter( - (line) => - Math.sign(line.x2 - line.x1) === Math.sign(currentVectorX.toNumber()) && - Math.sign(line.y2 - line.y1) === Math.sign(currentVectorY.toNumber()), - ) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter( - (line) => - Math.sign(line.x2 - line.x1) === Math.sign(currentVectorX.toNumber()) && - Math.sign(line.y2 - line.y1) === Math.sign(currentVectorY.toNumber()), - ) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber(), - }) - } - } - }) - } - let currentRoof - if (intersectionRoofs.length > 0) { - currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line - } - - if (currentLine.attributes.type === LINE_TYPE.WALLLINE.EAVES || currentLine.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) { - const currentMidEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { - x: currentMidX.plus(checkSize.times(Math.sign(checkVectorX.neg().toNumber()))).toNumber(), - y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.neg().toNumber()))).toNumber(), - }, - } - let oppositeLines = [] - baseLines - .filter((line) => { - if (eavesType.includes(line.attributes.type)) { - const angle = calculateAngle(line.startPoint, line.endPoint) - switch (currentAngle) { - case 90: - return angle === -90 - case -90: - return angle === 90 - case 0: - return angle === 180 - case 180: - return angle === 0 - default: - return false - } - } else { - return false - } - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(currentMidEdge, lineEdge) - if (intersection) { - oppositeLines.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - }) - - if (oppositeLines.length === 0) { - return - } - const oppositeLine = oppositeLines.sort((a, b) => b.size - a.size)[0].line - - let ridgePoint - if (currentVectorY.eq(0)) { - const ridgeY = Big(currentLine.y1).plus(Big(oppositeLine.y1)).div(2).round() - ridgePoint = [currentRoof.x1, ridgeY.toNumber(), currentRoof.x2, ridgeY.toNumber()] - } else { - const ridgeX = Big(currentLine.x1).plus(Big(oppositeLine.x1)).div(2).round() - ridgePoint = [ridgeX.toNumber(), currentRoof.y1, ridgeX.toNumber(), currentRoof.y2] - } - const isAlreadyRidge = baseGableRidgeLines.find( - (line) => - (line.x1 === ridgePoint[0] && line.y1 === ridgePoint[1] && line.x2 === ridgePoint[2] && line.y2 === ridgePoint[3]) || - (line.x1 === ridgePoint[2] && line.y1 === ridgePoint[3] && line.x2 === ridgePoint[0] && line.y2 === ridgePoint[1]) || - segmentsOverlap(line, { x1: ridgePoint[0], y1: ridgePoint[1], x2: ridgePoint[2], y2: ridgePoint[3] }), - ) - if (baseRidgeCount < getMaxRidge(baseLines.length) && !isAlreadyRidge) { - const ridgeLine = drawRidgeLine(ridgePoint, canvas, roof, textMode) - baseGableRidgeLines.push(ridgeLine) - baseRidgeCount++ - } - } else { - const checkPoints = { - x: currentMidX.plus(checkSize.times(Math.sign(checkVectorX.toNumber()))).toNumber(), - y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.toNumber()))).toNumber(), - } - if (!checkWallPolygon.inPolygon(checkPoints)) { - const currentMidEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { - x: currentMidX.plus(checkSize.times(Math.sign(checkVectorX.neg().toNumber()))).toNumber(), - y: currentMidY.plus(checkSize.times(Math.sign(checkVectorY.neg().toNumber()))).toNumber(), - }, - } - - let oppositeLines = [] - baseLines - .filter((line, index) => { - let nextLine = baseLines[(index + 1) % baseLines.length] - let prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length] - if ( - (gableType.includes(nextLine.attributes.type) && gableType.includes(prevLine.attributes.type)) || - (eavesType.includes(nextLine.attributes.type) && eavesType.includes(prevLine.attributes.type)) - ) { - const angle = calculateAngle(line.startPoint, line.endPoint) - switch (currentAngle) { - case 90: - return angle === -90 - case -90: - return angle === 90 - case 0: - return angle === 180 - case 180: - return angle === 0 - } - } - return false - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(currentMidEdge, lineEdge) - if (intersection) { - oppositeLines.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - }) - - if (oppositeLines.length === 0) { - return - } - const oppositeLine = oppositeLines.sort((a, b) => a.size - b.size)[0] - - let points = [] - if (eavesType.includes(oppositeLine.line.attributes.type)) { - const oppositeCurrentLine = oppositeLine.line - let oppositePrevLine, oppositeNextLine - baseLines.forEach((line, index) => { - if (line === oppositeCurrentLine) { - oppositePrevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length] - oppositeNextLine = baseLines[(index + 1) % baseLines.length] - } - }) - if (gableType.includes(oppositeNextLine.attributes.type) && gableType.includes(oppositePrevLine.attributes.type)) { - if (currentVectorX.eq(0)) { - const centerX = currentMidX.plus(oppositeLine.intersection.x).div(2).toNumber() - points = [centerX, currentLine.y1, centerX, currentLine.y2] - } else { - const centerY = currentMidY.plus(oppositeLine.intersection.y).div(2).toNumber() - points = [currentLine.x1, centerY, currentLine.x2, centerY] - } - } - if (eavesType.includes(oppositeNextLine.attributes.type) && eavesType.includes(oppositePrevLine.attributes.type)) { - /** 이전, 다음라인의 사잇각의 vector를 구한다. */ - let prevVector = getHalfAngleVector(oppositePrevLine, oppositeCurrentLine) - let nextVector = getHalfAngleVector(oppositeCurrentLine, oppositeNextLine) - - let prevHipVector = { x: Big(prevVector.x), y: Big(prevVector.y) } - let nextHipVector = { x: Big(nextVector.x), y: Big(nextVector.y) } - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const prevCheckPoint = { - x: Big(oppositeCurrentLine.x1).plus(Big(prevHipVector.x).times(10)), - y: Big(oppositeCurrentLine.y1).plus(Big(prevHipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(prevCheckPoint)) { - prevHipVector = { x: Big(prevHipVector.x).neg(), y: Big(prevHipVector.y).neg() } - } - - /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const nextCheckPoint = { - x: Big(oppositeCurrentLine.x2).plus(Big(nextHipVector.x).times(10)), - y: Big(oppositeCurrentLine.y2).plus(Big(nextHipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(nextCheckPoint)) { - nextHipVector = { x: Big(nextHipVector.x).neg(), y: Big(nextHipVector.y).neg() } - } - - /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/ - let hipLength = Big(oppositeCurrentLine.attributes.planeSize) - .div(2) - .pow(2) - .plus(Big(oppositeCurrentLine.attributes.planeSize).div(2).pow(2)) - .sqrt() - .div(10) - .round(2) - - const ridgeEndPoint = { - x: Big(oppositeCurrentLine.x1).plus(hipLength.times(prevHipVector.x)).round(1), - y: Big(oppositeCurrentLine.y1).plus(hipLength.times(prevHipVector.y)).round(1), - } - - const prevHypotenuse = Big(oppositePrevLine.attributes.offset).pow(2).plus(Big(oppositeCurrentLine.attributes.offset).pow(2)).sqrt() - const prevHipPoints = { - x1: Big(oppositeCurrentLine.x1).plus(prevHypotenuse.times(prevHipVector.x.neg())).round(1).toNumber(), - y1: Big(oppositeCurrentLine.y1).plus(prevHypotenuse.times(prevHipVector.y.neg())).round(1).toNumber(), - x2: ridgeEndPoint.x.toNumber(), - y2: ridgeEndPoint.y.toNumber(), - } - - const nextHypotenuse = Big(oppositeNextLine.attributes.offset).pow(2).plus(Big(oppositeCurrentLine.attributes.offset).pow(2)).sqrt() - const nextHipPoints = { - x1: Big(oppositeCurrentLine.x2).plus(nextHypotenuse.times(nextHipVector.x.neg())).round(1).toNumber(), - y1: Big(oppositeCurrentLine.y2).plus(nextHypotenuse.times(nextHipVector.y.neg())).round(1).toNumber(), - x2: ridgeEndPoint.x.toNumber(), - y2: ridgeEndPoint.y.toNumber(), - } - - const prevIntersection = findRoofIntersection(roof, prevHipPoints, ridgeEndPoint) - const nextIntersection = findRoofIntersection(roof, nextHipPoints, ridgeEndPoint) - - if (prevIntersection) { - const prevHip = drawHipLine( - [prevIntersection.intersection.x, prevIntersection.intersection.y, ridgeEndPoint.x.toNumber(), ridgeEndPoint.y.toNumber()], - canvas, - roof, - textMode, - - prevDegree, - prevDegree, - ) - baseHipLines.push({ - x1: oppositeCurrentLine.x1, - y1: oppositeCurrentLine.y1, - x2: ridgeEndPoint.x, - y2: ridgeEndPoint.y, - line: prevHip, - }) - } - if (nextIntersection) { - const nextHip = drawHipLine( - [nextIntersection.intersection.x, nextIntersection.intersection.y, ridgeEndPoint.x.toNumber(), ridgeEndPoint.y.toNumber()], - canvas, - roof, - textMode, - - nextDegree, - nextDegree, - ) - baseHipLines.push({ - x1: ridgeEndPoint.x, - y1: ridgeEndPoint.y, - x2: oppositeCurrentLine.x2, - y2: oppositeCurrentLine.y2, - line: nextHip, - }) - } - - const ridgeVectorX = Math.sign(currentMidX.minus(ridgeEndPoint.x).toNumber()) - const ridgeVectorY = Math.sign(currentMidY.minus(ridgeEndPoint.y).toNumber()) - const ridgePoints = { - x1: currentMidX.plus(Big(currentLine.attributes.offset).times(ridgeVectorX)).toNumber(), - y1: currentMidY.plus(Big(currentLine.attributes.offset).times(ridgeVectorY)).toNumber(), - x2: ridgeEndPoint.x.toNumber(), - y2: ridgeEndPoint.y.toNumber(), - } - const ridgeIntersection = findRoofIntersection(roof, ridgePoints, { - x: Big(ridgePoints.x2), - y: Big(ridgePoints.y2), - }) - if (ridgeIntersection) { - points = [ridgeIntersection.intersection.x, ridgeIntersection.intersection.y, ridgeEndPoint.x, ridgeEndPoint.y] - } - } - } else { - if (currentVectorX.eq(0)) { - points = [oppositeLine.intersection.x, currentLine.y1, oppositeLine.intersection.x, currentLine.y2] - } else { - points = [currentLine.x1, oppositeLine.intersection.y, currentLine.x2, oppositeLine.intersection.y] - } - } - - const isAlreadyRidge = baseGableRidgeLines.find( - (line) => - (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) || - (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]), - ) - if (baseRidgeCount < getMaxRidge(baseLines.length) && !isAlreadyRidge) { - const ridgeLine = drawRidgeLine(points, canvas, roof, textMode) - baseGableRidgeLines.push(ridgeLine) - baseRidgeCount++ - } - } else { - const oppositeLines = baseLines.filter((line) => { - const lineAngle = calculateAngle(line.startPoint, line.endPoint) - switch (currentAngle) { - case 90: - return lineAngle === -90 - case -90: - return lineAngle === 90 - case 0: - return lineAngle === 180 - case 180: - return lineAngle === 0 - } - }) - - if (oppositeLines.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) { - let ridgePoints = [] - const oppositeLine = oppositeLines.sort((a, b) => { - let diffCurrentA, diffCurrentB - if (Math.sign(currentVectorX) === 0) { - diffCurrentA = currentMidY.minus(a.y1).abs() - diffCurrentB = currentMidY.minus(b.y1).abs() - } else { - diffCurrentA = currentMidX.minus(a.x1).abs() - diffCurrentB = currentMidX.minus(b.x1).abs() - } - return diffCurrentA.minus(diffCurrentB).toNumber() - })[0] - - const prevOffset = prevLine.attributes.offset - const nextOffset = nextLine.attributes.offset - if (Math.sign(currentVectorX) === 0) { - const prevY = Big(currentLine.y1) - .plus(Big(Math.sign(currentVectorY)).neg().times(prevOffset)) - .toNumber() - const nextY = Big(currentLine.y2) - .plus(Big(Math.sign(currentVectorY)).times(nextOffset)) - .toNumber() - const midX = Big(currentLine.x1).plus(oppositeLine.x1).div(2).toNumber() - ridgePoints = [midX, prevY, midX, nextY] - } else { - const prevX = Big(currentLine.x1) - .plus(Big(Math.sign(currentVectorX)).neg().times(prevOffset)) - .toNumber() - const nextX = Big(currentLine.x2) - .plus(Big(Math.sign(currentVectorX)).times(nextOffset)) - .toNumber() - const midY = Big(currentLine.y1).plus(oppositeLine.y1).div(2).toNumber() - ridgePoints = [prevX, midY, nextX, midY] - } - const isAlreadyRidge = baseGableRidgeLines.find( - (line) => - (line.x1 === ridgePoints[0] && line.y1 === ridgePoints[1] && line.x2 === ridgePoints[2] && line.y2 === ridgePoints[3]) || - (line.x1 === ridgePoints[2] && line.y1 === ridgePoints[3] && line.x2 === ridgePoints[0] && line.y2 === ridgePoints[1]), - ) - if (!isAlreadyRidge) { - const ridge = drawRidgeLine(ridgePoints, canvas, roof, textMode) - baseGableRidgeLines.push(ridge) - baseRidgeCount++ - } - } - } - } - }) - - const uniqueRidgeLines = [] - /** 중복제거 */ - baseGableRidgeLines.forEach((currentLine, index) => { - if (index === 0) { - uniqueRidgeLines.push(currentLine) - } else { - const duplicateLines = uniqueRidgeLines.filter( - (line) => - (currentLine.x1 === line.x1 && currentLine.y1 === line.y1 && currentLine.x2 === line.x2 && currentLine.y2 === line.y2) || - (currentLine.x1 === line.x2 && currentLine.y1 === line.y2 && currentLine.x2 === line.x1 && currentLine.y2 === line.y1), - ) - if (duplicateLines.length === 0) { - uniqueRidgeLines.push(currentLine) - } - } - }) - - baseGableRidgeLines = uniqueRidgeLines - - /** 박공지붕 polygon 생성 */ - drawGablePolygonFirst.forEach((current) => { - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - - const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1) - const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1) - const nextVectorX = Math.sign(nextLine.x1 - nextLine.x2) - const nextVectorY = Math.sign(nextLine.y1 - nextLine.y2) - const currentDegree = getDegreeByChon(currentLine.attributes.pitch) - - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2) - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2) - const intersectionRoofs = [] - if (currentVectorX === 0) { - const checkEdge = { - vertex1: { x: prevLine.x1, y: currentMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } - let currentRoof, prevRoof, nextRoof - if (intersectionRoofs.length > 0) { - currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line - } - - if (currentRoof) { - prevRoof = roof.lines.find((line) => line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1) - nextRoof = roof.lines.find((line) => line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2) - - const prevRoofEdge = { - vertex1: { x: prevRoof.x2, y: prevRoof.y2 }, - vertex2: { x: prevRoof.x1, y: prevRoof.y1 }, - } - const nextRoofEdge = { - vertex1: { x: nextRoof.x1, y: nextRoof.y1 }, - vertex2: { x: nextRoof.x2, y: nextRoof.y2 }, - } - - let polygonPoints = [ - { x: currentRoof.x1, y: currentRoof.y1 }, - { x: currentRoof.x2, y: currentRoof.y2 }, - ] - const prevHipLines = [] - const nextHipLines = [] - let prevLineRidge, nextLineRidge - - baseHipLines.forEach((current) => { - const { line } = current - if ( - (Math.abs(line.x1 - currentRoof.x1) <= 1 && - Math.abs(line.y1 - currentRoof.y1) <= 1 && - isPointOnLine(prevRoof, { x: line.x2, y: line.y2 })) || - (Math.abs(line.x2 - currentRoof.x1) <= 1 && - Math.abs(line.y2 - currentRoof.y1) <= 1 && - isPointOnLine(prevRoof, { - x: line.x1, - y: line.y1, - })) - ) { - prevHipLines.push(current) - } - if ( - (Math.abs(line.x1 - currentRoof.x2) <= 1 && - Math.abs(line.y1 - currentRoof.y2) <= 1 && - isPointOnLine(nextRoof, { x: line.x2, y: line.y2 })) || - (Math.abs(line.x2 - currentRoof.x2) <= 1 && - Math.abs(line.y2 - currentRoof.y2) <= 1 && - isPointOnLine(nextRoof, { - x: line.x1, - y: line.y1, - })) - ) { - nextHipLines.push(current) - } - }) - prevHipLines.forEach((current) => { - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - let findPoint - if (Math.abs(current.x1 - currentRoof.x1) <= 1 && Math.abs(current.y1 - currentRoof.y1) <= 1) { - findPoint = { x: current.x2, y: current.y2 } - } else { - findPoint = { x: current.x1, y: current.y1 } - } - baseHipLines - .filter( - (line) => - ((Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) || - (Math.abs(line.x2 - findPoint.x) <= 1 && Math.abs(line.y2 - findPoint.y) <= 1)) && - line.x1 !== line.x2 && - line.y1 !== line.y2, - ) - .forEach((line) => { - polygonPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 }) - let ridgePoint - if (Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) { - ridgePoint = { x: line.x2, y: line.y2 } - } else { - ridgePoint = { x: line.x1, y: line.y1 } - } - prevLineRidge = baseGableRidgeLines.find( - (ridge) => - (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) || - (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1), - ) - }) - } else { - let ridgePoint - if (Math.abs(current.x1 - currentRoof.x1) <= 1 && Math.abs(current.y1 - currentRoof.y1) <= 1) { - ridgePoint = { x: current.x2, y: current.y2 } - } else { - ridgePoint = { x: current.x1, y: current.y1 } - } - - prevLineRidge = baseGableRidgeLines.find((ridge) => { - return ( - (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) || - (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1) - ) - }) - } - }) - nextHipLines.forEach((current) => { - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - let findPoint - if (Math.abs(current.x1 - currentRoof.x2) <= 1 && Math.abs(current.y1 - currentRoof.y2) <= 1) { - findPoint = { x: current.x2, y: current.y2 } - } else { - findPoint = { x: current.x1, y: current.y1 } - } - - baseHipLines - .filter( - (line) => - ((Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) || - (Math.abs(line.x2 - findPoint.x) <= 1 && Math.abs(line.y2 - findPoint.y) <= 1)) && - line.x1 !== line.x2 && - line.y1 !== line.y2, - ) - .forEach((line) => { - polygonPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 }) - let ridgePoint - if (Math.abs(line.x1 - findPoint.x) <= 1 && Math.abs(line.y1 - findPoint.y) <= 1) { - ridgePoint = { x: line.x2, y: line.y2 } - } else { - ridgePoint = { x: line.x1, y: line.y1 } - } - nextLineRidge = baseGableRidgeLines.find( - (ridge) => - (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) || - (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1), - ) - }) - } else { - let ridgePoint - if (Math.abs(current.x1 - currentRoof.x2) <= 1 && Math.abs(current.y1 - currentRoof.y2) <= 1) { - ridgePoint = { x: current.x2, y: current.y2 } - } else { - ridgePoint = { x: current.x1, y: current.y1 } - } - - nextLineRidge = baseGableRidgeLines.find( - (ridge) => - (Math.abs(ridge.x1 - ridgePoint.x) <= 1 && Math.abs(ridge.y1 - ridgePoint.y) <= 1) || - (Math.abs(ridge.x2 - ridgePoint.x) <= 1 && Math.abs(ridge.y2 - ridgePoint.y) <= 1), - ) - } - }) - - if (!prevLineRidge) { - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - } else { - const isRidgePoints = [] - baseGableRidgeLines.forEach((ridge) => { - const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } - const intersection = edgesIntersection(prevRoofEdge, ridgeEdge) - if ( - intersection && - ((ridge.x1 <= intersection.x && intersection.x <= ridge.x2 && ridge.y1 <= intersection.y && intersection.y <= ridge.y2) || - (ridge.x2 <= intersection.x && intersection.x <= ridge.x1 && ridge.y2 <= intersection.y && intersection.y <= ridge.y1)) - ) { - const size = Big(intersection.x) - .minus(Big(currentRoof.x1)) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(Big(currentRoof.y1)).abs().pow(2)) - .sqrt() - isRidgePoints.push({ intersection, ridge, size }) - } - }) - if (isRidgePoints.length > 0) { - const sortedRidgePoints = isRidgePoints.sort((a, b) => a.size - b.size) - prevLineRidge = sortedRidgePoints[0].ridge - } - } - } - if (!nextLineRidge) { - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - } else { - const isRidgePoints = [] - baseGableRidgeLines.forEach((ridge) => { - const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } - const intersection = edgesIntersection(nextRoofEdge, ridgeEdge) - if ( - intersection && - ((ridge.x1 <= intersection.x && intersection.x <= ridge.x2 && ridge.y1 <= intersection.y && intersection.y <= ridge.y2) || - (ridge.x2 <= intersection.x && intersection.x <= ridge.x1 && ridge.y2 <= intersection.y && intersection.y <= ridge.y1)) - ) { - const size = Big(intersection.x) - .minus(Big(currentRoof.x2)) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(Big(currentRoof.y2)).abs().pow(2)) - .sqrt() - isRidgePoints.push({ intersection, ridge, size }) - } - }) - if (isRidgePoints.length > 0) { - const sortedRidgePoints = isRidgePoints.sort((a, b) => a.size - b.size) - nextLineRidge = sortedRidgePoints[0].ridge - } - } - } - const ridgeLine = prevLineRidge === undefined ? nextLineRidge : prevLineRidge - - if (prevLineRidge !== undefined && nextLineRidge !== undefined) { - /** 4각*/ - if (prevLineRidge === nextLineRidge) { - polygonPoints.push({ x: ridgeLine.x1, y: ridgeLine.y1 }, { x: ridgeLine.x2, y: ridgeLine.y2 }) - /** 포인트가 직각 사각형인지 확인하여 아닌경우 직각인 다각형 포인트로 변경한다.*/ - const checkPoints = getSortedPoint(polygonPoints, baseHipLines) - let hasDiagonal = false - if (checkPoints < 4) { - hasDiagonal = true - } else { - checkPoints.forEach((point, index) => { - const nextPoint = checkPoints[(index + 1) % checkPoints.length] - if (point.x !== nextPoint.x && point.y !== nextPoint.y) { - hasDiagonal = true - } - }) - } - if (hasDiagonal) { - const vectorX = Math.sign(currentRoof.x1 - ridgeLine.x1) - const vectorY = Math.sign(currentRoof.y1 - ridgeLine.y1) - const ridgeMinX = Math.min(ridgeLine.x1, ridgeLine.x2) - const ridgeMaxX = Math.max(ridgeLine.x1, ridgeLine.x2) - const ridgeMinY = Math.min(ridgeLine.y1, ridgeLine.y2) - const ridgeMaxY = Math.max(ridgeLine.y1, ridgeLine.y2) - if ( - (!isPointOnLineNew(prevRoof, { x: ridgeLine.x1, y: ridgeLine.y1 }) && - !isPointOnLineNew(nextRoof, { x: ridgeLine.x1, y: ridgeLine.y1 })) || - (!isPointOnLineNew(prevRoof, { x: ridgeLine.x2, y: ridgeLine.y2 }) && !isPointOnLineNew(nextRoof, { x: ridgeLine.x2, y: ridgeLine.y2 })) - ) { - roof.lines - .filter((line) => line !== currentRoof && line !== prevRoof && line !== nextRoof) - .filter((line) => - ridgeLine.y1 === ridgeLine.y2 - ? vectorY === Math.sign(line.y1 - ridgeLine.y1) && - ridgeMinX <= line.x1 && - line.x1 <= ridgeMaxX && - ridgeMinX <= line.x2 && - line.x2 <= ridgeMaxX - : vectorX === Math.sign(line.x1 - ridgeLine.x1) && - ridgeMinY <= line.y1 && - line.y1 <= ridgeMaxY && - ridgeMinY <= line.y2 && - line.y2 <= ridgeMaxY, - ) - .forEach((line) => { - if (ridgeLine.y1 === ridgeLine.y2) { - if (vectorY === Math.sign(line.y1 - ridgeLine.y1)) { - polygonPoints.push({ x: line.x1, y: line.y1 }) - } - if (vectorY === Math.sign(line.y2 - ridgeLine.y1)) { - polygonPoints.push({ x: line.x2, y: line.y2 }) - } - } else { - if (vectorX === Math.sign(line.x1 - ridgeLine.x1)) { - polygonPoints.push({ x: line.x1, y: line.y1 }) - } - if (vectorX === Math.sign(line.x2 - ridgeLine.x1)) { - polygonPoints.push({ x: line.x2, y: line.y2 }) - } - } - }) - } - if ( - !isPointOnLineNew(prevRoof, { x: ridgeLine.x2, y: ridgeLine.y2 }) && - !isPointOnLineNew(nextRoof, { x: ridgeLine.x2, y: ridgeLine.y2 }) - ) { - } - } - } else { - /** 6각이상*/ - let isOverLap = - currentVectorX === 0 - ? (prevLineRidge.y1 <= nextLineRidge.y1 && prevLineRidge.y2 >= nextLineRidge.y1) || - (prevLineRidge.y1 >= nextLineRidge.y1 && prevLineRidge.y2 <= nextLineRidge.y1) || - (prevLineRidge.y1 <= nextLineRidge.y2 && prevLineRidge.y2 >= nextLineRidge.y2) || - (prevLineRidge.y1 >= nextLineRidge.y2 && prevLineRidge.y2 <= nextLineRidge.y2) - : (prevLineRidge.x1 <= nextLineRidge.x1 && prevLineRidge.x2 >= nextLineRidge.x1) || - (prevLineRidge.x1 >= nextLineRidge.x1 && prevLineRidge.x2 <= nextLineRidge.x1) || - (prevLineRidge.x1 <= nextLineRidge.x2 && prevLineRidge.x2 >= nextLineRidge.x2) || - (prevLineRidge.x1 >= nextLineRidge.x2 && prevLineRidge.x2 <= nextLineRidge.x2) - if (isOverLap) { - const prevDistance = currentVectorX === 0 ? Math.abs(prevLineRidge.x1 - currentRoof.x1) : Math.abs(prevLineRidge.y1 - currentRoof.y1) - const nextDistance = currentVectorX === 0 ? Math.abs(nextLineRidge.x1 - currentRoof.x1) : Math.abs(nextLineRidge.y1 - currentRoof.y1) - - /** 현재 지붕 라인과 먼 라인의 포인트를 온전히 사용한다. */ - if (Math.abs(prevDistance - nextDistance) < 1) { - const minX = Math.min(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2) - const maxX = Math.max(currentRoof.x1, currentRoof.x2, currentLine.x1, currentLine.x2) - const minY = Math.min(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2) - const maxY = Math.max(currentRoof.y1, currentRoof.y2, currentLine.y1, currentLine.y2) - if (currentVectorX === 0) { - polygonPoints.push({ x: prevLineRidge.x1, y: minY }, { x: prevLineRidge.x1, y: maxY }) - } else { - polygonPoints.push({ x: minX, y: prevLineRidge.y1 }, { x: maxX, y: prevLineRidge.y1 }) - } - } else if (prevDistance < nextDistance) { - polygonPoints.push({ x: nextLineRidge.x1, y: nextLineRidge.y1 }, { x: nextLineRidge.x2, y: nextLineRidge.y2 }) - - /** 이전라인과 교차한 마루의 포인트*/ - let prevRidgePoint1 - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - prevRidgePoint1 = polygonPoints.find( - (point) => - (point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1) || (point.x === prevLineRidge.x2 && point.y === prevLineRidge.y2), - ) - } else { - prevRidgePoint1 = - currentVectorX === 0 - ? currentRoof.y1 === prevLineRidge.y1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - : currentRoof.x1 === prevLineRidge.x1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - - polygonPoints.push(prevRidgePoint1) - } - - /** 다음 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ - let checkRidgePoint - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const ridgePoint1 = polygonPoints.filter((point) => point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1) - checkRidgePoint = ridgePoint1.length > 0 ? { x: nextLineRidge.x2, y: nextLineRidge.y2 } : { x: nextLineRidge.x1, y: nextLineRidge.y1 } - } else { - checkRidgePoint = - currentVectorX === 0 - ? currentRoof.y2 !== nextLineRidge.y1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - : currentRoof.x2 !== nextLineRidge.x1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - } - - const prevRidgePoint2 = - currentVectorX === 0 ? { x: prevRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: prevRidgePoint1.y } - polygonPoints.push(prevRidgePoint2) - } else { - polygonPoints.push({ x: prevLineRidge.x1, y: prevLineRidge.y1 }, { x: prevLineRidge.x2, y: prevLineRidge.y2 }) - - /** 다음라인과 교차한 마루의 포인트*/ - let nextRidgePoint1 - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - nextRidgePoint1 = polygonPoints.find( - (point) => - (point.x === nextLineRidge.x1 && point.y === nextLineRidge.y1) || (point.x === nextLineRidge.x2 && point.y === nextLineRidge.y2), - ) - } else { - nextRidgePoint1 = - currentVectorX === 0 - ? currentRoof.y2 === nextLineRidge.y1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - : currentRoof.x2 === nextLineRidge.x1 - ? { x: nextLineRidge.x1, y: nextLineRidge.y1 } - : { x: nextLineRidge.x2, y: nextLineRidge.y2 } - polygonPoints.push(nextRidgePoint1) - } - - /** 이전 라인과 교차한 마루의 포인트 중 라인과 접하지 않은 포인트*/ - let checkRidgePoint - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const ridgePoint1 = polygonPoints.filter((point) => point.x === prevLineRidge.x1 && point.y === prevLineRidge.y1) - checkRidgePoint = ridgePoint1.length > 0 ? { x: prevLineRidge.x2, y: prevLineRidge.y2 } : { x: prevLineRidge.x1, y: prevLineRidge.y1 } - } else { - checkRidgePoint = - currentVectorX === 0 - ? currentRoof.y1 !== prevLineRidge.y1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - : currentRoof.x1 !== prevLineRidge.x1 - ? { x: prevLineRidge.x1, y: prevLineRidge.y1 } - : { x: prevLineRidge.x2, y: prevLineRidge.y2 } - } - - const nextRidgePoint2 = - currentVectorX === 0 ? { x: nextRidgePoint1.x, y: checkRidgePoint.y } : { x: checkRidgePoint.x, y: nextRidgePoint1.y } - polygonPoints.push(nextRidgePoint2) - } - } else { - /** 마루가 겹치지 않을때 */ - const otherRidgeLines = [] - - baseGableRidgeLines - .filter((ridge) => ridge !== prevLineRidge && ridge !== nextLineRidge) - .filter((ridge) => (currentVectorX === 0 ? ridge.x1 === ridge.x2 : ridge.y1 === ridge.y2)) - .filter((ridge) => - currentVectorX === 0 ? nextVectorX === Math.sign(nextLine.x1 - ridge.x1) : nextVectorY === Math.sign(nextLine.y1 - ridge.y1), - ) - .forEach((ridge) => { - const size = currentVectorX === 0 ? Math.abs(nextLine.x1 - ridge.x1) : Math.abs(nextLine.y1 - ridge.y1) - otherRidgeLines.push({ ridge, size }) - }) - if (otherRidgeLines.length > 0) { - const otherRidge = otherRidgeLines.sort((a, b) => a.size - b.size)[0].ridge - /** - * otherRidge이 prevRidgeLine, nextRidgeLine 과 currentLine의 사이에 있는지 확인해서 분할하여 작업 - * 지붕의 덮힘이 다르기 때문 - */ - const isInside = - currentVectorX === 0 - ? Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - prevLineRidge.x1) && - Math.abs(currentLine.x1 - otherRidge.x1) < Math.abs(currentLine.x1 - nextLineRidge.x1) - : Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - prevLineRidge.y1) && - Math.abs(currentLine.y1 - otherRidge.y1) < Math.abs(currentLine.y1 - nextLineRidge.y1) - - if (isInside) { - polygonPoints.push( - { x: prevLineRidge.x1, y: prevLineRidge.y1 }, - { x: prevLineRidge.x2, y: prevLineRidge.y2 }, - { x: nextLineRidge.x1, y: nextLineRidge.y1 }, - { x: nextLineRidge.x2, y: nextLineRidge.y2 }, - ) - - let ridgeAllPoints = [ - { x: prevLineRidge.x1, y: prevLineRidge.y1 }, - { x: prevLineRidge.x2, y: prevLineRidge.y2 }, - { x: nextLineRidge.x1, y: nextLineRidge.y1 }, - { x: nextLineRidge.x2, y: nextLineRidge.y2 }, - ] - let ridgePoints = [] - ridgeAllPoints.forEach((point) => { - let isOnLine = false - roof.lines.forEach((line) => { - if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { - isOnLine = true - } - }) - if (!isOnLine) { - ridgePoints.push(point) - } - }) - if (ridgePoints.length === 2) { - if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { - polygonPoints.push( - { x: otherRidge.x1, y: ridgePoints[0].y }, - { - x: otherRidge.x1, - y: ridgePoints[1].y, - }, - ) - } else { - polygonPoints.push( - { x: ridgePoints[0].x, y: otherRidge.y1 }, - { - x: ridgePoints[1].x, - y: otherRidge.y1, - }, - ) - } - } - } else { - polygonPoints.push({ x: otherRidge.x1, y: otherRidge.y1 }, { x: otherRidge.x2, y: otherRidge.y2 }) - - let ridgePoints = [ - { x: prevLineRidge.x1, y: prevLineRidge.y1 }, - { x: prevLineRidge.x2, y: prevLineRidge.y2 }, - { x: nextLineRidge.x1, y: nextLineRidge.y1 }, - { x: nextLineRidge.x2, y: nextLineRidge.y2 }, - ] - - ridgePoints.forEach((point) => { - let isOnLine = false - roof.lines.forEach((line) => { - if (isPointOnLine({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }, point)) { - isOnLine = true - } - }) - if (isOnLine) { - polygonPoints.push(point) - } - }) - - if (Math.sign(otherRidge.x1 - otherRidge.x2) === 0) { - const prevY = - (prevLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= prevLineRidge.y2) || - (prevLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= prevLineRidge.y2) - ? otherRidge.y1 - : otherRidge.y2 - const nextY = - (nextLineRidge.y1 <= otherRidge.y1 && otherRidge.y1 <= nextLineRidge.y2) || - (nextLineRidge.y1 >= otherRidge.y1 && otherRidge.y1 >= nextLineRidge.y2) - ? otherRidge.y1 - : otherRidge.y2 - polygonPoints.push({ x: prevLineRidge.x1, y: prevY }, { x: nextLineRidge.x1, y: nextY }) - } else { - const prevX = - (prevLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= prevLineRidge.x2) || - (prevLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= prevLineRidge.x2) - ? otherRidge.x1 - : otherRidge.x2 - const nextX = - (nextLineRidge.x1 <= otherRidge.x1 && otherRidge.x1 <= nextLineRidge.x2) || - (nextLineRidge.x1 >= otherRidge.x1 && otherRidge.x1 >= nextLineRidge.x2) - ? otherRidge.x1 - : otherRidge.x2 - polygonPoints.push({ x: prevX, y: prevLineRidge.y1 }, { x: nextX, y: nextLineRidge.y1 }) - } - } - } - } - } - } else { - if (ridgeLine) { - const ridgeEdge = { vertex1: { x: ridgeLine.x1, y: ridgeLine.y1 }, vertex2: { x: ridgeLine.x2, y: ridgeLine.y2 } } - const prevRoofEdge = { vertex1: { x: prevRoof.x1, y: prevRoof.y1 }, vertex2: { x: prevRoof.x2, y: prevRoof.y2 } } - const nextRoofEdge = { vertex1: { x: nextRoof.x1, y: nextRoof.y1 }, vertex2: { x: nextRoof.x2, y: nextRoof.y2 } } - const isPrevRoof = edgesIntersection(prevRoofEdge, ridgeEdge) - const isNextRoof = edgesIntersection(nextRoofEdge, ridgeEdge) - if (isPrevRoof && isPointOnLine(ridgeLine, isPrevRoof)) { - polygonPoints.push({ x: isPrevRoof.x, y: isPrevRoof.y }) - } else { - polygonPoints.push({ x: prevRoof.x1, y: prevRoof.y1 }) - } - if (isNextRoof && isPointOnLine(ridgeLine, isNextRoof)) { - polygonPoints.push({ x: isNextRoof.x, y: isNextRoof.y }) - } else { - polygonPoints.push({ x: nextRoof.x2, y: nextRoof.y2 }) - } - - roof.lines - .filter((line) => line !== currentRoof && line !== prevRoof && line !== nextRoof) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(ridgeEdge, lineEdge) - if (intersection && isPointOnLine(ridgeLine, intersection)) { - const size1 = Math.sqrt(Math.pow(line.x1 - intersection.x, 2) + Math.pow(line.y1 - intersection.y, 2)) - const size2 = Math.sqrt(Math.pow(line.x2 - intersection.x, 2) + Math.pow(line.y2 - intersection.y, 2)) - if (size1 < size2) { - polygonPoints.push({ x: line.x2, y: line.y2 }) - } else { - polygonPoints.push({ x: line.x1, y: line.y1 }) - } - polygonPoints.push({ x: intersection.x, y: intersection.y }) - } - }) - } - } - /** 중복되는 포인트 제거 */ - const uniquePoints = [] - polygonPoints.forEach((point) => { - const isAlready = uniquePoints.find((uniquePoint) => uniquePoint.x === point.x && uniquePoint.y === point.y) - if (!isAlready) { - uniquePoints.push(point) - } - }) - polygonPoints = getSortedPoint(uniquePoints, baseHipLines) - - /*polygonPoints.forEach((point) => { - const checkCircle = new fabric.Circle({ - left: point.x, - top: point.y, - radius: 4, - fill: 'red', - parentId: roofId, - name: 'checkCircle', - }) - canvas.add(checkCircle) - canvas.renderAll() - - /!** 확인용 라인 제거 *!/ - canvas - .getObjects() - .filter((obj) => obj.name === 'checkCircle' || obj.name === 'checkLine') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() - })*/ - - polygonPoints.forEach((currentPoint, index) => { - const nextPoint = polygonPoints[(index + 1) % polygonPoints.length] - const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y] - const isParallel = ridgeLine.x1 === ridgeLine.x2 ? currentPoint.x === nextPoint.x : currentPoint.y === nextPoint.y - const ridgeLines = baseGableRidgeLines.filter( - (line) => - (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) || - (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]), - ) - const hipLine = baseHipLines.filter( - (line) => - (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) || - (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]), - ) - /** 이미 존재하는 라인이면 넘긴다.*/ - if (ridgeLines.length > 0 || hipLine.length > 0) { - return - } - - let line - if (isParallel) { - line = drawRoofLine(points, canvas, roof, textMode) - baseGableLines.push(line) - } else { - line = drawHipLine(points, canvas, roof, textMode, currentDegree, currentDegree) - baseHipLines.push({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2, line }) - } - }) - } - }) - - drawGablePolygonSecond.forEach((current) => { - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - let { x1, x2, y1, y2 } = currentBaseLine - - /*const checkLine = new fabric.Line([x1, y1, x2, y2], { - stroke: 'red', - strokeWidth: 4, - parentId: roofId, - name: 'checkLine', - }) - canvas.add(checkLine) - canvas.renderAll()*/ - - const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1) - const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1) - const currentDegree = getDegreeByChon(currentLine.attributes.pitch) - - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2) - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2) - const intersectionRoofs = [] - if (currentVectorX === 0) { - const checkEdge = { - vertex1: { x: prevLine.x1, y: currentMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Math.sqrt(Math.pow(intersection.x - currentMidX.toNumber(), 2) + Math.pow(intersection.y - currentMidY.toNumber(), 2)), - }) - } - }) - } else { - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Math.sqrt(Math.pow(intersection.x - currentMidX.toNumber(), 2) + Math.pow(intersection.y - currentMidY.toNumber(), 2)), - }) - } - }) - } - let currentRoof, prevRoof, nextRoof - if (intersectionRoofs.length > 0) { - currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line - prevRoof = roof.lines.find((line) => line.x2 === currentRoof.x1 && line.y2 === currentRoof.y1) - nextRoof = roof.lines.find((line) => line.x1 === currentRoof.x2 && line.y1 === currentRoof.y2) - } - - let polygonPoints = [] - if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) { - const xVector = Big(nextLine.x2).minus(Big(nextLine.x1)) - const yVector = Big(nextLine.y2).minus(Big(nextLine.y1)) - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2) - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2) - - const checkPoints = { - x: currentMidX.plus(Big(10).times(Math.sign(xVector.toNumber()))).toNumber(), - y: currentMidY.plus(Big(10).times(Math.sign(yVector.toNumber()))).toNumber(), - } - - if (checkWallPolygon.inPolygon(checkPoints)) { - const currentRidge = baseGableRidgeLines.find((line) => - currentVectorX === 0 - ? (line.y1 === y1 && line.y2 === y2) || (line.y1 === y2 && line.y2 === y1) - : (line.x1 === x1 && line.x2 === x2) || (line.x1 === x2 && line.x2 === x1), - ) - if (currentRidge) { - const ridgeVectorX = Math.sign(currentRidge.x1 - currentRidge.x2) - const ridgeVectorY = Math.sign(currentRidge.y1 - currentRidge.y2) - - let checkEdge - if (currentVectorX === 0) { - checkEdge = { - vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, - vertex2: { x: currentLine.x1, y: currentRidge.y1 }, - } - } else { - checkEdge = { - vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, - vertex2: { x: currentRidge.x1, y: currentLine.y1 }, - } - } - const isRoofLines = [] - roof.lines - .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(checkEdge, lineEdge) - if (is) { - const checkVectorX = Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) - const checkVectorY = Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) - const isVectorX = Math.sign(checkEdge.vertex1.x - is.x) - const isVectorY = Math.sign(checkEdge.vertex1.y - is.y) - if ((ridgeVectorX === 0 && checkVectorX === isVectorX) || (ridgeVectorY === 0 && checkVectorY === isVectorY)) { - const size = ridgeVectorX === 0 ? Math.abs(checkEdge.vertex1.x - is.x) : Math.abs(checkEdge.vertex1.y - is.y) - isRoofLines.push({ line, size }) - } - } - }) - isRoofLines.sort((a, b) => a.size - b.size) - const roofLine = isRoofLines[0].line - polygonPoints.push({ x: currentRidge.x1, y: currentRidge.y1 }, { x: currentRidge.x2, y: currentRidge.y2 }) - if (ridgeVectorX === 0) { - polygonPoints.push({ x: roofLine.x1, y: currentRidge.y1 }, { x: roofLine.x1, y: currentRidge.y2 }) - } else { - polygonPoints.push({ x: currentRidge.x1, y: roofLine.y1 }, { x: currentRidge.x2, y: roofLine.y1 }) - } - } - } else { - const currentRidge = baseGableRidgeLines.find((line) => - currentVectorX === 0 - ? (Math.abs(line.y1 - currentRoof.y1) < 1 && Math.abs(line.y2 - currentRoof.y2) < 1) || - (Math.abs(line.y1 - currentRoof.y2) < 1 && Math.abs(line.y2 - currentRoof.y1) < 1) - : (Math.abs(line.x1 - currentRoof.x1) < 1 && Math.abs(line.x2 - currentRoof.x2) < 1) || - (Math.abs(line.x1 - currentRoof.x2) < 1 && Math.abs(line.x2 - currentRoof.x1) < 1), - ) - if (currentRidge) { - if (currentVectorX === 0) { - polygonPoints.push({ x: currentRoof.x1, y: currentLine.y1 }, { x: currentRoof.x2, y: currentLine.y2 }) - polygonPoints.push({ x: currentRidge.x1, y: currentLine.y1 }, { x: currentRidge.x1, y: currentLine.y2 }) - } else { - polygonPoints.push({ x: currentLine.x1, y: currentRoof.y1 }, { x: currentLine.x2, y: currentRoof.y2 }) - polygonPoints.push({ x: currentLine.x1, y: currentRidge.y1 }, { x: currentLine.x2, y: currentRidge.y1 }) - } - } - } - } else { - const prevEdge = { vertex1: { x: prevRoof.x2, y: prevRoof.y2 }, vertex2: { x: prevRoof.x1, y: prevRoof.y1 } } - const prevVectorX = Math.sign(prevRoof.x1 - prevRoof.x2) - const prevVectorY = Math.sign(prevRoof.y1 - prevRoof.y2) - - let prevRidge, nextRidge - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const hipLines = [] - baseHipLines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(prevEdge, lineEdge) - if (is) { - const size = Big(is.x).minus(prevRoof.x2).abs().pow(2).plus(Big(is.y).minus(prevRoof.y2).abs().pow(2)).sqrt().toNumber() - hipLines.push({ line, is, size }) - } - }) - if (hipLines.length > 0) { - hipLines.sort((a, b) => a.size - b.size) - const hipLine = hipLines[0] - polygonPoints.push({ x: hipLine.is.x, y: hipLine.is.y }) - const ridgePoint = - hipLine.is.x === hipLine.line.x1 && hipLine.is.y === hipLine.line.y1 - ? { x: hipLine.line.x2, y: hipLine.line.y2 } - : { x: hipLine.line.x1, y: hipLine.line.y1 } - prevRidge = baseGableRidgeLines.find( - (line) => (line.x1 === ridgePoint.x && line.y1 === ridgePoint.y) || (line.x2 === ridgePoint.x && line.y2 === ridgePoint.y), - ) - } - } else { - const prevRidges = [] - baseGableRidgeLines.forEach((ridge) => { - const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } - const is = edgesIntersection(prevEdge, ridgeEdge) - if (is) { - const isVectorX = Math.sign(prevRoof.x1 - is.x) - const isVectorY = Math.sign(prevRoof.y1 - is.y) - if ( - isVectorX === prevVectorX && - isVectorY === prevVectorY && - ((Math.abs(ridge.x1 - is.x) < 1 && Math.abs(ridge.y1 - is.y) < 1) || (Math.abs(ridge.x2 - is.x) < 1 && Math.abs(ridge.y2 - is.y) < 1)) - ) { - const size = Big(prevRoof.x1).minus(is.x).abs().pow(2).plus(Big(prevRoof.y1).minus(is.y).abs().pow(2)).sqrt().toNumber() - prevRidges.push({ ridge, size }) - } - } - }) - if (prevRidges.length > 0) { - prevRidges.sort((a, b) => a.size - b.size) - prevRidge = prevRidges[0].ridge - } - } - - const nextEdge = { vertex1: { x: nextRoof.x1, y: nextRoof.y1 }, vertex2: { x: nextRoof.x2, y: nextRoof.y2 } } - const nextVectorX = Math.sign(nextLine.x1 - nextLine.x2) - const nextVectorY = Math.sign(nextLine.y1 - nextLine.y2) - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - const hipLines = [] - baseHipLines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(nextEdge, lineEdge) - if (is) { - const size = Big(is.x).minus(nextRoof.x1).abs().pow(2).plus(Big(is.y).minus(nextRoof.y1).abs().pow(2)).sqrt().toNumber() - hipLines.push({ line, is, size }) - } - }) - if (hipLines.length > 0) { - hipLines.sort((a, b) => a.size - b.size) - const hipLine = hipLines[0] - polygonPoints.push({ x: hipLine.is.x, y: hipLine.is.y }) - const ridgePoint = - hipLine.is.x === hipLine.line.x1 && hipLine.is.y === hipLine.line.y1 - ? { x: hipLine.line.x2, y: hipLine.line.y2 } - : { x: hipLine.line.x1, y: hipLine.line.y1 } - nextRidge = baseGableRidgeLines.find( - (line) => (line.x1 === ridgePoint.x && line.y1 === ridgePoint.y) || (line.x2 === ridgePoint.x && line.y2 === ridgePoint.y), - ) - } - } else { - const nextRidges = [] - baseGableRidgeLines.forEach((ridge) => { - const ridgeEdge = { vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } } - const is = edgesIntersection(nextEdge, ridgeEdge) - if (is) { - const isVectorX = Math.sign(nextRoof.x1 - is.x) - const isVectorY = Math.sign(nextRoof.y1 - is.y) - if ( - isVectorX === nextVectorX && - isVectorY === nextVectorY && - ((Math.abs(ridge.x1 - is.x) < 1 && Math.abs(ridge.y1 - is.y) < 1) || (Math.abs(ridge.x2 - is.x) < 1 && Math.abs(ridge.y2 - is.y) < 1)) - ) { - const size = Big(nextLine.x1).minus(is.x).abs().pow(2).plus(Big(nextLine.y1).minus(is.y).abs().pow(2)).sqrt().toNumber() - nextRidges.push({ ridge, size }) - } - } - }) - if (nextRidges.length > 0) { - nextRidges.sort((a, b) => a.size - b.size) - nextRidge = nextRidges[0].ridge - } - } - - let currentRidge - - if (prevRidge) { - if (currentVectorX === 0) { - const minY = Math.min(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2) - const maxY = Math.max(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2) - if (minY <= prevRidge.y1 && maxY >= prevRidge.y1 && minY <= prevRidge.y2 && maxY >= prevRidge.y2) { - currentRidge = prevRidge - } - } - if (currentVectorY === 0) { - const minX = Math.min(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2) - const maxX = Math.max(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2) - - if (minX <= prevRidge.x1 && maxX >= prevRidge.x1 && minX <= prevRidge.x2 && maxX >= prevRidge.x2) { - currentRidge = prevRidge - } - } - } - if (nextRidge) { - if (currentVectorX === 0) { - const minY = Math.min(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2) - const maxY = Math.max(currentLine.y1, currentLine.y2, currentRoof.y1, currentRoof.y2) - if (minY <= nextRidge.y1 && maxY >= nextRidge.y1 && minY <= nextRidge.y2 && maxY >= nextRidge.y2) { - currentRidge = nextRidge - } - } - if (currentVectorY === 0) { - const minX = Math.min(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2) - const maxX = Math.max(currentLine.x1, currentLine.x2, currentRoof.x1, currentRoof.x2) - - if (minX <= nextRidge.x1 && maxX >= nextRidge.x1 && minX <= nextRidge.x2 && maxX >= nextRidge.x2) { - currentRidge = nextRidge - } - } - } - - if (currentRidge) { - polygonPoints.push({ x: currentRidge.x1, y: currentRidge.y1 }, { x: currentRidge.x2, y: currentRidge.y2 }) - - /** 기준점이 될 포인트를 찾는다. 기준점 = 지붕선이나 hip 등에 붙지 않은 포인트 */ - const checkRidgePoints = [ - { x: currentRidge.x1, y: currentRidge.y1, checkPoint: true }, - { x: currentRidge.x2, y: currentRidge.y2, checkPoint: true }, - ] - const ridgeEdge = { vertex1: { x: currentRidge.x1, y: currentRidge.y1 }, vertex2: { x: currentRidge.x2, y: currentRidge.y2 } } - /** 포인트가 지붕선과 붙은 경우 */ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const is = edgesIntersection(ridgeEdge, lineEdge) - if (is) { - if (Math.abs(is.x - currentRidge.x1) < 1 && Math.abs(is.y - currentRidge.y1) < 1) { - checkRidgePoints[0].checkPoint = false - } - if (Math.abs(is.x - currentRidge.x2) < 1 && Math.abs(is.y - currentRidge.y2) < 1) { - checkRidgePoints[1].checkPoint = false - } - } - }) - /** 포인트가 hip과 붙은 경우 */ - baseHipLines - .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) - .forEach((line) => { - if ( - (Math.abs(line.x1 - currentRidge.x1) < 1 && Math.abs(line.y1 - currentRidge.y1) < 1) || - (Math.abs(line.x2 - currentRidge.x1) < 1 && Math.abs(line.y2 - currentRidge.y1) < 1) - ) { - checkRidgePoints[0].checkPoint = false - } - if ( - (Math.abs(line.x1 - currentRidge.x2) < 1 && Math.abs(line.y1 - currentRidge.y2) < 1) || - (Math.abs(line.x2 - currentRidge.x2) < 1 && Math.abs(line.y2 - currentRidge.y2) < 1) - ) { - checkRidgePoints[1].checkPoint = false - } - }) - - const checkRidgePoint = checkRidgePoints.find((point) => point.checkPoint) - - if (!checkRidgePoint) return - /** 마루에서 현재라인으로 향하는 외벽선까지의 포인트를 확인 하여 처리*/ - let checkEdge - if (currentVectorX === 0) { - checkEdge = { - vertex1: { x: checkRidgePoint.x, y: checkRidgePoint.y }, - vertex2: { x: currentRoof.x1, y: checkRidgePoint.y }, - } - } else { - checkEdge = { - vertex1: { x: checkRidgePoint.x, y: checkRidgePoint.y }, - vertex2: { x: checkRidgePoint.x, y: currentRoof.y1 }, - } - } - const currentRoofEdge = { vertex1: { x: currentRoof.x1, y: currentRoof.y1 }, vertex2: { x: currentRoof.x2, y: currentRoof.y2 } } - - const isRoofPoint = edgesIntersection(checkEdge, currentRoofEdge) - if (isRoofPoint) { - if (currentVectorX === 0) { - const minY = Math.min(currentRoof.y1, currentRoof.y2, isRoofPoint.y) - const maxY = Math.max(currentRoof.y1, currentRoof.y2, isRoofPoint.y) - polygonPoints.push({ x: isRoofPoint.x, y: minY }, { x: isRoofPoint.x, y: maxY }) - } else { - const minX = Math.min(currentRoof.x1, currentRoof.x2, isRoofPoint.x) - const maxX = Math.max(currentRoof.x1, currentRoof.x2, isRoofPoint.x) - polygonPoints.push({ x: minX, y: isRoofPoint.y }, { x: maxX, y: isRoofPoint.y }) - } - } - } - } - - const uniquePoints = [] - polygonPoints.forEach((point) => { - const isAlready = uniquePoints.find((uniquePoint) => uniquePoint.x === point.x && uniquePoint.y === point.y) - if (!isAlready) { - uniquePoints.push(point) - } - }) - - polygonPoints = getSortedPoint(uniquePoints, baseHipLines) - polygonPoints.forEach((currentPoint, index) => { - const nextPoint = polygonPoints[(index + 1) % polygonPoints.length] - const points = [currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y] - - const ridgeLines = baseGableRidgeLines.filter( - (line) => - (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) || - (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]), - ) - const hipLines = baseHipLines.filter( - (line) => - (line.x1 === points[0] && line.y1 === points[1] && line.x2 === points[2] && line.y2 === points[3]) || - (line.x1 === points[2] && line.y1 === points[3] && line.x2 === points[0] && line.y2 === points[1]), - ) - /** 이미 존재하는 라인이면 넘긴다.*/ - if (ridgeLines.length > 0 || hipLines.length > 0) { - return - } - - const hipLine = drawHipLine(points, canvas, roof, textMode, currentDegree, currentDegree) - if (currentVectorX === 0) { - if (Math.sign(currentPoint.x - nextPoint.x) === 0) { - hipLine.attributes.actualSize = hipLine.attributes.planeSize - } - } else { - if (Math.sign(currentPoint.y - nextPoint.y) === 0) { - hipLine.attributes.actualSize = hipLine.attributes.planeSize - } - } - baseHipLines.push({ x1: hipLine.x1, y1: hipLine.y1, x2: hipLine.x2, y2: hipLine.y2, line: hipLine }) - }) - }) - - /** 케라바 지붕에 연결된 마루 중 처마라인이 그려지지 않은 경우 확*/ - baseGableRidgeLines.forEach((ridge) => { - const ridgeVectorX = Math.sign(ridge.x1 - ridge.x2) - const ridgeVectorY = Math.sign(ridge.y1 - ridge.y2) - - const firstGableLines = [] - const secondGableLines = [] - - baseGableLines - .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) - .filter((line) => (line.x1 === ridge.x1 && line.y1 === ridge.y1) || (line.x2 === ridge.x1 && line.y2 === ridge.y1)) - .forEach((line) => firstGableLines.push(line)) - baseGableLines - .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) - .filter((line) => (line.x1 === ridge.x2 && line.y1 === ridge.y2) || (line.x2 === ridge.x2 && line.y2 === ridge.y2)) - .forEach((line) => secondGableLines.push(line)) - .filter((line) => (line.x1 === ridge.x1 && line.y1 === ridge.y1) || (line.x2 === ridge.x1 && line.y2 === ridge.y1)) - .forEach((line) => firstGableLines.push(line)) - baseHipLines - .filter((line) => (ridgeVectorX === 0 ? line.x1 !== line.x2 : line.y1 !== line.y2)) - .filter((line) => (line.x1 === ridge.x2 && line.y1 === ridge.y2) || (line.x2 === ridge.x2 && line.y2 === ridge.y2)) - .forEach((line) => secondGableLines.push(line)) - - let degree1, degree2 - if (firstGableLines.length < 2 || secondGableLines.length < 2) { - drawBaseLines.forEach((currentBaseLine, index) => { - let prevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] - let nextBaseLine = drawBaseLines[(index + 1) % drawBaseLines.length] - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - - if ( - gableType.includes(currentLine.attributes?.type) && - eavesType.includes(prevLine.attributes?.type) && - eavesType.includes(nextLine.attributes?.type) && - Big(prevAngle).minus(Big(nextAngle)).abs().eq(180) - ) { - if ( - ridgeVectorX === 0 && - currentLine.x1 !== currentLine.x2 && - ((currentLine.x1 <= ridge.x1 && ridge.x1 <= currentLine.x2) || (currentLine.x2 <= ridge.x1 && ridge.x1 <= currentLine.x1)) - ) { - degree1 = getDegreeByChon(prevLine.attributes.pitch) - degree2 = getDegreeByChon(nextLine.attributes.pitch) - } - - if ( - ridgeVectorY === 0 && - currentLine.y1 !== currentLine.y2 && - ((currentLine.y1 <= ridge.y1 && ridge.y1 <= currentLine.y2) || (currentLine.y2 <= ridge.y1 && ridge.y1 <= currentLine.y1)) - ) { - degree1 = getDegreeByChon(prevLine.attributes.pitch) - degree2 = getDegreeByChon(nextLine.attributes.pitch) - } - } - }) - } - - if (firstGableLines.length < 2) { - const connectRoof = roof.lines.find( - (line) => - (line.x1 <= ridge.x1 && line.x2 >= ridge.x1 && line.y1 <= ridge.y1 && line.y2 >= ridge.y1) || - (line.x2 <= ridge.x1 && line.x1 >= ridge.x1 && line.y2 <= ridge.y1 && line.y1 >= ridge.y1), - ) - if (connectRoof) { - let hipPoint1 = [connectRoof.x1, connectRoof.y1, ridge.x1, ridge.y1] - let hipPoint2 = [connectRoof.x2, connectRoof.y2, ridge.x1, ridge.y1] - let intersectPoints1 - let intersectPoints2 - baseHipLines - .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) - .forEach((hip) => { - const line = hip.line - if ( - (hipPoint1[0] <= line.x1 && line.x1 <= hipPoint1[2] && hipPoint1[1] <= line.y1 && line.y1 <= hipPoint1[3]) || - (hipPoint1[2] <= line.x1 && line.x1 <= hipPoint1[0] && hipPoint1[3] <= line.y1 && line.y1 <= hipPoint1[1]) - ) { - intersectPoints1 = { x: line.x1, y: line.y1 } - } - if ( - (hipPoint1[0] <= line.x2 && line.x2 <= hipPoint1[2] && hipPoint1[1] <= line.y2 && line.y2 <= hipPoint1[3]) || - (hipPoint1[2] <= line.x2 && line.x2 <= hipPoint1[0] && hipPoint1[3] <= line.y2 && line.y2 <= hipPoint1[1]) - ) { - intersectPoints1 = { x: line.x2, y: line.y2 } - } - if ( - (hipPoint2[0] <= line.x1 && line.x1 <= hipPoint2[2] && hipPoint2[1] <= line.y1 && line.y1 <= hipPoint2[3]) || - (hipPoint2[2] <= line.x1 && line.x1 <= hipPoint2[0] && hipPoint2[3] <= line.y1 && line.y1 <= hipPoint2[1]) - ) { - intersectPoints2 = { x: line.x1, y: line.y1 } - } - if ( - (hipPoint2[0] <= line.x2 && line.x2 <= hipPoint2[2] && hipPoint2[1] <= line.y2 && line.y2 <= hipPoint2[3]) || - (hipPoint2[2] <= line.x2 && line.x2 <= hipPoint2[0] && hipPoint2[3] <= line.y2 && line.y2 <= hipPoint2[1]) - ) { - intersectPoints2 = { x: line.x2, y: line.y2 } - } - }) - if (intersectPoints1) { - hipPoint1 = [intersectPoints1.x, intersectPoints1.y, ridge.x1, ridge.y1] - } - if (intersectPoints2) { - hipPoint2 = [intersectPoints2.x, intersectPoints2.y, ridge.x1, ridge.y1] - } - - if (hipPoint1) { - const hipLines = baseHipLines.filter( - (line) => - (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) || - (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]), - ) - - const gableLines = baseGableLines.filter( - (line) => - (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) || - (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]), - ) - - if (gableLines.length === 0 && hipLines.length === 0) { - const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, degree1, degree1) - baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 }) - } - } - if (hipPoint2) { - const hipLines = baseHipLines.filter( - (line) => - (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) || - (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]), - ) - const gableLines = baseGableLines.filter( - (line) => - (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) || - (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]), - ) - if (hipLines.length === 0 && gableLines.length === 0) { - const hipLine2 = drawHipLine(hipPoint2, canvas, roof, textMode, degree2, degree2) - baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 }) - } - } - } - } - if (secondGableLines.length < 2) { - const connectRoof = roof.lines.find( - (line) => - (line.x1 <= ridge.x2 && line.x2 >= ridge.x2 && line.y1 <= ridge.y2 && line.y2 >= ridge.y2) || - (line.x2 <= ridge.x2 && line.x1 >= ridge.x2 && line.y2 <= ridge.y2 && line.y1 >= ridge.y2), - ) - if (connectRoof) { - let hipPoint1 = [connectRoof.x1, connectRoof.y1, ridge.x2, ridge.y2] - let hipPoint2 = [connectRoof.x2, connectRoof.y2, ridge.x2, ridge.y2] - let intersectPoints1 - let intersectPoints2 - - baseHipLines - .filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2) - .forEach((hip) => { - const line = hip.line - if ( - (hipPoint1[0] <= line.x1 && line.x1 <= hipPoint1[2] && hipPoint1[1] <= line.y1 && line.y1 <= hipPoint1[3]) || - (hipPoint1[2] <= line.x1 && line.x1 <= hipPoint1[0] && hipPoint1[3] <= line.y1 && line.y1 <= hipPoint1[1]) - ) { - intersectPoints1 = { x: line.x1, y: line.y1 } - } - if ( - (hipPoint1[0] <= line.x2 && line.x2 <= hipPoint1[2] && hipPoint1[1] <= line.y2 && line.y2 <= hipPoint1[3]) || - (hipPoint1[2] <= line.x2 && line.x2 <= hipPoint1[0] && hipPoint1[3] <= line.y2 && line.y2 <= hipPoint1[1]) - ) { - intersectPoints1 = { x: line.x2, y: line.y2 } - } - if ( - (hipPoint2[0] <= line.x1 && line.x1 <= hipPoint2[2] && hipPoint2[1] <= line.y1 && line.y1 <= hipPoint2[3]) || - (hipPoint2[2] <= line.x1 && line.x1 <= hipPoint2[0] && hipPoint2[3] <= line.y1 && line.y1 <= hipPoint2[1]) - ) { - intersectPoints2 = { x: line.x1, y: line.y1 } - } - if ( - (hipPoint2[0] <= line.x2 && line.x2 <= hipPoint2[2] && hipPoint2[1] <= line.y2 && line.y2 <= hipPoint2[3]) || - (hipPoint2[2] <= line.x2 && line.x2 <= hipPoint2[0] && hipPoint2[3] <= line.y2 && line.y2 <= hipPoint2[1]) - ) { - intersectPoints2 = { x: line.x2, y: line.y2 } - } - }) - - if (intersectPoints1) { - hipPoint1 = [intersectPoints1.x, intersectPoints1.y, ridge.x2, ridge.y2] - } - if (intersectPoints2) { - hipPoint2 = [intersectPoints2.x, intersectPoints2.y, ridge.x2, ridge.y2] - } - - if (hipPoint1) { - const hipLines = baseHipLines.filter( - (line) => - (line.line.x1 === hipPoint1[0] && line.line.y1 === hipPoint1[1] && line.line.x2 === hipPoint1[2] && line.line.y2 === hipPoint1[3]) || - (line.line.x2 === hipPoint1[0] && line.line.y2 === hipPoint1[1] && line.line.x1 === hipPoint1[2] && line.line.y1 === hipPoint1[3]), - ) - const gableLines = baseGableLines.filter( - (line) => - (line.x1 === hipPoint1[0] && line.y1 === hipPoint1[1] && line.x2 === hipPoint1[2] && line.y2 === hipPoint1[3]) || - (line.x2 === hipPoint1[0] && line.y2 === hipPoint1[1] && line.x1 === hipPoint1[2] && line.y1 === hipPoint1[3]), - ) - - if (hipLines.length === 0 && gableLines.length === 0) { - const hipLine1 = drawHipLine(hipPoint1, canvas, roof, textMode, degree1, degree1) - baseHipLines.push({ x1: hipLine1.x1, y1: hipLine1.y1, x2: hipLine1.x2, y2: hipLine1.y2, line: hipLine1 }) - } - } - if (hipPoint2) { - const hipLines = baseHipLines.filter( - (line) => - (line.line.x1 === hipPoint2[0] && line.line.y1 === hipPoint2[1] && line.line.x2 === hipPoint2[2] && line.line.y2 === hipPoint2[3]) || - (line.line.x2 === hipPoint2[0] && line.line.y2 === hipPoint2[1] && line.line.x1 === hipPoint2[2] && line.line.y1 === hipPoint2[3]), - ) - const gableLines = baseGableLines.filter( - (line) => - (line.x1 === hipPoint2[0] && line.y1 === hipPoint2[1] && line.x2 === hipPoint2[2] && line.y2 === hipPoint2[3]) || - (line.x2 === hipPoint2[0] && line.y2 === hipPoint2[1] && line.x1 === hipPoint2[2] && line.y1 === hipPoint2[3]), - ) - if (hipLines.length === 0 && gableLines.length === 0) { - const hipLine2 = drawHipLine(hipPoint2, canvas, roof, textMode, degree2, degree2) - baseHipLines.push({ x1: hipLine2.x1, y1: hipLine2.y1, x2: hipLine2.x2, y2: hipLine2.y2, line: hipLine2 }) - } - } - } - } - }) - - /** 팔작지붕 */ - drawHipAndGableFirst.forEach((current) => { - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - let { x1, x2, y1, y2 } = currentBaseLine - const currentDegree = getDegreeByChon(currentLine.attributes.pitch) - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - const nextDegree = getDegreeByChon(nextLine.attributes.pitch) - - let beforePrevLine, afterNextLine - drawBaseLines.forEach((line, index) => { - if (line === prevBaseLine) { - beforePrevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] - } - if (line === nextBaseLine) { - afterNextLine = drawBaseLines[(index + 1) % drawBaseLines.length] - } - }) - /** 팔작지붕 두께*/ - const lineWidth = - currentLine.attributes.width < Big(currentLine.attributes.planeSize).div(20).toNumber() - ? currentLine.attributes.width - : Big(currentLine.attributes.planeSize).div(20).toNumber() - - const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1) - const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1) - - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2) - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2) - const intersectionRoofs = [] - if (currentVectorX === 0) { - const checkEdge = { - vertex1: { x: prevLine.x1, y: currentMidY.toNumber() }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: currentMidX.toNumber(), y: prevLine.y1 }, - vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } - - let currentRoof, prevRoof, nextRoof - if (intersectionRoofs.length > 0) { - currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line - } - - roof.lines.forEach((line, index) => { - if (line === currentRoof) { - prevRoof = roof.lines[(index - 1 + roof.lines.length) % roof.lines.length] - nextRoof = roof.lines[(index + 1) % roof.lines.length] - } - }) - - // /** 이전, 다음라인의 사잇각의 vector를 구한다. */ - let prevVector = getHalfAngleVector(prevRoof, currentRoof) - let nextVector = getHalfAngleVector(currentRoof, nextRoof) - - let prevHipVector = { x: Math.sign(prevVector.x), y: Math.sign(prevVector.y) } - let nextHipVector = { x: Math.sign(nextVector.x), y: Math.sign(nextVector.y) } - - /** 현재 라인의 길이 추녀마루 길이의 기준이 된다. */ - let hipSize = Big(lineWidth).pow(2).plus(Big(lineWidth).pow(2)).sqrt() - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const prevCheckPoint = { - x: Big(currentRoof.x1).plus(Big(prevHipVector.x).times(lineWidth)), - y: Big(currentRoof.y1).plus(Big(prevHipVector.y).times(lineWidth)), - } - if (!roof.inPolygon(prevCheckPoint)) { - prevHipVector = { x: Math.sign(prevHipVector.x * -1), y: Math.sign(prevHipVector.y * -1) } - } - - /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const nextCheckPoint = { - x: Big(currentRoof.x2).plus(Big(nextHipVector.x).times(lineWidth)), - y: Big(currentRoof.y2).plus(Big(nextHipVector.y).times(lineWidth)), - } - if (!roof.inPolygon(nextCheckPoint)) { - nextHipVector = { x: Math.sign(nextHipVector.x * -1), y: Math.sign(nextHipVector.y * -1) } - } - - /** 처마끝에서 올라오는 라인*/ - const prevPoint = [ - currentRoof.x1, - currentRoof.y1, - Big(currentRoof.x1).plus(Big(prevHipVector.x).times(lineWidth)).toNumber(), - Big(currentRoof.y1).plus(Big(prevHipVector.y).times(lineWidth)).toNumber(), - ] - const nextPoint = [ - currentRoof.x2, - currentRoof.y2, - Big(currentRoof.x2).plus(Big(nextHipVector.x).times(lineWidth)).toNumber(), - Big(currentRoof.y2).plus(Big(nextHipVector.y).times(lineWidth)).toNumber(), - ] - const prevHipLine = drawHipLine(prevPoint, canvas, roof, textMode, prevDegree, currentDegree) - const nextHipLine = drawHipLine(nextPoint, canvas, roof, textMode, currentDegree, nextDegree) - baseHipLines.push({ x1, y1, x2: prevHipLine.x1, y2: prevHipLine.y1, line: prevHipLine }) - baseHipLines.push({ x1: x2, y1: y2, x2: nextHipLine.x1, y2: nextHipLine.y1, line: nextHipLine }) - - /** 처마끝에서 올라오는 라인에서 가운데로 모이는 라인*/ - let midX, midY - if (currentVectorX === 0) { - midX = prevHipLine.x2 - midY = currentMidY.toNumber() - } else { - midX = currentMidX.toNumber() - midY = prevHipLine.y2 - } - const prevGablePoint = [prevHipLine.x2, prevHipLine.y2, midX, midY] - const nextGablePoint = [nextHipLine.x2, nextHipLine.y2, midX, midY] - - const prevGableLine = drawHipLine(prevGablePoint, canvas, roof, textMode, prevDegree, currentDegree) - const nextGableLine = drawHipLine(nextGablePoint, canvas, roof, textMode, currentDegree, nextDegree) - baseHipLines.push({ x1: prevGableLine.x1, y1: prevGableLine.y1, x2: prevGableLine.x2, y2: prevGableLine.y2, line: prevGableLine }) - baseHipLines.push({ x1: nextGableLine.x1, y1: nextGableLine.y1, x2: nextGableLine.x2, y2: nextGableLine.y2, line: nextGableLine }) - - let oppositeLine - baseLines - .filter((line) => line !== currentLine) - .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) - .forEach((oppCurrLine) => { - let checkEdge - if (currentVectorX === 0) { - checkEdge = { - vertex1: { x: midX, y: midY }, - vertex2: { x: oppCurrLine.x1, y: midY }, - } - } else { - checkEdge = { - vertex1: { x: midX, y: midY }, - vertex2: { x: midX, y: oppCurrLine.y1 }, - } - } - const lineEdge = { vertex1: { x: oppCurrLine.x1, y: oppCurrLine.y1 }, vertex2: { x: oppCurrLine.x2, y: oppCurrLine.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && isPointOnLine(oppCurrLine, intersection)) { - const size = - calcLinePlaneSize({ - x1: checkEdge.vertex1.x, - y1: checkEdge.vertex1.y, - x2: intersection.x, - y2: intersection.y, - }) / 10 - oppositeLine = { intersection, size, oppCurrLine } - } - }) - - if (oppositeLine) { - const { intersection, size, oppCurrLine } = oppositeLine - let oppPrevLine, oppNextLine - let oppRoofLine - - let ridgePoints = [] - let ridgeSize - - const ridgeEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { x: intersection.x, y: intersection.y }, - } - - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let beforePrevVector = getHalfAngleVector(prevLine, beforePrevLine) - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const beforePrevCheckPoint = { - x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(10)), - y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(beforePrevCheckPoint)) { - beforePrevVector = { x: -beforePrevVector.x, y: -beforePrevVector.y } - } - - const checkBeforeEdge = { - vertex1: { x: prevLine.x1, y: prevLine.y1 }, - vertex2: { - x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(10)).toNumber(), - y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(10)).toNumber(), - }, - } - - const isBefore = edgesIntersection(checkBeforeEdge, ridgeEdge) - if (isBefore) { - const size = Big(isBefore.x).minus(midX).abs().pow(2).plus(Big(isBefore.y).minus(midY).abs().pow(2)).sqrt().toNumber() - ridgePoints.push({ x: isBefore.x, y: isBefore.y, size }) - } - } - - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && afterNextLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let afterNextVector = getHalfAngleVector(nextLine, afterNextLine) - - /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const afterNextCheckPoint = { - x: Big(nextLine.x2).plus(Big(afterNextVector.x).times(10)), - y: Big(nextLine.y2).plus(Big(afterNextVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(afterNextCheckPoint)) { - afterNextVector = { x: -afterNextVector.x, y: -afterNextVector.y } - } - - const checkAfterEdge = { - vertex1: { x: nextLine.x2, y: nextLine.y2 }, - vertex2: { - x: Big(nextLine.x2).plus(Big(afterNextVector.x).times(10)).toNumber(), - y: Big(nextLine.y2).plus(Big(afterNextVector.y).times(10)).toNumber(), - }, - } - const isAfter = edgesIntersection(checkAfterEdge, ridgeEdge) - if (isAfter) { - const size = Big(isAfter.x).minus(midX).abs().pow(2).plus(Big(isAfter.y).minus(midY).abs().pow(2)).sqrt().toNumber() - ridgePoints.push({ x: isAfter.x, y: isAfter.y, size }) - } - } - - baseLines.forEach((line, index) => { - if (line === oppCurrLine) { - oppPrevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length] - oppNextLine = baseLines[(index + 1) % baseLines.length] - } - }) - - const oppositeRoofs = [] - const oppositeMidX = Big(oppCurrLine.x1).plus(Big(oppCurrLine.x2)).div(2) - const oppositeMidY = Big(oppCurrLine.y1).plus(Big(oppCurrLine.y2)).div(2) - const oppositeVectorX = Math.sign(oppCurrLine.x2 - oppCurrLine.x1) - const oppositeVectorY = Math.sign(oppCurrLine.y2 - oppCurrLine.y1) - - if (Math.sign(oppCurrLine.x1 - oppCurrLine.x2) === 0) { - const checkEdge = { - vertex1: { x: oppPrevLine.x1, y: oppositeMidY.toNumber() }, - vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - oppositeRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppPrevLine.y1 }, - vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - oppositeRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } - if (oppositeRoofs.length > 0) { - oppRoofLine = oppositeRoofs.sort((a, b) => a.size - b.size)[0].line - } - - if (oppCurrLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - if (oppRoofLine) { - const oppRoofSize = Big(oppRoofLine.attributes.planeSize).div(20) - const ridgeEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { x: intersection.x, y: intersection.y }, - } - - if (oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let oppPrevVector = getHalfAngleVector(oppCurrLine, oppPrevLine) - oppPrevVector = { x: oppPrevVector.x, y: oppPrevVector.y } - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const prevCheckPoint = { - x: Big(oppCurrLine.x1).plus(Big(oppPrevVector.x).times(10)), - y: Big(oppCurrLine.y1).plus(Big(oppPrevVector.y).times(10)), - } - - if (!checkWallPolygon.inPolygon(prevCheckPoint)) { - oppPrevVector = { x: -oppPrevVector.x, y: -oppPrevVector.y } - } - - const oppPrevHipEdge = { - vertex1: { - x: oppRoofLine.x1, - y: oppRoofLine.y1, - }, - vertex2: { - x: Big(oppRoofLine.x1).plus(Big(oppPrevVector.x).times(oppRoofSize)).toNumber(), - y: Big(oppRoofLine.y1).plus(Big(oppPrevVector.y).times(oppRoofSize)).toNumber(), - }, - } - - const isOppPrev = edgesIntersection(oppPrevHipEdge, ridgeEdge) - - if ( - isOppPrev && - isPointOnLine( - { - x1: oppPrevHipEdge.vertex1.x, - y1: oppPrevHipEdge.vertex1.y, - x2: oppPrevHipEdge.vertex2.x, - y2: oppPrevHipEdge.vertex2.y, - }, - isOppPrev, - ) - ) { - const size = Big(isOppPrev.x).minus(midX).abs().pow(2).plus(Big(isOppPrev.y).minus(midY).abs().pow(2)).sqrt().toNumber() - ridgePoints.push({ x: isOppPrev.x, y: isOppPrev.y, size }) - } - } - if (oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let oppNextVector = getHalfAngleVector(oppCurrLine, oppNextLine) - oppNextVector = { x: oppNextVector.x, y: oppNextVector.y } - - /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const nextCheckPoint = { - x: Big(oppCurrLine.x2).plus(Big(oppNextVector.x).times(10)), - y: Big(oppCurrLine.y2).plus(Big(oppNextVector.y).times(10)), - } - - if (!checkWallPolygon.inPolygon(nextCheckPoint)) { - oppNextVector = { x: -oppNextVector.x, y: -oppNextVector.y } - } - - const oppNextHipEdge = { - vertex1: { - x: oppRoofLine.x2, - y: oppRoofLine.y2, - }, - vertex2: { - x: Big(oppRoofLine.x2).plus(Big(oppNextVector.x).times(oppRoofSize)).toNumber(), - y: Big(oppRoofLine.y2).plus(Big(oppNextVector.y).times(oppRoofSize)).toNumber(), - }, - } - const isOppNext = edgesIntersection(oppNextHipEdge, ridgeEdge) - if ( - isOppNext && - isPointOnLine( - { - x1: oppNextHipEdge.vertex1.x, - y1: oppNextHipEdge.vertex1.y, - x2: oppNextHipEdge.vertex2.x, - y2: oppNextHipEdge.vertex2.y, - }, - isOppNext, - ) - ) { - const size = Big(isOppNext.x).minus(midX).abs().pow(2).plus(Big(isOppNext.y).minus(midY).abs().pow(2)).sqrt().toNumber() - ridgePoints.push({ x: isOppNext.x, y: isOppNext.y, size }) - } - } - } - } else if (oppCurrLine.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) { - ridgeSize = Big(size).minus(Big(oppCurrLine.attributes.width)).plus(Big(oppCurrLine.attributes.offset)).toNumber() - } - - if (ridgePoints.length > 0) { - ridgeSize = ridgePoints.sort((a, b) => a.size - b.size)[0].size - } - - if (ridgeSize > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) { - const ridgeVectorX = Math.sign(midX - intersection.x) - const ridgeVectorY = Math.sign(midY - intersection.y) - const ridgePoint = [ - midX, - midY, - Big(midX).minus(Big(ridgeSize).times(ridgeVectorX)).toNumber(), - Big(midY).minus(Big(ridgeSize).times(ridgeVectorY)).toNumber(), - ] - const ridgeLine = drawRidgeLine(ridgePoint, canvas, roof, textMode) - baseRidgeLines.push(ridgeLine) - baseRidgeCount++ - } else { - let ridges = [] - baseGableRidgeLines - .filter( - (ridge) => - (Math.abs(ridge.x1 - midX) < 1 && Math.abs(ridge.y1 - midY) < 1) || (Math.abs(ridge.x2 - midX) < 1 && Math.abs(ridge.y2 - midY) < 1), - ) - .forEach((ridge) => ridges.push(ridge)) - baseRidgeLines - .filter( - (ridge) => - (Math.abs(ridge.x1 - midX) < 1 && Math.abs(ridge.y1 - midY) < 1) || (Math.abs(ridge.x2 - midX) < 1 && Math.abs(ridge.y2 - midY) < 1), - ) - .forEach((ridge) => ridges.push(ridge)) - if (ridges.length > 0) { - return - } - - // canvas.remove(prevGableLine) - // canvas.remove(nextGableLine) - baseHipLines = baseHipLines.filter((base) => base.line !== prevGableLine && base.line !== nextGableLine) - - const points = [prevGableLine.x1, prevGableLine.y1, nextGableLine.x1, nextGableLine.y1] - const gableLine = drawRoofLine(points, canvas, roof, textMode) - baseHipLines.push({ x1: gableLine.x1, y1: gableLine.y1, x2: gableLine.x2, y2: gableLine.y2, line: gableLine }) - } - } - }) - - /** 벽과 이어진 마루를 그린다. */ - drawWallRidgeLine.forEach((current) => { - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - let beforePrevLine, afterNextLine - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - const nextDegree = getDegreeByChon(nextLine.attributes.pitch) - const currentMidX = Big(currentLine.x1).plus(Big(currentLine.x2)).div(2).toNumber() - const currentMidY = Big(currentLine.y1).plus(Big(currentLine.y2)).div(2).toNumber() - const currentVectorX = Math.sign(currentLine.x2 - currentLine.x1) - const currentVectorY = Math.sign(currentLine.y2 - currentLine.y1) - - /** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */ - drawBaseLines.forEach((line, index) => { - if (line === prevBaseLine) { - beforePrevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] - } - if (line === nextBaseLine) { - afterNextLine = drawBaseLines[(index + 1) % drawBaseLines.length] - } - }) - - let oppositeLine - baseLines - .filter((line) => line !== currentLine) - .filter((line) => (currentVectorX === 0 ? line.x1 === line.x2 : line.y1 === line.y2)) - .forEach((oppCurrLine) => { - let checkEdge - if (currentVectorX === 0) { - checkEdge = { - vertex1: { x: currentMidX, y: currentMidY }, - vertex2: { x: oppCurrLine.x1, y: currentMidY }, - } - } else { - checkEdge = { - vertex1: { x: currentMidX, y: currentMidY }, - vertex2: { x: currentMidX, y: oppCurrLine.y1 }, - } - } - const lineEdge = { vertex1: { x: oppCurrLine.x1, y: oppCurrLine.y1 }, vertex2: { x: oppCurrLine.x2, y: oppCurrLine.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && isPointOnLine(oppCurrLine, intersection)) { - const size = - calcLinePlaneSize({ - x1: checkEdge.vertex1.x, - y1: checkEdge.vertex1.y, - x2: intersection.x, - y2: intersection.y, - }) / 10 - oppositeLine = { intersection, size, oppCurrLine } - } - }) - - const ridgePoints = [] - if (oppositeLine) { - const { intersection, size, oppCurrLine } = oppositeLine - ridgePoints.push({ x: intersection.x, y: intersection.y, size }) - const oppPrevLine = baseLines.find((line) => line.x2 === oppCurrLine.x1 && line.y2 === oppCurrLine.y1) - const oppNextLine = baseLines.find((line) => line.x1 === oppCurrLine.x2 && line.y1 === oppCurrLine.y2) - - const oppositeRoofs = [] - const oppositeMidX = Big(oppCurrLine.x1).plus(Big(oppCurrLine.x2)).div(2) - const oppositeMidY = Big(oppCurrLine.y1).plus(Big(oppCurrLine.y2)).div(2) - const oppositeVectorX = Math.sign(oppCurrLine.x2 - oppCurrLine.x1) - const oppositeVectorY = Math.sign(oppCurrLine.y2 - oppCurrLine.y1) - - let oppRoofLine - - if (Math.sign(oppCurrLine.x1 - oppCurrLine.x2) === 0) { - const checkEdge = { - vertex1: { x: oppPrevLine.x1, y: oppositeMidY.toNumber() }, - vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - oppositeRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: oppositeMidX.toNumber(), y: oppPrevLine.y1 }, - vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === oppositeVectorX && Math.sign(line.y2 - line.y1) === oppositeVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - oppositeRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(oppositeMidX).abs().pow(2).plus(Big(intersection.y).minus(oppositeMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } - if (oppositeRoofs.length > 0) { - oppRoofLine = oppositeRoofs.sort((a, b) => a.size - b.size)[0].line - } - - if (oppRoofLine) { - const ridgeEdge = { vertex1: { x: currentMidX, y: currentMidY }, vertex2: { x: intersection.x, y: intersection.y } } - - if (oppCurrLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - const oppRoofSize = Big(oppRoofLine.attributes.planeSize).div(20) - - if (oppPrevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let oppPrevVector = getHalfAngleVector(oppCurrLine, oppPrevLine) - oppPrevVector = { x: oppPrevVector.x, y: oppPrevVector.y } - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const prevCheckPoint = { - x: Big(oppCurrLine.x1).plus(Big(oppPrevVector.x).times(10)), - y: Big(oppCurrLine.y1).plus(Big(oppPrevVector.y).times(10)), - } - - if (!checkWallPolygon.inPolygon(prevCheckPoint)) { - oppPrevVector = { x: -oppPrevVector.x, y: -oppPrevVector.y } - } - - const oppPrevHipEdge = { - vertex1: { - x: oppRoofLine.x1, - y: oppRoofLine.y1, - }, - vertex2: { - x: Big(oppRoofLine.x1).plus(Big(oppPrevVector.x).times(oppRoofSize)).toNumber(), - y: Big(oppRoofLine.y1).plus(Big(oppPrevVector.y).times(oppRoofSize)).toNumber(), - }, - } - - const isOppPrev = edgesIntersection(oppPrevHipEdge, ridgeEdge) - - if ( - isOppPrev && - isPointOnLine( - { - x1: oppPrevHipEdge.vertex1.x, - y1: oppPrevHipEdge.vertex1.y, - x2: oppPrevHipEdge.vertex2.x, - y2: oppPrevHipEdge.vertex2.y, - }, - isOppPrev, - ) - ) { - const size = Big(isOppPrev.x).minus(currentMidX).abs().pow(2).plus(Big(isOppPrev.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber() - ridgePoints.push({ x: isOppPrev.x, y: isOppPrev.y, size }) - } - } - if (oppNextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let oppNextVector = getHalfAngleVector(oppCurrLine, oppNextLine) - oppNextVector = { x: oppNextVector.x, y: oppNextVector.y } - - /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const nextCheckPoint = { - x: Big(oppCurrLine.x2).plus(Big(oppNextVector.x).times(10)), - y: Big(oppCurrLine.y2).plus(Big(oppNextVector.y).times(10)), - } - - if (!checkWallPolygon.inPolygon(nextCheckPoint)) { - oppNextVector = { x: -oppNextVector.x, y: -oppNextVector.y } - } - - const oppNextHipEdge = { - vertex1: { - x: oppRoofLine.x2, - y: oppRoofLine.y2, - }, - vertex2: { - x: Big(oppRoofLine.x2).plus(Big(oppNextVector.x).times(oppRoofSize)).toNumber(), - y: Big(oppRoofLine.y2).plus(Big(oppNextVector.y).times(oppRoofSize)).toNumber(), - }, - } - - const isOppNext = edgesIntersection(oppNextHipEdge, ridgeEdge) - if ( - isOppNext && - isPointOnLine( - { - x1: oppNextHipEdge.vertex1.x, - y1: oppNextHipEdge.vertex1.y, - x2: oppNextHipEdge.vertex2.x, - y2: oppNextHipEdge.vertex2.y, - }, - isOppNext, - ) - ) { - const size = Big(isOppNext.x).minus(currentMidX).abs().pow(2).plus(Big(isOppNext.y).minus(currentMidY).abs().pow(2)).sqrt().toNumber() - ridgePoints.push({ x: isOppNext.x, y: isOppNext.y, size }) - } - } - } else { - baseHipLines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(ridgeEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - const size = Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt() - ridgePoints.push({ x: intersection.x, y: intersection.y, size }) - } - } - }) - } - - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let beforePrevVector = getHalfAngleVector(prevLine, beforePrevLine) - const checkPoint = { - x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(10)), - y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(checkPoint)) { - beforePrevVector = { x: -beforePrevVector.x, y: -beforePrevVector.y } - } - - const hipEdge = { - vertex1: { x: prevLine.x1, y: prevLine.y1 }, - vertex2: { - x: Big(prevLine.x1).plus(Big(beforePrevVector.x).times(prevLine.attributes.planeSize)).toNumber(), - y: Big(prevLine.y1).plus(Big(beforePrevVector.y).times(prevLine.attributes.planeSize)).toNumber(), - }, - } - - const isLines = [] - drawBaseLines - .filter((base) => base !== currentBaseLine && base !== prevBaseLine && base !== beforePrevLine) - .forEach((base) => { - const lineEdge = { vertex1: { x: base.line.x1, y: base.line.y1 }, vertex2: { x: base.line.x2, y: base.line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if (intersection && isPointOnLine(base.line, intersection)) { - const size = Big(intersection.x) - .minus(prevLine.x1) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(prevLine.y1).abs().pow(2)) - .sqrt() - .toNumber() - isLines.push({ intersection, size }) - } - }) - - if (isLines.length > 0) { - const hipSize = getAdjacent(isLines.sort((a, b) => a.size - b.size)[0].size / 2) - const hipPoint = [ - prevLine.x1, - prevLine.y1, - Big(prevLine.x1).plus(Big(beforePrevVector.x).times(hipSize)).toNumber(), - Big(prevLine.y1).plus(Big(beforePrevVector.y).times(hipSize)).toNumber(), - ] - - const hipEdge = { vertex1: { x: hipPoint[0], y: hipPoint[1] }, vertex2: { x: hipPoint[2], y: hipPoint[3] } } - const intersection = edgesIntersection(ridgeEdge, hipEdge) - if ( - intersection && - (isPointOnLine({ x1: hipPoint[0], y1: hipPoint[1], x2: hipPoint[2], y2: hipPoint[3] }, intersection) || - (Math.abs(hipPoint[0] - intersection.x) < 1 && Math.abs(hipPoint[1] - intersection.y) < 1) || - (Math.abs(hipPoint[2] - intersection.x) < 1 && Math.abs(hipPoint[3] - intersection.y) < 1)) - ) { - const size = Big(intersection.x) - .minus(currentMidX) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) - .sqrt() - .toNumber() - ridgePoints.push({ x: intersection.x, y: intersection.y, size }) - } - } - } - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && afterNextLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let afterNextVector = getHalfAngleVector(nextLine, afterNextLine) - const checkPoint = { - x: Big(nextLine.x1).plus(Big(afterNextVector.x).times(10)), - y: Big(nextLine.y1).plus(Big(afterNextVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(checkPoint)) { - afterNextVector = { x: -afterNextVector.x, y: -afterNextVector.y } - } - - const hipEdge = { - vertex1: { x: nextLine.x2, y: nextLine.y2 }, - vertex2: { - x: Big(nextLine.x2).plus(Big(afterNextVector.x).times(nextLine.attributes.planeSize)).toNumber(), - y: Big(nextLine.y2).plus(Big(afterNextVector.y).times(nextLine.attributes.planeSize)).toNumber(), - }, - } - - const isLines = [] - drawBaseLines - .filter((base) => base !== currentBaseLine && base !== nextBaseLine && base !== afterNextLine) - .forEach((base) => { - const lineEdge = { vertex1: { x: base.line.x1, y: base.line.y1 }, vertex2: { x: base.line.x2, y: base.line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if (intersection && isPointOnLine(base.line, intersection)) { - const size = Big(intersection.x) - .minus(nextLine.x2) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(nextLine.y2).abs().pow(2)) - .sqrt() - .toNumber() - isLines.push({ intersection, size }) - } - }) - if (isLines.length > 0) { - const hipSize = getAdjacent(isLines.sort((a, b) => a.size - b.size)[0].size / 2) - const hipPoint = [ - nextLine.x2, - nextLine.y2, - Big(nextLine.x2).plus(Big(afterNextVector.x).times(hipSize)).toNumber(), - Big(nextLine.y2).plus(Big(afterNextVector.y).times(hipSize)).toNumber(), - ] - const hipEdge = { vertex1: { x: hipPoint[0], y: hipPoint[1] }, vertex2: { x: hipPoint[2], y: hipPoint[3] } } - const intersection = edgesIntersection(ridgeEdge, hipEdge) - - if ( - intersection && - (isPointOnLine({ x1: hipPoint[0], y1: hipPoint[1], x2: hipPoint[2], y2: hipPoint[3] }, intersection) || - (Math.abs(hipPoint[0] - intersection.x) < 1 && Math.abs(hipPoint[1] - intersection.y) < 1) || - (Math.abs(hipPoint[2] - intersection.x) < 1 && Math.abs(hipPoint[3] - intersection.y) < 1)) - ) { - const size = Big(intersection.x) - .minus(currentMidX) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(currentMidY).abs().pow(2)) - .sqrt() - .toNumber() - ridgePoints.push({ x: intersection.x, y: intersection.y, size }) - } - } - } - } - } - - if (ridgePoints.length === 0 || baseRidgeCount >= getMaxRidge(baseLines.length)) return - const ridgeEndPoint = ridgePoints.sort((a, b) => a.size - b.size)[0] - const ridgePoint = { x1: currentMidX, y1: currentMidY, x2: ridgeEndPoint.x, y2: ridgeEndPoint.y } - - /** 포인트가 지붕밖에 있는 경우 조정*/ - if (!roof.inPolygon({ x: ridgePoint.x1, y: ridgePoint.y1 })) { - const checkEdge = { vertex1: { x: ridgePoint.x2, y: ridgePoint.y2 }, vertex2: { x: ridgePoint.x1, y: ridgePoint.y1 } } - const isPoints = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && isPointOnLine(line, intersection)) { - if ( - Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) === Math.sign(checkEdge.vertex1.x - intersection.x) && - Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) === Math.sign(checkEdge.vertex1.y - intersection.y) - ) { - const size = Big(intersection.x) - .minus(ridgePoint.x2) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(ridgePoint.y2).abs().pow(2)) - .sqrt() - .toNumber() - isPoints.push({ x: intersection.x, y: intersection.y, size }) - } - } - }) - if (isPoints.length > 0) { - const newPoint = isPoints.sort((a, b) => a.size - b.size)[0] - ridgePoint.x1 = newPoint.x - ridgePoint.y1 = newPoint.y - } - } - - if (!roof.inPolygon({ x: ridgePoint.x2, y: ridgePoint.y2 })) { - const checkEdge = { vertex1: { x: ridgePoint.x1, y: ridgePoint.y1 }, vertex2: { x: ridgePoint.x2, y: ridgePoint.y2 } } - const isPoints = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && isPointOnLine(line, intersection)) { - if ( - Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x) === Math.sign(checkEdge.vertex1.x - intersection.x) && - Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y) === Math.sign(checkEdge.vertex1.y - intersection.y) - ) { - const size = Big(intersection.x) - .minus(ridgePoint.x1) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(ridgePoint.y1).abs().pow(2)) - .sqrt() - .toNumber() - isPoints.push({ x: intersection.x, y: intersection.y, size }) - } - } - }) - if (isPoints.length > 0) { - const newPoint = isPoints.sort((a, b) => a.size - b.size)[0] - ridgePoint.x2 = newPoint.x - ridgePoint.y2 = newPoint.y - } - } - - const ridge = drawRidgeLine([ridgePoint.x1, ridgePoint.y1, ridgePoint.x2, ridgePoint.y2], canvas, roof, textMode) - baseRidgeLines.push(ridge) - baseRidgeCount++ - - /** 현재 라인의 지붕 라인을 찾는다. */ - const intersectionRoofs = [] - let currentRoof - if (currentVectorX === 0) { - const checkEdge = { - vertex1: { x: prevLine.x1, y: currentMidY }, - vertex2: { x: currentMidX, y: currentMidY }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } else { - const checkEdge = { - vertex1: { x: currentMidX, y: prevLine.y1 }, - vertex2: { x: currentMidX, y: currentMidY }, - } - roof.lines - .filter((line) => Math.sign(line.x2 - line.x1) === currentVectorX && Math.sign(line.y2 - line.y1) === currentVectorY) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection) { - if (isPointOnLine(line, intersection)) { - intersectionRoofs.push({ - line, - intersection, - size: Big(intersection.x).minus(currentMidX).abs().pow(2).plus(Big(intersection.y).minus(currentMidY).abs().pow(2)).sqrt(), - }) - } - } - }) - } - if (intersectionRoofs.length > 0) { - currentRoof = intersectionRoofs.sort((a, b) => a.size - b.size)[0].line - } - if (currentRoof) { - const prevHipPoint = [currentRoof.x1, currentRoof.y1, currentMidX, currentMidY] - const nextHipPoint = [currentRoof.x2, currentRoof.y2, currentMidX, currentMidY] - - const prevHipLine = drawHipLine(prevHipPoint, canvas, roof, textMode, prevDegree, prevDegree) - const nextHipLine = drawHipLine(nextHipPoint, canvas, roof, textMode, nextDegree, nextDegree) - baseHipLines.push({ x1: prevHipLine.x1, y1: prevHipLine.y1, x2: prevHipLine.x2, y2: prevHipLine.y2, line: prevHipLine }) - baseHipLines.push({ x1: nextHipLine.x1, y1: nextHipLine.y1, x2: nextHipLine.x2, y2: nextHipLine.y2, line: nextHipLine }) - } - }) - - /** ⨆ 모양 처마에 추녀마루를 그린다. */ - drawEavesFirstLines.forEach((current) => { - // 확인용 라인, 포인트 제거 - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - let { x1, x2, y1, y2, size } = currentBaseLine - let beforePrevLine, afterNextLine - - /** 이전 라인의 경사 */ - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - /** 다음 라인의 경사 */ - const currentDegree = getDegreeByChon(currentLine.attributes.pitch) - - /** 이전 라인의 전라인, 다음 라인의 다음라인을 찾는다 */ - drawBaseLines.forEach((line, index) => { - if (line === prevBaseLine) { - beforePrevLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length] - } - if (line === nextBaseLine) { - afterNextLine = drawBaseLines[(index + 1) % drawBaseLines.length] - } - }) - - /** 이전, 다음라인의 사잇각의 vector를 구한다. */ - let prevVector = getHalfAngleVector(prevLine, currentLine) - let nextVector = getHalfAngleVector(currentLine, nextLine) - - let prevHipVector = { x: prevVector.x, y: prevVector.y } - let nextHipVector = { x: nextVector.x, y: nextVector.y } - - /** 각 라인의 흐름 방향을 확인한다. */ - const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - const beforePrevAngle = calculateAngle(beforePrevLine.line.startPoint, beforePrevLine.line.endPoint) - const afterNextAngle = calculateAngle(afterNextLine.line.startPoint, afterNextLine.line.endPoint) - - /** 현재 라인의 길이 추녀마루 길이의 기준이 된다. */ - let currentSize = Big(size).div(10) - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const prevCheckPoint = { - x: Big(x1).plus(Big(prevHipVector.x).times(10)), - y: Big(y1).plus(Big(prevHipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(prevCheckPoint)) { - prevHipVector = { x: -prevHipVector.x, y: -prevHipVector.y } - } - - /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const nextCheckPoint = { - x: Big(x2).plus(Big(nextHipVector.x).times(10)), - y: Big(y2).plus(Big(nextHipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(nextCheckPoint)) { - nextHipVector = { x: -nextHipVector.x, y: -nextHipVector.y } - } - - /** 현재 라인의 길이를 기준으로 추녀 마루의 길이를 삼각함수를 사용하여 판단한다.*/ - let hipLength = currentSize.div(2).pow(2).plus(currentSize.div(2).pow(2)).sqrt() - - /** - * 현재 라인에서 2번째 전 라인과 2번째 후 라인의 각도가 같을때 -_- 와 같은 형태로 판단하고 - * 맞은 편 외벽선까지의 거리를 확인후 currentSize 를 조정한다. - */ - if (beforePrevLine === afterNextLine || (currentAngle === beforePrevAngle && currentAngle === afterNextAngle)) { - console.log('4각 ::::::::: ') - const xVector = Big(nextLine.x2).minus(Big(nextLine.x1)) - const yVector = Big(nextLine.y2).minus(Big(nextLine.y1)) - const currentMidX = Big(x1).plus(Big(x2)).div(2) - const currentMidY = Big(y1).plus(Big(y2)).div(2) - - const midLineEdge = { - vertex1: { x: currentMidX.toNumber(), y: currentMidY.toNumber() }, - vertex2: { - x: currentMidX.plus(currentSize.times(Math.sign(xVector))).toNumber(), - y: currentMidY.plus(currentSize.times(Math.sign(yVector))).toNumber(), - }, - } - - /** 현재 라인의 중심 지점에서 현재라인의 길이만큼 다음라인의 방향만큼 거리를 확인한다*/ - baseLines - .filter((line) => line !== currentLine) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(midLineEdge, lineEdge) - /** 현재라인의 길이만큼 거리가 모자라면 해당 길이 만큼을 현재라인의 길이로 판단하고 나머지 계산을 진행한다.*/ - if (intersection && !intersection.isIntersectionOutside) { - const intersectionSize = Big(intersection.x) - .minus(Big(currentMidX)) - .plus(Big(intersection.y).minus(Big(currentMidY))) - .abs() - if (intersectionSize.lt(currentSize)) { - currentSize = intersectionSize - } - } - }) - - hipLength = currentSize.div(2).pow(2).plus(currentSize.div(2).pow(2)).sqrt() - } else { - if (currentAngle !== beforePrevAngle && currentAngle !== afterNextAngle && beforePrevLine !== afterNextLine) { - const beforePrevX1 = beforePrevLine.x1, - beforePrevY1 = beforePrevLine.y1 - const afterNextX2 = afterNextLine.x2, - afterNextY2 = afterNextLine.y2 - - /** beforePrevLine 과 afterNextLine 을 연결하는 사각형의 경우 6각으로 판단 */ - const connectBAPoint = { x1: afterNextX2, y1: afterNextY2, x2: beforePrevX1, y2: beforePrevY1 } - const isConnect = - baseLines.filter( - (line) => - line.x1 === connectBAPoint.x1 && line.y1 === connectBAPoint.y1 && line.x2 === connectBAPoint.x2 && line.y2 === connectBAPoint.y2, - ).length > 0 - - /** 6각 */ - if (isConnect) { - const checkScale = currentSize.pow(2).plus(currentSize.pow(2)).sqrt() - const intersectBaseLine = [] - if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0) { - const prevEndPoint = { - x: Big(x1).plus(Big(prevHipVector.x).times(checkScale)), - y: Big(y1).plus(Big(prevHipVector.y).times(checkScale)), - } - baseLines - .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine) - .forEach((line) => { - const intersection = edgesIntersection( - { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if (intersection && !intersection.isIntersectionOutside) { - intersectBaseLine.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(x1)) - .pow(2) - .plus(Big(intersection.y).minus(Big(y1)).pow(2)) - .sqrt(), - }) - } - }) - } - if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0) { - const nextEndPoint = { - x: Big(x2).plus(Big(nextHipVector.x).times(checkScale)), - y: Big(y2).plus(Big(nextHipVector.y).times(checkScale)), - } - baseLines - .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine) - .forEach((line) => { - const intersection = edgesIntersection( - { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if (intersection && !intersection.isIntersectionOutside) { - intersectBaseLine.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(x2)) - .pow(2) - .plus(Big(intersection.y).minus(Big(y2)).pow(2)) - .sqrt(), - }) - } - }) - } - const intersection = intersectBaseLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectBaseLine[0]) - if (intersection) { - hipLength = intersection.distance - } - } else { - const rightAngleLine = baseLines - .filter( - (line) => - line !== currentLine && - line !== prevLine && - line !== nextLine && - (prevAngle === calculateAngle(line.startPoint, line.endPoint) || nextAngle === calculateAngle(line.startPoint, line.endPoint)), - ) - .filter((line) => { - const index = baseLines.indexOf(line) - const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length] - const nextLine = baseLines[(index + 1) % baseLines.length] - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - switch (prevAngle) { - case 90: - return nextAngle === -90 - case -90: - return nextAngle === 90 - case 0: - return nextAngle === 180 - case 180: - return nextAngle === 0 - } - }) - - const oppositeCurrentLine = baseLines - .filter((line) => { - const angle = calculateAngle(line.startPoint, line.endPoint) - switch (currentAngle) { - case 90: - return angle === -90 - case -90: - return angle === 90 - case 0: - return angle === 180 - case 180: - return angle === 0 - } - }) - .filter((line) => { - const index = baseLines.indexOf(line) - const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length] - const nextLine = baseLines[(index + 1) % baseLines.length] - const prevAngle = calculateAngle(prevLine.startPoint, prevLine.endPoint) - const nextAngle = calculateAngle(nextLine.startPoint, nextLine.endPoint) - switch (prevAngle) { - case 90: - return nextAngle === -90 - case -90: - return nextAngle === 90 - case 0: - return nextAngle === 180 - case 180: - return nextAngle === 0 - } - }) - - let checkHipPoints - if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0) { - checkHipPoints = [ - x1, - y1, - Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(2).toNumber(), - Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(2).toNumber(), - ] - } - - if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0) { - checkHipPoints = [ - x2, - y2, - Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(2).toNumber(), - Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(2).toNumber(), - ] - } - - if (checkHipPoints) { - const intersectPoints = [] - rightAngleLine.forEach((line) => { - const intersection = edgesIntersection( - { - vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] }, - vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] }, - }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if (intersection) { - intersectPoints.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(checkHipPoints[0])) - .pow(2) - .plus(Big(intersection.y).minus(Big(checkHipPoints[1])).pow(2)) - .sqrt() - .toNumber(), - }) - } - }) - - oppositeCurrentLine.forEach((line) => { - const intersection = edgesIntersection( - { - vertex1: { x: checkHipPoints[0], y: checkHipPoints[1] }, - vertex2: { x: checkHipPoints[2], y: checkHipPoints[3] }, - }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if (intersection) { - intersectPoints.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(checkHipPoints[0])) - .pow(2) - .plus(Big(intersection.y).minus(Big(checkHipPoints[1])).pow(2)) - .sqrt() - .toNumber(), - }) - } - }) - - if (intersectPoints.length > 0) { - const intersection = intersectPoints.sort((a, b) => a.distance - b.distance)[0] - hipLength = getAdjacent(intersection.distance) / 2 - } - } - } - } - } - let prevHipLine, nextHipLine - /** 이전라인과의 연결지점에 추녀마루를 그린다. */ - if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0) { - const prevEndPoint = { - x: Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(1), - y: Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(1), - } - - if (!roof.inPolygon({ x: prevEndPoint.x.toNumber(), y: prevEndPoint.y.toNumber() })) { - const checkEdge = { vertex1: { x: prevEndPoint.x.toNumber(), y: prevEndPoint.y.toNumber() }, vertex2: { x: x1, y: y1 } } - const intersectionPoints = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && !intersection.isIntersectionOutside) { - const size = Big(intersection.x) - .minus(Big(prevEndPoint.x)) - .pow(2) - .plus(Big(intersection.y).minus(Big(prevEndPoint.y)).pow(2)) - .sqrt() - .toNumber() - intersectionPoints.push({ intersection, size }) - } - }) - if (intersectionPoints.length > 0) { - const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection - prevEndPoint.x = Big(intersection.x) - prevEndPoint.y = Big(intersection.y) - } - } - const overlapLine = baseHipLines.find( - (line) => - isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: line.x1, y: line.y1 }) || - isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: line.x2, y: line.y2 }), - ) - - if (overlapLine) { - let size1, size2 - if ( - isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: overlapLine.x1, y: overlapLine.y1 }) - ) { - size1 = Math.sqrt(Math.pow(x1 - overlapLine.x1, 2) + Math.pow(y1 - overlapLine.y1, 2)) - } - if ( - isPointOnLineNew({ x1: x1, y1: y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber() }, { x: overlapLine.x2, y: overlapLine.y2 }) - ) { - size2 = Math.sqrt(Math.pow(x1 - overlapLine.x2, 2) + Math.pow(y1 - overlapLine.y2, 2)) - } - if (size1 && size2) { - if (size1 < size2) { - prevEndPoint.x = Big(overlapLine.x1) - prevEndPoint.y = Big(overlapLine.y1) - } else { - prevEndPoint.x = Big(overlapLine.x2) - prevEndPoint.y = Big(overlapLine.y2) - } - } else { - if (size1) { - prevEndPoint.x = Big(overlapLine.x1) - prevEndPoint.y = Big(overlapLine.y1) - } - if (size2) { - prevEndPoint.x = Big(overlapLine.x2) - prevEndPoint.y = Big(overlapLine.y2) - } - } - } - const intersectRidgeLine = [] - baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection( - { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if (intersection && !intersection.isIntersectionOutside) { - intersectRidgeLine.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(x1)) - .pow(2) - .plus(Big(intersection.y).minus(Big(y1)).pow(2)) - .sqrt(), - }) - } - }) - const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0]) - - if (intersectRidge) { - prevEndPoint.x = Big(intersectRidge.intersection.x).round(1) - prevEndPoint.y = Big(intersectRidge.intersection.y).round(1) - } - - const xVector = Math.sign(Big(prevEndPoint.x).minus(Big(x1)).neg().toNumber()) - const yVector = Math.sign(Big(prevEndPoint.y).minus(Big(y1)).neg().toNumber()) - /** 지붕 선까지의 곂침에 따른 길이를 파악하기 위한 scale*/ - let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(prevLine.attributes.offset).pow(2)).sqrt() - scale = scale.eq(0) ? Big(1) : scale - - /** scale 만큼 추녀마루를 늘려서 겹치는 포인트를 확인한다. */ - const hipEdge = { - vertex1: { x: Big(x1).plus(scale.times(xVector)).toNumber(), y: Big(y1).plus(scale.times(yVector)).toNumber() }, - vertex2: prevEndPoint, - } - - let intersectPoints = [] - /** 외벽선에서 추녀 마루가 겹치는 경우에 대한 확인*/ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - isPointOnLineNew(line, { x: intersection.x, y: intersection.y }) && - Math.sign(prevEndPoint.x - x1) === Math.sign(prevEndPoint.x - intersection.x) && - Math.sign(prevEndPoint.y - y1) === Math.sign(prevEndPoint.y - intersection.y) - ) { - const intersectSize = prevEndPoint.x - .minus(Big(intersection.x)) - .pow(2) - .plus(prevEndPoint.y.minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - }) - } - }) - - intersectPoints = intersectPoints.reduce((prev, current) => { - return prev.size < current.size ? prev : current - }, intersectPoints[0]) - - /** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/ - if (intersectPoints && intersectPoints.intersection) { - prevHipLine = drawHipLine( - [intersectPoints.intersection.x, intersectPoints.intersection.y, prevEndPoint.x.toNumber(), prevEndPoint.y.toNumber()], - canvas, - roof, - textMode, - - prevDegree, - currentDegree, - ) - baseHipLines.push({ x1, y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber(), line: prevHipLine }) - } - } - if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0) { - const nextEndPoint = { - x: Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(1), - y: Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(1), - } - - if (!roof.inPolygon({ x: nextEndPoint.x.toNumber(), y: nextEndPoint.y.toNumber() })) { - const checkEdge = { vertex1: { x: nextEndPoint.x.toNumber(), y: nextEndPoint.y.toNumber() }, vertex2: { x: x2, y: y2 } } - const intersectionPoints = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && !intersection.isIntersectionOutside) { - const size = Big(intersection.x) - .minus(Big(nextEndPoint.x)) - .pow(2) - .plus(Big(intersection.y).minus(Big(nextEndPoint.y)).pow(2)) - .sqrt() - .toNumber() - intersectionPoints.push({ intersection, size }) - } - }) - if (intersectionPoints.length > 0) { - const intersection = intersectionPoints.sort((a, b) => a.size - b.size)[0].intersection - nextEndPoint.x = Big(intersection.x) - nextEndPoint.y = Big(intersection.y) - } - } - - // const overlapLine = baseHipLines.find((line) => isPointOnLine(line, { x: nextEndPoint.x.toNumber(), y: nextEndPoint.y.toNumber() })) - const overlapLine = baseHipLines.find( - (line) => - isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: line.x1, y: line.y1 }) || - isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: line.x2, y: line.y2 }), - ) - if (overlapLine) { - let size1, size2 - if ( - isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: overlapLine.x1, y: overlapLine.y1 }) - ) { - size1 = Math.sqrt(Math.pow(x2 - overlapLine.x1, 2) + Math.pow(y2 - overlapLine.y1, 2)) - } - if ( - isPointOnLineNew({ x1: x2, y1: y2, x2: nextEndPoint.x.toNumber(), y2: nextEndPoint.y.toNumber() }, { x: overlapLine.x2, y: overlapLine.y2 }) - ) { - size2 = Math.sqrt(Math.pow(x2 - overlapLine.x2, 2) + Math.pow(y2 - overlapLine.y2, 2)) - } - if (size1 && size2) { - if (size1 < size2) { - nextEndPoint.x = Big(overlapLine.x1) - nextEndPoint.y = Big(overlapLine.y1) - } else { - nextEndPoint.x = Big(overlapLine.x2) - nextEndPoint.y = Big(overlapLine.y2) - } - } else { - if (size1) { - nextEndPoint.x = Big(overlapLine.x1) - nextEndPoint.y = Big(overlapLine.y1) - } - if (size2) { - nextEndPoint.x = Big(overlapLine.x2) - nextEndPoint.y = Big(overlapLine.y2) - } - } - } - - const intersectRidgeLine = [] - baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection( - { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - - if (intersection && !intersection.isIntersectionOutside) { - intersectRidgeLine.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(x1)) - .pow(2) - .plus(Big(intersection.y).minus(Big(y1)).pow(2)) - .sqrt(), - }) - } - }) - const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0]) - - if (intersectRidge) { - nextEndPoint.x = Big(intersectRidge.intersection.x).round(1) - nextEndPoint.y = Big(intersectRidge.intersection.y).round(1) - } - - const xVector = Math.sign(Big(nextEndPoint.x).minus(Big(x2)).neg().toNumber()) - const yVector = Math.sign(Big(nextEndPoint.y).minus(Big(y2)).neg().toNumber()) - let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(nextLine.attributes.offset).pow(2)).sqrt() - scale = scale.eq(0) ? Big(1) : scale - - const hipEdge = { - vertex1: { x: Big(x2).plus(scale.times(xVector)).toNumber(), y: Big(y2).plus(scale.times(yVector)).toNumber() }, - vertex2: nextEndPoint, - } - - let intersectPoints = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - isPointOnLineNew(line, { x: intersection.x, y: intersection.y }) && - Math.sign(nextEndPoint.x - x2) === Math.sign(nextEndPoint.x - intersection.x) && - Math.sign(nextEndPoint.y - y2) === Math.sign(nextEndPoint.y - intersection.y) - ) { - const intersectSize = nextEndPoint.x - .minus(Big(intersection.x)) - .pow(2) - .plus(nextEndPoint.y.minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - }) - } - }) - - intersectPoints = intersectPoints.reduce((prev, current) => { - return prev.size < current.size ? prev : current - }, intersectPoints[0]) - - if (intersectPoints && intersectPoints.intersection) { - nextHipLine = drawHipLine( - [intersectPoints.intersection.x, intersectPoints.intersection.y, nextEndPoint.x.toNumber(), nextEndPoint.y.toNumber()], - canvas, - roof, - textMode, - - prevDegree, - currentDegree, - ) - baseHipLines.push({ - x1: x2, - y1: y2, - x2: nextEndPoint.x.toNumber(), - y2: nextEndPoint.y.toNumber(), - line: 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) - if (intersection) { - /** 포인트 조정*/ - 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 ( - prevHipLine !== undefined && - nextHipLine !== undefined && - Big(prevHipLine.x2).minus(Big(nextHipLine.x2)).abs().lte(1) && - Big(prevHipLine.y2).minus(Big(nextHipLine.y2)).abs().lte(1) - ) { - 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) - if (beforePrevLine === afterNextLine) { - console.log('4각 :::::::: ') - const oppositeMidX = Big(beforePrevLine.x2).plus(Big(beforePrevLine.x1)).div(2) - const oppositeMidY = Big(beforePrevLine.y2).plus(Big(beforePrevLine.y1)).div(2) - if (beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - ridgeSize = oppositeMidX - .minus(Big(startPoint.x)) - .abs() - .pow(2) - .plus(oppositeMidY.minus(Big(startPoint.y)).abs().pow(2)) - .sqrt() - .minus(Big(beforePrevLine.line.attributes.planeSize).div(20)) - } else { - let width = 0 - if (beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { - width = beforePrevLine.line.attributes.width / 2 - } else if (beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) { - width = beforePrevLine.line.attributes.width - } - const checkEdge = { vertex1: { x: startPoint.x, y: startPoint.y }, vertex2: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() } } - const vectorX = Math.sign(startPoint.x - oppositeMidX.toNumber()) - const vectorY = Math.sign(startPoint.y - oppositeMidY.toNumber()) - const oppositeRoofPoints = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdge, lineEdge) - if (intersection && Math.sign(startPoint.x - intersection.x) === vectorX && Math.sign(startPoint.y - intersection.y) === vectorY) { - const size = Big(intersection.x) - .minus(Big(startPoint.x)) - .pow(2) - .plus(Big(intersection.y).minus(Big(startPoint.y)).pow(2)) - .sqrt() - .toNumber() - oppositeRoofPoints.push({ intersection, size }) - } - }) - if (oppositeRoofPoints.length > 0) { - const oppositeRoofPoint = oppositeRoofPoints.sort((a, b) => a.size - b.size)[0].intersection - ridgeSize = Big(oppositeRoofPoint.x) - .minus(Big(startPoint.x)) - .abs() - .pow(2) - .plus(Big(oppositeRoofPoint.y).minus(Big(startPoint.y)).abs().pow(2)) - .minus(width) - .sqrt() - } - } - } else { - 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) - 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) - if (intersection) { - ridgeSize = Big(intersection.x) - .minus(Big(startPoint.x)) - .pow(2) - .plus(Big(intersection.y).minus(Big(startPoint.y)).pow(2)) - .sqrt() - } - } 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) - if (intersection) { - 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) - if (intersectPoints.length > 0) { - ridgeSize = Big(intersectPoints[0].size) - } - } - } else { - /** baseLines 에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산*/ - let minX = Infinity - let maxX = -Infinity - let minY = Infinity - let maxY = -Infinity - - baseLines.forEach((line) => { - if (line.x1 < minX) { - minX = line.x1 - } - if (line.x1 > maxX) { - maxX = line.x1 - } - if (line.y1 < minY) { - minY = line.y1 - } - if (line.y1 > maxY) { - maxY = line.y1 - } - }) - const checkLength = Big(maxX) - .minus(Big(minX)) - .pow(2) - .plus(Big(maxY).minus(Big(minY)).pow(2)) - .sqrt() - - const checkEdges = { - vertex1: { x: startPoint.x, y: startPoint.y }, - vertex2: { - x: Big(startPoint.x).minus(checkLength.times(Math.sign(xVector))), - y: Big(startPoint.y).minus(checkLength.times(Math.sign(yVector))), - }, - } - - /** 맞은편 벽 까지의 길이 판단을 위한 교차되는 line*/ - const intersectBaseLine = [] - baseLines - .filter((line) => { - /** currentAngle 의 반대 각도인 라인 */ - const angle = calculateAngle(line.startPoint, line.endPoint) - switch (currentAngle) { - case 90: - return angle === -90 - case -90: - return angle === 90 - case 0: - return angle === 180 - case 180: - return angle === 0 - } - }) - .filter((line) => { - const currentMinX = Math.min(x1, x2) - const currentMaxX = Math.max(x1, x2) - const currentMinY = Math.min(y1, y2) - const currentMaxY = Math.max(y1, y2) - const lineMinX = Math.min(line.x1, line.x2) - const lineMaxX = Math.max(line.x1, line.x2) - const lineMinY = Math.min(line.y1, line.y2) - const lineMaxY = Math.max(line.y1, line.y2) - - /** currentLine 의 안쪽에 있거나 currentLine이 line의 안쪽에 있는 라인 */ - if (Big(currentLine.y1).minus(Big(currentLine.y2)).abs().lte(1)) { - return ( - (currentMinX <= lineMinX && lineMinX <= currentMaxX) || - (currentMinX <= lineMaxX && lineMaxX <= currentMaxX) || - (lineMinX <= currentMinX && currentMinX <= lineMaxX) || - (lineMinX <= currentMaxX && currentMaxX <= lineMaxX) - ) - } else { - return ( - (currentMinY <= lineMinY && lineMinY <= currentMaxY) || - (currentMinY <= lineMaxY && lineMaxY <= currentMaxY) || - (lineMinY <= currentMinY && currentMinY <= lineMaxY) || - (lineMinY <= currentMaxY && currentMaxY <= lineMaxY) - ) - } - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(checkEdges, lineEdge) - if (intersection) { - intersectBaseLine.push({ intersection, line }) - } - }) - - /** 맞은편 라인 */ - const oppositeLine = intersectBaseLine.reduce((prev, current) => { - const prevDistance = Big(prev.intersection.x) - .minus(Big(startPoint.x)) - .pow(2) - .plus(Big(prev.intersection.y).minus(Big(startPoint.y)).pow(2)) - .sqrt() - const currentDistance = Big(current.intersection.x) - .minus(Big(startPoint.x)) - .pow(2) - .plus(Big(current.intersection.y).minus(Big(startPoint.y)).pow(2)) - .sqrt() - return prevDistance < currentDistance ? prev : current - }, intersectBaseLine[0]) - - /** 맞은편 라인까지의 길이 = 전체 길이 - 현재라인의 길이 */ - const oppositeSize = oppositeLine - ? Big(oppositeLine.intersection.x) - .minus(Big(startPoint.x)) - .pow(2) - .plus(Big(oppositeLine.intersection.y).minus(Big(startPoint.y)).pow(2)) - .sqrt() - .minus(currentSize.div(2)) - .round(1) - .toNumber() - : Infinity - - /** 이전, 다음 라인중 길이가 짧은 길이*/ - const lineMinSize = - prevBaseLine.size < nextBaseLine.size ? Big(prevBaseLine.size).div(10).toNumber() : Big(nextBaseLine.size).div(10).toNumber() - /** 마루의 길이는 이전 다음 라인중 짧은것의 길이와 현재라인부터 맞은편 라인까지의 길이에서 현재 라인의 길이를 뺀 것중 짧은 길이 */ - ridgeSize = Big(Math.min(oppositeSize, lineMinSize)) - } - } - - if (ridgeSize.gt(0) && baseRidgeCount < getMaxRidge(baseLines.length)) { - const points = [ - startPoint.x, - startPoint.y, - Big(startPoint.x) - .minus(ridgeSize.times(Math.sign(xVector))) - .toNumber(), - Big(startPoint.y) - .minus(ridgeSize.times(Math.sign(yVector))) - .toNumber(), - ] - - const oppositeHipPoints = [] - const ridgeEdge = { vertex1: { x: points[0], y: points[1] }, vertex2: { x: points[2], y: points[3] } } - if (prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && beforePrevLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let hipVector = getHalfAngleVector(prevLine, beforePrevLine.line) - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const checkPoint = { - x: Big(prevLine.x1).plus(Big(hipVector.x).times(10)), - y: Big(prevLine.y1).plus(Big(hipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(checkPoint)) { - hipVector = { x: -hipVector.x, y: -hipVector.y } - } - - const hipEdge = { - vertex1: { x: prevLine.x1, y: prevLine.y1 }, - vertex2: { - x: Big(prevLine.x1).plus(Big(hipVector.x).times(prevLine.attributes.planeSize)).toNumber(), - y: Big(prevLine.y1).plus(Big(hipVector.y).times(prevLine.attributes.planeSize)).toNumber(), - }, - } - const intersection = edgesIntersection(ridgeEdge, hipEdge) - if (intersection) { - const size = Big(points[0] - intersection.x) - .abs() - .pow(2) - .plus( - Big(points[1] - intersection.y) - .abs() - .pow(2), - ) - .sqrt() - .toNumber() - oppositeHipPoints.push({ x: intersection.x, y: intersection.y, size }) - } - } - if (nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES && afterNextLine.line.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let hipVector = getHalfAngleVector(nextLine, afterNextLine.line) - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const checkPoint = { - x: Big(nextLine.x1).plus(Big(hipVector.x).times(10)), - y: Big(nextLine.y1).plus(Big(hipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(checkPoint)) { - hipVector = { x: -hipVector.x, y: -hipVector.y } - } - - const hipEdge = { - vertex1: { x: nextLine.x2, y: nextLine.y2 }, - vertex2: { - x: Big(nextLine.x2).plus(Big(hipVector.x).times(nextLine.attributes.planeSize)).toNumber(), - y: Big(nextLine.y2).plus(Big(hipVector.y).times(nextLine.attributes.planeSize)).toNumber(), - }, - } - const intersection = edgesIntersection(ridgeEdge, hipEdge) - if (intersection) { - const size = Big(points[0] - intersection.x) - .abs() - .pow(2) - .plus( - Big(points[1] - intersection.y) - .abs() - .pow(2), - ) - .sqrt() - .toNumber() - oppositeHipPoints.push({ x: intersection.x, y: intersection.y, size }) - } - } - if (oppositeHipPoints.length > 0) { - const oppositeHipPoint = oppositeHipPoints.sort((a, b) => a.size - b.size)[0] - points[2] = oppositeHipPoint.x - points[3] = oppositeHipPoint.y - } - - /** 동일 라인이 있는지 확인. */ - if ( - baseRidgeLines.filter((line) => { - const ridgeMinX = Math.min(points[0], points[2]) - const ridgeMaxX = Math.max(points[0], points[2]) - const ridgeMinY = Math.min(points[1], points[3]) - const ridgeMaxY = Math.max(points[1], points[3]) - const lineMinX = Math.min(line.x1, line.x2) - const lineMaxX = Math.max(line.x1, line.x2) - const lineMinY = Math.min(line.y1, line.y2) - const lineMaxY = Math.max(line.y1, line.y2) - - return ridgeMinX === lineMinX && ridgeMaxX === lineMaxX && ridgeMinY === lineMinY && ridgeMaxY === lineMaxY - }).length > 0 - ) { - return - } - - const ridgeLine = drawRidgeLine(points, canvas, roof, textMode) - if ( - oppositeHipPoints.length === 0 && - (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) - ) { - baseGableRidgeLines.push(ridgeLine) - } else { - baseRidgeLines.push(ridgeLine) - } - baseRidgeCount = baseRidgeCount + 1 - - /** 포인트 조정*/ - baseHipLines - .filter((line) => line.line === prevHipLine || line.line === nextHipLine) - .forEach((line) => { - line.x2 = points[0] - line.y2 = points[1] - line.line.set({ x2: points[0], y2: points[1] }) - // line.line.fire('modified') - }) - prevHipLine.x2 = points[0] - 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.y2 = points[1] - const nextSize = reCalculateSize(nextHipLine) - nextHipLine.attributes.planeSize = nextSize.planeSize - nextHipLine.attributes.actualSize = nextSize.actualSize - nextHipLine.fire('modified') - canvas.renderAll() - - if ( - oppositeHipPoints.length === 0 && - (gableType.includes(beforePrevLine.line.attributes.type) || gableType.includes(afterNextLine.line.attributes.type)) - ) { - const oppositeLine = gableType.includes(beforePrevLine.line.attributes.type) ? beforePrevLine.line : afterNextLine.line - 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 firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine - const firstDegree = - gableVector === Math.sign(ridgeLine.x1 - prevLine.x1) - ? getDegreeByChon(prevLine.attributes.pitch) - : getDegreeByChon(nextLine.attributes.pitch) - - const oppositeRoofPoints = [ - ridgeLine.x2, - ridgeLine.y2, - ridgeLine.x1 === firstHipLine.x1 ? firstHipLine.x2 : firstHipLine.x1, - ridgeLine.y2, - ] - const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, 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) - ? getDegreeByChon(nextLine.attributes.pitch) - : getDegreeByChon(prevLine.attributes.pitch) - - 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, 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 firstHipLine = gableVector === prevVector ? prevHipLine : nextHipLine - const firstDegree = - gableVector === Math.sign(ridgeLine.y1 - prevLine.y1) - ? getDegreeByChon(prevLine.attributes.pitch) - : getDegreeByChon(nextLine.attributes.pitch) - - const oppositeRoofPoints = [ - ridgeLine.x2, - ridgeLine.y2, - ridgeLine.x2, - ridgeLine.y1 === firstHipLine.y1 ? firstHipLine.y2 : firstHipLine.y1, - ] - const oppositeRoofLine = drawHipLine(oppositeRoofPoints, canvas, roof, textMode, 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) - ? getDegreeByChon(nextLine.attributes.pitch) - : getDegreeByChon(prevLine.attributes.pitch) - - 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, 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, - }) - } - } - } - } - } - }) - - /** 중복제거 */ - baseRidgeLines.forEach((ridge) => { - baseRidgeLines - .filter((ridge2) => ridge !== ridge2) - .forEach((ridge2) => { - let overlap = segmentsOverlap(ridge, ridge2) - if (overlap) { - roof.canvas.remove(ridge) - roof.canvas.remove(ridge2) - baseRidgeLines = baseRidgeLines.filter((r) => r !== ridge && r !== ridge2) - - baseRidgeCount = baseRidgeCount - 2 - - let x1 = Math.min(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2) - let x2 = Math.max(ridge.x1, ridge2.x1, ridge.x2, ridge2.x2) - let y1 = Math.min(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2) - let y2 = Math.max(ridge.y1, ridge2.y1, ridge.y2, ridge2.y2) - - const newRidge = drawRidgeLine([x1, y1, x2, y2], canvas, roof, textMode) - baseRidgeLines.push(newRidge) - baseRidgeCount = baseRidgeCount + 1 - } - }) - }) - - /** ㄴ 모양 처마에 추녀마루를 그린다. */ - drawEavesSecondLines.forEach((current) => { - const { currentBaseLine, prevBaseLine, nextBaseLine } = current - const currentLine = currentBaseLine.line - const prevLine = prevBaseLine.line - const nextLine = nextBaseLine.line - let { x1, x2, y1, y2 } = currentBaseLine - - /** 이전 라인의 경사 */ - const prevDegree = getDegreeByChon(prevLine.attributes.pitch) - /** 다음 라인의 경사 */ - const currentDegree = getDegreeByChon(currentLine.attributes.pitch) - - /** 이전, 다음라인의 사잇각의 vector를 구한다. */ - let prevVector = getHalfAngleVector(prevLine, currentLine) - let nextVector = getHalfAngleVector(currentLine, nextLine) - - let prevHipVector = { x: prevVector.x, y: prevVector.y } - let nextHipVector = { x: nextVector.x, y: nextVector.y } - - /** 각 라인의 흐름 방향을 확인한다. */ - const currentAngle = calculateAngle(currentLine.startPoint, currentLine.endPoint) - - /** 현재 라인의 길이 추녀마루 길이의 기준이 된다. */ - let hipLength = Big(x2) - .minus(Big(x1)) - .plus(Big(y2).minus(Big(y1))) - .abs() - - /** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const prevCheckPoint = { - x: Big(x1).plus(Big(prevHipVector.x).times(10)), - y: Big(y1).plus(Big(prevHipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(prevCheckPoint)) { - prevHipVector = { x: -prevHipVector.x, y: -prevHipVector.y } - } - - /** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/ - const nextCheckPoint = { - x: Big(x2).plus(Big(nextHipVector.x).times(10)), - y: Big(y2).plus(Big(nextHipVector.y).times(10)), - } - if (!checkWallPolygon.inPolygon(nextCheckPoint)) { - nextHipVector = { x: -nextHipVector.x, y: -nextHipVector.y } - } - - let prevHipLine, nextHipLine - /** 이전라인과의 연결지점에 추녀마루를 그린다. */ - if (baseHipLines.filter((line) => line.x1 === x1 && line.y1 === y1).length === 0 && prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let prevEndPoint = { - x: Big(x1).plus(Big(prevHipVector.x).times(hipLength)).round(2), - y: Big(y1).plus(Big(prevHipVector.y).times(hipLength)).round(2), - } - - const prevEndEdge = { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint } - - const intersectBaseLine = [] - baseLines - .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine) - .filter((line) => { - if (currentAngle === 0 || currentAngle === 180) { - return Math.sign(line.y1 - y1) === nextHipVector.y || Math.sign(line.y2 - y1) === nextHipVector.y - } else { - return Math.sign(line.x1 - x1) === nextHipVector.x || Math.sign(line.x2 - x1) === nextHipVector.x - } - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(prevEndEdge, lineEdge) - - if (intersection && Math.sign(intersection.x - x1) === nextHipVector.x && Math.sign(intersection.y - y1) === nextHipVector.y) { - const size = Big(intersection.x - x1) - .abs() - .pow(2) - .plus( - Big(intersection.y - y1) - .pow(2) - .abs(), - ) - .sqrt() - if (size.gt(0)) { - intersectBaseLine.push({ - intersection, - size, - }) - } - } - }) - - const intersectBase = intersectBaseLine.reduce((prev, current) => { - return prev.size < current.size ? prev : current - }, intersectBaseLine[0]) - - if (intersectBase) { - prevEndPoint = { - x: Big(x1) - .plus(Big(nextHipVector.x).times(intersectBase.size.div(2))) - .round(2), - y: Big(y1) - .plus(Big(nextHipVector.y).times(intersectBase.size.div(2))) - .round(2), - } - } - - const intersectRidgeLine = [] - baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection( - { vertex1: { x: x1, y: y1 }, vertex2: prevEndPoint }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if (intersection && !intersection.isIntersectionOutside) { - intersectRidgeLine.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(x1)) - .abs() - .pow(2) - .plus(Big(intersection.y).minus(Big(y1)).pow(2).abs()) - .sqrt(), - }) - } - }) - - const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0]) - - if (intersectRidge) { - prevEndPoint.x = Big(intersectRidge.intersection.x).round(1) - prevEndPoint.y = Big(intersectRidge.intersection.y).round(1) - } - - const xVector = Math.sign(Big(prevEndPoint.x).minus(Big(x1)).neg().toNumber()) - const yVector = Math.sign(Big(prevEndPoint.y).minus(Big(y1)).neg().toNumber()) - /** 지붕 선까지의 곂침에 따른 길이를 파악하기 위한 scale*/ - let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(prevLine.attributes.offset).pow(2)).sqrt() - scale = scale.eq(0) ? Big(1) : scale - - /** scale 만큼 추녀마루를 늘려서 겹치는 포인트를 확인한다. */ - const hipEdge = { - vertex1: { x: Big(x1).plus(scale.times(xVector)).toNumber(), y: Big(y1).plus(scale.times(yVector)).toNumber() }, - vertex2: prevEndPoint, - } - - let intersectPoints = [] - /** 외벽선에서 추녀 마루가 겹치는 경우에 대한 확인*/ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - !intersection.isIntersectionOutside && - Math.sign(prevEndPoint.x - x1) === Math.sign(prevEndPoint.x - intersection.x) && - Math.sign(prevEndPoint.y - y1) === Math.sign(prevEndPoint.y - intersection.y) - ) { - const intersectSize = prevEndPoint.x - .minus(Big(intersection.x)) - .abs() - .pow(2) - .plus(prevEndPoint.y.minus(Big(intersection.y)).pow(2).abs()) - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - }) - } - }) - - intersectPoints = intersectPoints.reduce((prev, current) => { - return prev.size < current.size ? prev : current - }, intersectPoints[0]) - - /** 겹치는 외벽선이 있을때 추녀마루를 외벽선 까지 늘려서 수정*/ - if (intersectPoints && intersectPoints.intersection) { - prevHipLine = drawHipLine( - [intersectPoints.intersection.x, intersectPoints.intersection.y, prevEndPoint.x.toNumber(), prevEndPoint.y.toNumber()], - canvas, - roof, - textMode, - - prevDegree, - currentDegree, - ) - baseHipLines.push({ x1, y1, x2: prevEndPoint.x.toNumber(), y2: prevEndPoint.y.toNumber(), line: prevHipLine }) - } - } - /** 다음라인과의 연결지점에 추녀마루를 그린다. */ - if (baseHipLines.filter((line) => line.x1 === x2 && line.y1 === y2).length === 0 && nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) { - let nextEndPoint = { - x: Big(x2).plus(Big(nextHipVector.x).times(hipLength)).round(2), - y: Big(y2).plus(Big(nextHipVector.y).times(hipLength)).round(2), - } - - const nextEndEdge = { - vertex1: { x: x2, y: y2 }, - vertex2: nextEndPoint, - } - - const intersectBaseLine = [] - baseLines - .filter((line) => line !== currentLine && line !== prevLine && line !== nextLine) - .filter((line) => { - if (currentAngle === 0 || currentAngle === 180) { - return Math.sign(line.y1 - y1) === nextHipVector.y || Math.sign(line.y2 - y1) === nextHipVector.y - } else { - return Math.sign(line.x1 - x1) === nextHipVector.x || Math.sign(line.x2 - x1) === nextHipVector.x - } - }) - .forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(nextEndEdge, lineEdge) - - if (intersection && Math.sign(intersection.x - x2) === nextHipVector.x && Math.sign(intersection.y - y2) === nextHipVector.y) { - const size = Big(intersection.x - x2) - .abs() - .pow(2) - .plus( - Big(intersection.y - y2) - .abs() - .pow(2), - ) - .sqrt() - if (size.gt(0)) { - intersectBaseLine.push({ - intersection, - size, - }) - } - } - }) - - const intersectBase = intersectBaseLine.reduce((prev, current) => { - return prev.size.lt(current.size) ? prev : current - }, intersectBaseLine[0]) - - if (intersectBase) { - const size = Big(getAdjacent(intersectBase.size)) - nextEndPoint = { - x: Big(x2) - .plus(Big(nextHipVector.x).times(size.div(2))) - .round(2), - y: Big(y2) - .plus(Big(nextHipVector.y).times(size.div(2))) - .round(2), - } - } - - const intersectRidgeLine = [] - baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection( - { vertex1: { x: x2, y: y2 }, vertex2: nextEndPoint }, - { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }, - ) - if ( - intersection && - ((line.x1 <= intersection.x && line.x2 >= intersection.x && line.y1 <= intersection.y && line.y2 >= intersection.y) || - (line.x2 <= intersection.x && line.x1 >= intersection.x && line.y2 <= intersection.y && line.y1 >= intersection.y)) - ) { - intersectRidgeLine.push({ - intersection, - distance: Big(intersection.x) - .minus(Big(x1)) - .pow(2) - .plus(Big(intersection.y).minus(Big(y1)).pow(2)) - .sqrt(), - }) - } - }) - - const intersectRidge = intersectRidgeLine.reduce((prev, current) => (prev.distance < current.distance ? prev : current), intersectRidgeLine[0]) - - if (intersectRidge) { - nextEndPoint.x = Big(intersectRidge.intersection.x).round(1) - nextEndPoint.y = Big(intersectRidge.intersection.y).round(1) - } - - const xVector = Math.sign(Big(nextEndPoint.x).minus(Big(x2)).neg().toNumber()) - const yVector = Math.sign(Big(nextEndPoint.y).minus(Big(y2)).neg().toNumber()) - let scale = Big(currentLine.attributes.offset).pow(2).plus(Big(nextLine.attributes.offset).pow(2)).sqrt() - scale = scale.eq(0) ? Big(1) : scale - - const hipEdge = { - vertex1: { x: Big(x2).plus(scale.times(xVector)).toNumber(), y: Big(y2).plus(scale.times(yVector)).toNumber() }, - vertex2: nextEndPoint, - } - - let intersectPoints = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(hipEdge, lineEdge) - if ( - intersection && - !intersection.isIntersectionOutside && - Math.sign(nextEndPoint.x - x2) === Math.sign(nextEndPoint.x - intersection.x) && - Math.sign(nextEndPoint.y - y2) === Math.sign(nextEndPoint.y - intersection.y) - ) { - const intersectSize = nextEndPoint.x - .minus(Big(intersection.x)) - .pow(2) - .plus(nextEndPoint.y.minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - }) - } - }) - - intersectPoints = intersectPoints.reduce((prev, current) => { - return prev.size < current.size ? prev : current - }, intersectPoints[0]) - - if (intersectPoints && intersectPoints.intersection) { - nextHipLine = drawHipLine( - [intersectPoints.intersection.x, intersectPoints.intersection.y, nextEndPoint.x.toNumber(), nextEndPoint.y.toNumber()], - canvas, - roof, - textMode, - - prevDegree, - currentDegree, - ) - baseHipLines.push({ - x1: x2, - y1: y2, - x2: nextEndPoint.x.toNumber(), - y2: nextEndPoint.y.toNumber(), - line: nextHipLine, - }) - } - } - }) - - /** baseHipLine 이 ridge에 붙지 않은 경우 확인 */ - baseHipLines.forEach((hipLine) => { - const ridgeCount = baseRidgeLines.filter( - (ridgeLine) => (hipLine.x2 === ridgeLine.x1 && hipLine.y2 === ridgeLine.y1) || (hipLine.x2 === ridgeLine.x2 && hipLine.y2 === ridgeLine.y2), - ).length - if (ridgeCount === 0) { - const hipXVector = Big(hipLine.x2).minus(hipLine.x1) - const hipYVector = Big(hipLine.y2).minus(hipLine.y1) - const hipSize = hipXVector.abs().pow(2).plus(hipYVector.abs().pow(2)).sqrt() - - const intersectRidgePoints = [] - - const hipLineEdge = { vertex1: { x: hipLine.x1, y: hipLine.y1 }, vertex2: { x: hipLine.x2, y: hipLine.y2 } } - baseRidgeLines.forEach((ridgeLine) => { - const ridgeLineEdge = { - vertex1: { x: ridgeLine.x1, y: ridgeLine.y1 }, - vertex2: { x: ridgeLine.x2, y: ridgeLine.y2 }, - } - const intersection = edgesIntersection(hipLineEdge, ridgeLineEdge) - - if (intersection) { - const intersectXVector = Big(intersection.x).minus(Big(hipLine.x1)) - const intersectYVector = Big(intersection.y).minus(Big(hipLine.y1)) - const intersectSize = intersectXVector.pow(2).plus(intersectYVector.pow(2)).sqrt() - - if (!intersection.isIntersectionOutside) { - intersectRidgePoints.push({ - x: intersection.x, - y: intersection.y, - size: intersectSize, - }) - } else if ( - ((intersection.x === ridgeLine.x1 && intersection.y === ridgeLine.y1) || - (intersection.x === ridgeLine.x2 && intersection.y === ridgeLine.y2)) && - Math.sign(hipXVector.toNumber()) === Math.sign(intersectXVector.toNumber()) && - Math.sign(hipYVector.toNumber()) === Math.sign(intersectYVector.toNumber()) && - intersectSize.gt(0) && - intersectSize.lt(hipSize) - ) { - intersectRidgePoints.push({ - x: intersection.x, - y: intersection.y, - size: intersectSize, - }) - } - } - }) - intersectRidgePoints.sort((prev, current) => prev.size.minus(current.size).toNumber()) - if (intersectRidgePoints.length > 0) { - hipLine.x2 = intersectRidgePoints[0].x - hipLine.y2 = intersectRidgePoints[0].y - hipLine.line.set({ x2: intersectRidgePoints[0].x, y2: intersectRidgePoints[0].y }) - const hipSize = reCalculateSize(hipLine.line) - hipLine.line.attributes.planeSize = hipSize.planeSize - hipLine.line.attributes.actualSize = hipSize.actualSize - hipLine.line.fire('modified') - } - } - }) - - /** 지붕선에 맞닫지 않은 부분을 확인하여 처리 한다.*/ - /** 1. 그려진 마루 중 추녀마루가 부재하는 경우를 판단. 부재는 연결된 라인이 홀수인 경우로 판단한다.*/ - let unFinishedRidge = [] - baseRidgeLines.forEach((current) => { - let checkPoint = [ - { x: current.x1, y: current.y1, line: current, cnt: 0, onRoofLine: false }, - { x: current.x2, y: current.y2, line: current, cnt: 0, onRoofLine: false }, - ] - baseHipLines.forEach((line) => { - if ((line.x1 === current.x1 && line.y1 === current.y1) || (line.x2 === current.x1 && line.y2 === current.y1)) { - checkPoint[0].cnt = checkPoint[0].cnt + 1 - } - if ((line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2)) { - checkPoint[1].cnt = checkPoint[1].cnt + 1 - } - }) - - /** 마루의 포인트가 지붕선 위에 있는경우는 제외 (케라바 등)*/ - roof.lines.forEach((line) => { - if ( - line.x1 === line.x2 && - checkPoint[0].x === line.x1 && - ((line.y1 <= checkPoint[0].y && line.y2 >= checkPoint[0].y) || (line.y1 >= checkPoint[0].y && line.y2 <= checkPoint[0].y)) - ) { - checkPoint[0].onRoofLine = true - } - if ( - line.y1 === line.y2 && - checkPoint[0].y === line.y1 && - ((line.x1 <= checkPoint[0].x && line.x2 >= checkPoint[0].x) || (line.x1 >= checkPoint[0].x && line.x2 <= checkPoint[0].x)) - ) { - checkPoint[0].onRoofLine = true - } - if ( - line.x1 === line.x2 && - checkPoint[1].x === line.x1 && - ((line.y1 <= checkPoint[1].y && line.y2 >= checkPoint[1].y) || (line.y1 >= checkPoint[1].y && line.y2 <= checkPoint[1].y)) - ) { - checkPoint[1].onRoofLine = true - } - if ( - line.y1 === line.y2 && - checkPoint[1].y === line.y1 && - ((line.x1 <= checkPoint[1].x && line.x2 >= checkPoint[1].x) || (line.x1 >= checkPoint[1].x && line.x2 <= checkPoint[1].x)) - ) { - checkPoint[1].onRoofLine = true - } - }) - if ((checkPoint[0].cnt === 0 || checkPoint[0].cnt % 2 !== 0) && !checkPoint[0].onRoofLine) { - unFinishedRidge.push(checkPoint[0]) - } - if ((checkPoint[1].cnt === 0 || checkPoint[1].cnt % 2 !== 0) && !checkPoint[1].onRoofLine) { - unFinishedRidge.push(checkPoint[1]) - } - }) - - /** 2. 그려진 추녀마루 중 완성되지 않은 것을 찾는다. 완성되지 않았다는 것은 연결된 포인트가 홀수인 경우로 판단한다.*/ - const findUnFinishedPoints = (baseHipLines) => { - let unFinishedPoint = [] - baseHipLines.forEach((current) => { - let checkPoint = [ - { x: current.x1, y: current.y1, checked: true, line: current.line }, - { x: current.x2, y: current.y2, checked: true, line: current.line }, - ] - baseLines.forEach((line) => { - if ((line.x1 === current.x1 && line.y1 === current.y1) || (line.x2 === current.x1 && line.y2 === current.y1)) { - checkPoint[0].checked = false - } - if ((line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2)) { - checkPoint[1].checked = false - } - }) - - const samePoints = [] - checkPoint - .filter((point) => point.checked) - .forEach((point) => { - baseHipLines.forEach((line) => { - if (line.x1 === point.x && line.y1 === point.y) { - samePoints.push({ x: point.x, y: point.y, line: line }) - } - if (line.x2 === point.x && line.y2 === point.y) { - samePoints.push({ x: point.x, y: point.y, line: line }) - } - }) - }) - if (samePoints.length > 0 && samePoints.length % 2 !== 0) { - unFinishedPoint.push(samePoints[0]) - } - }) - return unFinishedPoint - } - - let unFinishedPoint = findUnFinishedPoints(baseHipLines) - - /**3. 라인이 부재인 마루의 모자란 라인을 찾는다. 라인은 그려진 추녀마루 중에 완성되지 않은 추녀마루와 확인한다.*/ - /**3-1 라인을 그릴때 각도가 필요하기 때문에 각도를 구한다. 각도는 전체 지부의 각도가 같다면 하나로 처리 */ - let degreeAllLine = [] - baseLines - .filter((line) => eavesType.includes(line.attributes.type)) - .forEach((line) => { - const pitch = line.attributes.pitch - degreeAllLine.push(getDegreeByChon(pitch)) - }) - - let currentDegree, prevDegree - degreeAllLine = [...new Set(degreeAllLine)] - currentDegree = degreeAllLine[0] - if (degreeAllLine.length === 1) { - prevDegree = currentDegree - } else { - prevDegree = degreeAllLine[1] - } - - /** 라인이 부재한 마루에 라인을 찾아 그린다.*/ - unFinishedRidge.forEach((current) => { - let checkPoints = [] - - unFinishedPoint - .filter( - (point) => - point.x !== current.x && - point.y !== current.y && - Big(point.x) - .minus(Big(current.x)) - .abs() - .minus(Big(point.y).minus(Big(current.y)).abs()) - .abs() - .lt(1), - ) - .forEach((point) => { - const pointEdge = { vertex1: { x: point.x, y: point.y }, vertex2: { x: current.x, y: current.y } } - let isIntersection = false - baseLines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(pointEdge, lineEdge) - if (intersection && !intersection.isIntersectionOutside) { - isIntersection = true - } - }) - if (!isIntersection) { - checkPoints.push({ - point, - size: Big(point.x) - .minus(Big(current.x)) - .abs() - .pow(2) - .plus(Big(point.y).minus(Big(current.y)).abs().pow(2)) - .sqrt(), - }) - } - }) - if (checkPoints.length > 0) { - checkPoints.sort((a, b) => a.size - b.size) - const maxCnt = Big(2).minus(Big(current.cnt)).toNumber() - for (let i = 0; i < maxCnt; i++) { - const checkPoint = checkPoints[i] - if (checkPoint) { - let point = [checkPoint.point.x, checkPoint.point.y, current.x, current.y] - let hipBasePoint - - baseHipLines.forEach((line) => { - const checkAngel1 = calculateAngle({ x: point[0], y: point[1] }, { x: point[2], y: point[3] }) - const checkAngel2 = calculateAngle( - { x: line.line.x1, y: line.line.y1 }, - { - x: line.line.x2, - y: line.line.y2, - }, - ) - - const checkPointCnt = checkPoints.filter((point) => point.point.x === checkPoint.point.x && point.point.y === checkPoint.point.y).length - const isConnectLine = - ((line.line.x1 === point[0] && line.line.y1 === point[1]) || (line.line.x2 === point[0] && line.line.y2 === point[1])) && - checkAngel1 === checkAngel2 - const isOverlap = segmentsOverlap(line.line, { x1: point[0], y1: point[1], x2: point[2], y2: point[3] }) - const isSameLine = - (point[0] === line.x2 && point[1] === line.y2 && point[2] === line.x1 && point[3] === line.y1) || - (point[0] === line.x1 && point[1] === line.y1 && point[2] === line.x2 && point[3] === line.y2) - - if (checkPointCnt === 1 && (isConnectLine || isOverlap || isSameLine)) { - /** 겹치는 추녀마루와 하나의 선으로 변경*/ - const mergePoint = [ - { x: point[0], y: point[1] }, - { x: point[2], y: point[3] }, - { x: line.line.x1, y: line.line.y1 }, - { x: line.line.x2, y: line.line.y2 }, - ] - /** baseHipLines도 조정*/ - mergePoint.sort((a, b) => a.x - b.x) - - hipBasePoint = { x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 } - point = [mergePoint[0].x, mergePoint[0].y, mergePoint[3].x, mergePoint[3].y] - const theta = Big( - Math.acos( - Big(line.line.attributes.planeSize).div( - line.line.attributes.actualSize === 0 || line.line.attributes.actualSize === '' || line.line.attributes.actualSize === undefined - ? line.line.attributes.planeSize - : line.line.attributes.actualSize, - ), - ), - ) - .times(180) - .div(Math.PI) - .round(1) - prevDegree = theta.toNumber() - currentDegree = theta.toNumber() - canvas.remove(line.line) - baseHipLines = baseHipLines.filter((baseLine) => baseLine.line !== line.line) - } - }) - - const hipLine = drawHipLine(point, canvas, roof, textMode, prevDegree, currentDegree) - if (hipBasePoint) { - baseHipLines.push({ x1: hipBasePoint.x1, y1: hipBasePoint.y1, x2: point[2], y2: point[3], line: hipLine }) - } else { - baseHipLines.push({ x1: point[0], y1: point[1], x2: point[2], y2: point[3], line: hipLine }) - } - current.cnt = current.cnt + 1 - } - } - } - - /** 라인이 다 그려지지 않은 경우 */ - if (current.cnt % 2 !== 0) { - let basePoints = baseLinePoints - .filter((point) => - Big(point.x) - .minus(Big(current.x)) - .abs() - .minus(Big(point.y).minus(Big(current.y)).abs()) - .abs() - .lt(1), - ) - .filter((point) => { - const pointEdge = { vertex1: { x: current.x, y: current.y }, vertex2: { x: point.x, y: point.y } } - - const intersectPoints = [] - baseLines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(pointEdge, lineEdge) - if (intersection && !intersection.isIntersectionOutside) { - intersectPoints.push(intersection) - } - }) - return ( - !intersectPoints.filter( - (intersect) => !(Big(intersect.x).minus(Big(point.x)).abs().lt(1) && Big(intersect.y).minus(Big(point.y)).abs().lt(1)), - ).length > 0 - ) - }) - - /** hip을 그리기 위한 기본 길이*/ - let hipSize = Big(0) - if (basePoints.length > 0) { - basePoints.sort((a, b) => { - const aSize = Big(a.x) - .minus(Big(current.x)) - .abs() - .pow(2) - .plus(Big(a.y).minus(Big(current.y)).abs().pow(2)) - .sqrt() - const bSize = Big(b.x) - .minus(Big(current.x)) - .abs() - .pow(2) - .plus(Big(b.y).minus(Big(current.y)).abs().pow(2)) - .sqrt() - return aSize - bSize - }) - const baseHips = baseHipLines.filter((line) => line.x1 === basePoints[0].x && line.y1 === basePoints[0].y) - if (baseHips.length > 0) { - hipSize = Big(baseHips[0].line.attributes.planeSize) - } - } - - if (hipSize.eq(0)) { - const ridge = current.line - basePoints = baseHipLines - .filter((line) => (line.x2 === ridge.x1 && line.y2 === ridge.y1) || (line.x2 === ridge.x2 && line.y2 === ridge.y2)) - .filter((line) => baseLines.filter((baseLine) => baseLine.x1 === line.x1 && baseLine.y1 === line.y1).length > 0) - basePoints.sort((a, b) => a.line.attributes.planeSize - b.line.attributes.planeSize) - if (basePoints.length > 0 && basePoints[0].line) { - hipSize = Big(basePoints[0].line.attributes.planeSize) - } else { - hipSize = Big(0) // 또는 기본값 설정 - } - } - hipSize = hipSize.pow(2).div(2).sqrt().round().div(10).toNumber() - - /** 현재 라인을 기준으로 45, 135, 225, 315 방향을 확인하기 위한 좌표, hip은 45도 방향으로만 그린다. */ - const checkEdge45 = { - vertex1: { x: current.x, y: current.y }, - vertex2: { x: current.x + hipSize, y: current.y - hipSize }, - } - const checkEdge135 = { - vertex1: { x: current.x, y: current.y }, - vertex2: { x: current.x + hipSize, y: current.y + hipSize }, - } - const checkEdge225 = { - vertex1: { x: current.x, y: current.y }, - vertex2: { x: current.x - hipSize, y: current.y + hipSize }, - } - const checkEdge315 = { - vertex1: { x: current.x, y: current.y }, - vertex2: { x: current.x - hipSize, y: current.y - hipSize }, - } - - let intersectPoints = [] - let notIntersect45 = true, - notIntersect135 = true, - notIntersect225 = true, - notIntersect315 = true - baseLines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection45 = edgesIntersection(checkEdge45, lineEdge) - const intersection135 = edgesIntersection(checkEdge135, lineEdge) - const intersection225 = edgesIntersection(checkEdge225, lineEdge) - const intersection315 = edgesIntersection(checkEdge315, lineEdge) - - if (intersection45 && !intersection45.isIntersectionOutside) { - intersectPoints.push(intersection45) - notIntersect45 = false - } - if (intersection135 && !intersection135.isIntersectionOutside) { - intersectPoints.push(intersection135) - notIntersect135 = false - } - if (intersection225 && !intersection225.isIntersectionOutside) { - intersectPoints.push(intersection225) - notIntersect225 = false - } - if (intersection315 && !intersection315.isIntersectionOutside) { - intersectPoints.push(intersection315) - notIntersect315 = false - } - }) - /** baseLine과 교차하지 않는 포인트를 추가한다.*/ - if (notIntersect45) { - intersectPoints.push(checkEdge45.vertex2) - } - if (notIntersect135) { - intersectPoints.push(checkEdge135.vertex2) - } - if (notIntersect225) { - intersectPoints.push(checkEdge225.vertex2) - } - if (notIntersect315) { - intersectPoints.push(checkEdge315.vertex2) - } - /** baseLine의 각 좌표와 교차하는 경우로 한정*/ - intersectPoints = intersectPoints.filter((is) => baseLinePoints.filter((point) => point.x === is.x && point.y === is.y).length > 0) - /** baseLine과 교차하는 좌표의 경우 이미 그려진 추녀마루가 존재한다면 제외한다. */ - intersectPoints = intersectPoints.filter((point) => baseHipLines.filter((hip) => hip.x1 === point.x && hip.y1 === point.y).length === 0) - /** 중복제거 */ - intersectPoints = intersectPoints.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y)) - - intersectPoints.forEach((is) => { - const points = [current.x, current.y, is.x, is.y] - /** 추녀마루의 연결점이 처마라인이 아닌경우 return */ - let hasGable = false - baseLines - .filter((line) => (line.x1 === points[2] && line.y1 === points[3]) || (line.x2 === points[2] && line.y2 === points[3])) - .forEach((line) => { - if (!eavesType.includes(line.attributes.type)) { - hasGable = true - } - }) - if (hasGable) return - const pointEdge = { vertex1: { x: points[0], y: points[1] }, vertex2: { x: points[2], y: points[3] } } - const vectorX = Math.sign(Big(points[2]).minus(Big(points[0])).toNumber()) - const vectorY = Math.sign(Big(points[3]).minus(Big(points[1])).toNumber()) - const roofIntersections = [] - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(pointEdge, lineEdge) - if (intersection) { - const vectorIntersectionX = Math.sign(Big(intersection.x).minus(Big(points[0])).toNumber()) - const vectorIntersectionY = Math.sign(Big(intersection.y).minus(Big(points[1])).toNumber()) - if (vectorIntersectionX === vectorX && vectorIntersectionY === vectorY) { - roofIntersections.push({ - x: intersection.x, - y: intersection.y, - size: calcLinePlaneSize({ x1: points[0], y1: points[1], x2: intersection.x, y2: intersection.y }), - }) - } - } - }) - roofIntersections.sort((a, b) => a.size - b.size) - - const hipLine = drawHipLine( - [points[0], points[1], roofIntersections[0].x, roofIntersections[0].y], - canvas, - roof, - textMode, - - prevDegree, - currentDegree, - ) - baseHipLines.push({ x1: points[0], y1: points[1], x2: points[2], y2: points[3], line: hipLine }) - current.cnt = current.cnt + 1 - }) - } - }) - - /** hip이 짝수개가 맞다아있는데 마루와 연결되지 않는 포인트를 찾는다. 그려지지 않은 마루를 찾기 위함.*/ - let noRidgeHipPoints = baseHipLines - .filter((current) => current.x1 !== current.x2 && current.y1 !== current.y2) - .filter((current) => { - const lines = baseHipLines - .filter((line) => line !== current) - .filter((line) => (line.x1 === current.x2 && line.y1 === current.y2) || (line.x2 === current.x2 && line.y2 === current.y2)) - - return lines.length !== 0 && lines.length % 2 !== 0 - }) - .filter( - (current) => - 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, - ) - - noRidgeHipPoints.forEach((current) => { - const orthogonalPoints = noRidgeHipPoints.filter((point) => { - if (point !== current && ((current.x2 === point.x2 && current.y2 !== point.y2) || (current.x2 !== point.x2 && current.y2 === point.y2))) { - return true - } - }) - - /** 직교 하는 포인트가 존재 할때 마루를 그린다. */ - if (orthogonalPoints.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) { - baseRidgeCount = baseRidgeCount + 1 - const points = [current.x2, current.y2, orthogonalPoints[0].x2, orthogonalPoints[0].y2] - const ridgeLine = drawRidgeLine(points, canvas, roof, textMode) - baseRidgeLines.push(ridgeLine) - } - }) - - /** 중복제거*/ - baseRidgeLines.forEach((current) => { - const sameRidge = baseRidgeLines.filter( - (line) => - line !== current && - ((line.x1 === current.x1 && line.y1 === current.y1 && line.x2 === current.x2 && line.y2 === current.y2) || - (line.x1 === current.x2 && line.y1 === current.y2 && line.x2 === current.x1 && line.y2 === current.y1)), - ) - if (sameRidge.length > 0) { - sameRidge.forEach((duplicateLine) => { - const index = baseRidgeLines.indexOf(duplicateLine) - if (index !== -1) { - baseRidgeLines.splice(index, 1) - } - canvas.remove(duplicateLine) - }) - } - }) - - /** 직교 하는 포인트가 없는 경우 남은 포인트 처리 */ - const checkEdgeLines = [] - noRidgeHipPoints.forEach((current) => { - noRidgeHipPoints - .filter((point) => point !== current) - .forEach((point) => { - checkEdgeLines.push( - { vertex1: { x: current.x2, y: current.y2 }, vertex2: { x: current.x2, y: point.y2 } }, - { vertex1: { x: current.x2, y: point.y2 }, vertex2: { x: point.x2, y: point.y2 } }, - { vertex1: { x: point.x2, y: point.y2 }, vertex2: { x: point.x2, y: current.y2 } }, - { vertex1: { x: point.x2, y: current.y2 }, vertex2: { x: current.x2, y: current.y2 } }, - ) - }) - }) - - /** 연결되지 않은 포인트를 찾아서 해당 포인트를 가지고 있는 라인을 찾는다. */ - let unFinishedPoints = [] - let unFinishedLines = [] - let intersectPoints = [] - baseHipLines.forEach((line) => { - if (baseLinePoints.filter((point) => point.x === line.x1 && point.y === line.y1).length === 0) { - unFinishedPoints.push({ x: line.x1, y: line.y1 }) - } - if (baseLinePoints.filter((point) => point.x === line.x2 && point.y === line.y2).length === 0) { - unFinishedPoints.push({ x: line.x2, y: line.y2 }) - } - }) - unFinishedPoints - .filter((point) => unFinishedPoints.filter((p) => p !== point && p.x === point.x && p.y === point.y).length === 0) - .forEach((point) => { - baseHipLines - .filter((line) => (line.x1 === point.x && line.y1 === point.y) || (line.x2 === point.x && line.y2 === point.y)) - .forEach((line) => unFinishedLines.push(line)) - }) - - unFinishedLines.forEach((line) => { - const xVector = Math.sign(Big(line.x2).minus(Big(line.x1))) - const yVector = Math.sign(Big(line.y2).minus(Big(line.y1))) - let lineIntersectPoints = [] - checkEdgeLines.forEach((edge) => { - const intersectEdge = edgesIntersection(edge, { - vertex1: { x: line.x1, y: line.y1 }, - vertex2: { x: line.x2, y: line.y2 }, - }) - if (intersectEdge) { - const isXVector = Math.sign(Big(intersectEdge.x).minus(Big(line.x1))) === xVector - const isYVector = Math.sign(Big(intersectEdge.y).minus(Big(line.y1))) === yVector - if (isXVector && isYVector) { - lineIntersectPoints.push({ - intersection: intersectEdge, - size: Big(intersectEdge.x) - .minus(Big(line.x1)) - .abs() - .pow(2) - .plus(Big(intersectEdge.y).minus(Big(line.y1)).abs().pow(2)) - .sqrt() - .round(1) - .toNumber(), - }) - } - } - }) - - lineIntersectPoints = lineIntersectPoints.filter( - (point, index, self) => index === self.findIndex((p) => p.intersection.x === point.intersection.x && p.intersection.y === point.intersection.y), - ) - lineIntersectPoints.sort((a, b) => a.size - b.size) - if (lineIntersectPoints.length > 0) { - intersectPoints.push({ intersection: lineIntersectPoints[0].intersection, line }) - } - }) - - /** 마루를 그릴수 있는지 찾는다. */ - noRidgeHipPoints.forEach((hipPoint) => { - const ridgePoints = [] - intersectPoints - .filter( - (intersectPoint) => - (intersectPoint.intersection.x !== hipPoint.x2 && intersectPoint.intersection.y === hipPoint.y2) || - (intersectPoint.intersection.x === hipPoint.x2 && intersectPoint.intersection.y !== hipPoint.y2), - ) - .forEach((intersectPoint) => { - ridgePoints.push({ - intersection: intersectPoint, - distance: Big(intersectPoint.intersection.x) - .minus(Big(hipPoint.x2)) - .abs() - .pow(2) - .plus(Big(intersectPoint.intersection.y).minus(Big(hipPoint.y2)).abs().pow(2)) - .sqrt() - .round(1) - .toNumber(), - }) - }) - ridgePoints.sort((a, b) => a.distance - b.distance) - - if (ridgePoints.length > 0 && baseRidgeCount < getMaxRidge(baseLines.length)) { - const intersection = ridgePoints[0].intersection - const isPoint = intersection.intersection - const points = [hipPoint.x2, hipPoint.y2, isPoint.x, isPoint.y] - const ridgeLine = drawRidgeLine(points, canvas, roof, textMode) - baseRidgeCount = baseRidgeCount + 1 - baseRidgeLines.push(ridgeLine) - - let baseHipLine = baseHipLines.filter((line) => line === intersection.line)[0] - baseHipLine.x2 = isPoint.x - baseHipLines.y2 = isPoint.y - /** 보조선 라인 조정*/ - const hipLine = intersection.line.line - /** 평면길이 */ - const planeSize = calcLinePlaneSize({ - x1: hipLine.x1, - y1: hipLine.y1, - x2: isPoint.x, - y2: isPoint.y, - }) - /** 실제길이 */ - const actualSize = - prevDegree === currentDegree - ? calcLineActualSize( - { - x1: hipLine.x1, - y1: hipLine.y1, - x2: isPoint.x, - y2: isPoint.y, - }, - currentDegree, - ) - : 0 - hipLine.set({ - x2: isPoint.x, - y2: isPoint.y, - attributes: { roofId: roof.id, planeSize, actualSize }, - }) - hipLine.fire('modified') - intersectPoints = intersectPoints.filter((isp) => isp !== intersection) - noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint) - } else { - const linePoints = [] - intersectPoints.forEach((intersectPoint) => { - const intersection = intersectPoint.intersection - const xVector = Math.sign(Big(intersection.x).minus(Big(hipPoint.x2))) - const yVector = Math.sign(Big(intersection.y).minus(Big(hipPoint.y2))) - - const checkEdge = { - vertex1: { x: intersection.x, y: intersection.y }, - vertex2: { - x: Big(intersection.x).plus(Big(xVector).times(10)).toNumber(), - y: Big(intersection.y).plus(Big(yVector).times(10)).toNumber(), - }, - } - const intersectX = edgesIntersection( - { - vertex1: { x: hipPoint.x2, y: hipPoint.y2 }, - vertex2: { x: Big(hipPoint.x2).plus(Big(xVector).neg().times(10)).toNumber(), y: hipPoint.y2 }, - }, - checkEdge, - ) - const intersectY = edgesIntersection( - { - vertex1: { x: hipPoint.x2, y: hipPoint.y2 }, - vertex2: { x: hipPoint.x2, y: Big(hipPoint.y2).plus(Big(yVector).neg().times(10)).toNumber() }, - }, - checkEdge, - ) - - let distanceX = Infinity, - distanceY = Infinity - - if (intersectX) { - distanceX = Big(intersectX.x) - .minus(Big(intersection.x)) - .abs() - .pow(2) - .plus(Big(intersectX.y).minus(Big(intersection.y)).abs().pow(2)) - .sqrt() - .round(1) - .toNumber() - } - if (intersectY) { - distanceY = Big(intersectY.x) - .minus(Big(intersection.x)) - .abs() - .pow(2) - .plus(Big(intersectY.y).minus(Big(intersection.y)).abs().pow(2)) - .sqrt() - .round(1) - .toNumber() - } - - if (distanceX < distanceY) { - linePoints.push({ intersection: intersectX, intersectPoint }) - } - if (distanceX > distanceY) { - linePoints.push({ intersection: intersectY, intersectPoint }) - } - }) - - const linePoint = linePoints.reduce((prev, current) => { - const prevDistance = Big(prev.intersection.x) - .minus(Big(hipPoint.x2)) - .abs() - .pow(2) - .plus(Big(prev.intersection.y).minus(Big(hipPoint.y2)).abs().pow(2)) - .sqrt() - const currentDistance = Big(current.intersection.x) - .minus(Big(hipPoint.x2)) - .abs() - .pow(2) - .plus(Big(current.intersection.y).minus(Big(hipPoint.y2)).abs().pow(2)) - .sqrt() - if (prevDistance < currentDistance) { - return prev - } else { - return current - } - }, linePoints[0]) - - if (!linePoint) return - const hipStartPoint = [hipPoint.x2, hipPoint.y2, linePoint.intersection.x, linePoint.intersection.y] - /** 직선인 경우 마루를 그린다.*/ - if ( - ((hipStartPoint[0] === hipStartPoint[2] && hipStartPoint[1] !== hipStartPoint[3]) || - (hipStartPoint[0] !== hipStartPoint[2] && hipStartPoint[1] === hipStartPoint[3])) && - baseRidgeCount < getMaxRidge(baseLines.length) - ) { - const ridgeLine = drawRidgeLine(hipStartPoint, canvas, roof, textMode) - baseRidgeCount = baseRidgeCount + 1 - baseRidgeLines.push(ridgeLine) - noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint) - } - /** 대각선인경우 hip을 그린다. */ - if ( - Big(hipStartPoint[0]) - .minus(Big(hipStartPoint[2])) - .abs() - .minus(Big(hipStartPoint[1]).minus(Big(hipStartPoint[3])).abs()) - .abs() - .lt(1) - ) { - // console.log('힙1') - const hipLine = drawHipLine(hipStartPoint, canvas, roof, textMode, prevDegree, currentDegree) - baseHipLines.push({ - x1: hipStartPoint[0], - y1: hipStartPoint[1], - x2: hipStartPoint[2], - y2: hipStartPoint[3], - line: hipLine, - }) - noRidgeHipPoints = noRidgeHipPoints.filter((hip) => hip !== hipPoint) - } - - const isStartPoint = [ - linePoint.intersection.x, - linePoint.intersection.y, - linePoint.intersectPoint.intersection.x, - linePoint.intersectPoint.intersection.y, - ] - if ( - ((isStartPoint[0] === isStartPoint[2] && isStartPoint[1] !== isStartPoint[3]) || - (isStartPoint[0] !== isStartPoint[2] && isStartPoint[1] === isStartPoint[3])) && - baseRidgeCount < getMaxRidge(baseLines.length) - ) { - const ridgeLine = drawRidgeLine(isStartPoint, canvas, roof, textMode) - baseRidgeCount = baseRidgeCount + 1 - baseRidgeLines.push(ridgeLine) - } - if ( - Big(isStartPoint[0]) - .minus(Big(isStartPoint[2])) - .abs() - .minus(Big(isStartPoint[1]).minus(Big(isStartPoint[3])).abs()) - .abs() - .lt(1) - ) { - const hipLine = drawHipLine(isStartPoint, canvas, roof, textMode, prevDegree, currentDegree) - baseHipLines.push({ - x1: isStartPoint[0], - y1: isStartPoint[1], - x2: isStartPoint[2], - y2: isStartPoint[3], - line: hipLine, - }) - } - } - }) - - const ridgeAllPoints = [] - baseRidgeLines.forEach((line) => ridgeAllPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 })) - baseGableRidgeLines.forEach((line) => ridgeAllPoints.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 })) - - /** hip 중에 지붕의 라인과 만나지 않은 선을 확인.*/ - baseHipLines - .filter( - (hip) => baseLinePoints.filter((point) => (point.x === hip.x1 && point.y === hip.y1) || (point.x === hip.x2 && point.y === hip.y2)).length > 0, - ) - .filter((hip) => { - const hipEdge = { vertex1: { x: hip.line.x1, y: hip.line.y1 }, vertex2: { x: hip.line.x2, y: hip.line.y2 } } - const hipVectorX = Math.sign(Big(hip.x1).minus(Big(hip.x2))) - const hipVectorY = Math.sign(Big(hip.y1).minus(Big(hip.y2))) - let isIntersect = false - roof.lines.forEach((line) => { - const edge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(edge, hipEdge) - if (intersection && !intersection.isIntersectionOutside) { - const isVectorX = Math.sign(Big(intersection.x).minus(Big(hip.x2))) - const isVectorY = Math.sign(Big(intersection.y).minus(Big(hip.y2))) - if (isVectorX === hipVectorX && isVectorY === hipVectorY) { - isIntersect = true - } - } - }) - return !isIntersect - }) - .forEach((hip) => { - const hipLine = hip.line - if (hipLine) { - const hipVectorX = Big(hipLine.x2).plus(Big(hipLine.attributes.planeSize).times(Big(hipLine.x1).minus(Big(hipLine.x2)).neg().s)) - const hipVectorY = Big(hipLine.y2).plus(Big(hipLine.attributes.planeSize).times(Big(hipLine.y1).minus(Big(hipLine.y2)).neg().s)) - const overlapLineX = roof.lines - .filter((roofLine) => roofLine.x1 !== roofLine.x2 && roofLine.y1 === hipLine.y2 && roofLine.y2 === hipLine.y2) - .filter((roofLine) => { - const minX = Math.min(roofLine.x1, roofLine.x2, hipLine.x2) - const maxX = Math.max(roofLine.x1, roofLine.x2, hipLine.x2) - const checkLineEdge = { vertex1: { x: minX, y: hipLine.y2 }, vertex2: { x: maxX, y: hipLine.y2 } } - let isIntersect = false - baseHipLines.forEach((baseHipLine) => { - const edge = { - vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 }, - vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 }, - } - const intersection = edgesIntersection(edge, checkLineEdge) - if (intersection && !intersection.isIntersectionOutside) { - const isVectorX = Math.sign(Big(intersection.x).minus(Big(baseHipLine.x2))) - const isVectorY = Math.sign(Big(intersection.y).minus(Big(baseHipLine.y2))) - if (isVectorX === hipVectorX && isVectorY === hipVectorY) { - isIntersect = true - } - } - }) - baseRidgeLines.forEach((baseRidgeLine) => { - const edge = { - vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 }, - vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 }, - } - const intersection = edgesIntersection(edge, checkLineEdge) - if (intersection && !intersection.isIntersectionOutside) { - const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2))) - const isVectorY = Math.sign(Big(intersection.y).minus(Big(hipLine.y2))) - if (isVectorX === hipVectorX && isVectorY === hipVectorY) { - isIntersect = true - } - } - }) - return !isIntersect - }) - const overlapLineY = roof.lines - .filter((roofLine) => roofLine.y1 !== roofLine.y2 && roofLine.x1 === hipLine.x2 && roofLine.x2 === hipLine.x2) - .filter((roofLine) => { - const minY = Math.min(roofLine.y1, roofLine.y2, hipLine.y2) - const maxY = Math.max(roofLine.y1, roofLine.y2, hipLine.y2) - const checkLineEdge = { vertex1: { x: hipLine.x2, y: minY }, vertex2: { x: hipLine.x2, y: maxY } } - let isIntersect = false - baseHipLines.forEach((baseHipLine) => { - const edge = { - vertex1: { x: baseHipLine.x1, y: baseHipLine.y1 }, - vertex2: { x: baseHipLine.x2, y: baseHipLine.y2 }, - } - const intersection = edgesIntersection(edge, checkLineEdge) - if (intersection && !intersection.isIntersectionOutside) { - const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2))) - const isVectorY = Math.sign(Big(intersection.y).minus(Big(hipLine.y2))) - if (isVectorX === hipVectorX && isVectorY === hipVectorY) { - isIntersect = true - } - } - }) - baseRidgeLines.forEach((baseRidgeLine) => { - const edge = { - vertex1: { x: baseRidgeLine.x1, y: baseRidgeLine.y1 }, - vertex2: { x: baseRidgeLine.x2, y: baseRidgeLine.y2 }, - } - const intersection = edgesIntersection(edge, checkLineEdge) - if (intersection && !intersection.isIntersectionOutside) { - const isVectorX = Math.sign(Big(intersection.x).minus(Big(hipLine.x2))) - const isVectorY = Math.sign(Big(intersection.y).minus(Big(hipLine.y2))) - if (isVectorX === hipVectorX && isVectorY === hipVectorY) { - isIntersect = true - } - } - }) - return !isIntersect - }) - - overlapLineX.reduce((prev, current) => { - const prevDistance = Big(prev.x1) - .minus(Big(hipLine.x2)) - .abs() - .lt(Big(prev.x2).minus(Big(hipLine.x2)).abs()) - ? Big(prev.x1).minus(Big(hipLine.x2)).abs() - : Big(prev.x2).minus(Big(hipLine.x2)).abs() - const currentDistance = Big(current.x1) - .minus(Big(hipLine.x2)) - .abs() - .lt(Big(current.x2).minus(Big(hipLine.x2)).abs()) - ? Big(current.x1).minus(Big(hipLine.x2)).abs() - : Big(current.x2).minus(Big(hipLine.x2)).abs() - - return prevDistance.lt(currentDistance) ? prev : current - }, overlapLineX[0]) - - overlapLineY.reduce((prev, current) => { - const prevDistance = Big(prev.y1) - .minus(Big(hipLine.y2)) - .abs() - .lt(Big(prev.y2).minus(Big(hipLine.y2)).abs()) - ? Big(prev.y1).minus(Big(hipLine.y2)).abs() - : Big(prev.y2).minus(Big(hipLine.y2)).abs() - const currentDistance = Big(current.y1) - .minus(Big(hipLine.y2)) - .abs() - .lt(Big(current.y2).minus(Big(hipLine.y2)).abs()) - ? Big(current.y1).minus(Big(hipLine.y2)).abs() - : Big(current.y2).minus(Big(hipLine.y2)).abs() - return prevDistance.lt(currentDistance) ? prev : current - }, overlapLineY[0]) - - if (overlapLineX.length > 0) { - const overlapLine = overlapLineX[0] - const maxX = Math.max(overlapLine.x1, overlapLine.x2) - const point = [hipLine.x2, hipLine.y2, maxX, hipLine.y2] - const addLine = drawHipLine(point, canvas, roof, textMode, prevDegree, currentDegree) - baseHipLines.push({ x1: point[0], y1: point[1], x2: point[2], y2: point[3], line: addLine }) - } - if (overlapLineY.length > 0) { - const overlapLine = overlapLineY[0] - const maxY = Math.max(overlapLine.y1, overlapLine.y2) - const point = [hipLine.x2, hipLine.y2, hipLine.x2, maxY] - const addLine = drawHipLine(point, canvas, roof, textMode, prevDegree, currentDegree) - baseHipLines.push({ x1: point[0], y1: point[1], x2: point[2], y2: point[3], line: addLine }) - } - } - - const modifiedBaseLine = baseLines.filter((line) => (hip.x2 === line.x1 && hip.y2 === line.y1) || (hip.x2 === line.x2 && hip.y2 === line.y2)) - if (modifiedBaseLine.length === 0) return - const verticalLine = modifiedBaseLine.find( - (line) => - (hip.x2 === line.attributes.originPoint.x1 && hip.x2 === line.attributes.originPoint.x2) || - (hip.y2 === line.attributes.originPoint.y1 && hip.y2 === line.attributes.originPoint.y2), - ) - const horizonLine = modifiedBaseLine.find((line) => line !== verticalLine) - - const horizonRoof = roof.lines.find((line) => { - const originPoint = horizonLine.attributes.originPoint - if (originPoint.y1 === originPoint.y2) { - return ( - line.y1 === line.y2 && - Math.sign(originPoint.x1 - originPoint.x2) === Math.sign(line.x1 - line.x2) && - Big(originPoint.y1).minus(Big(line.y1)).abs().minus(horizonLine.attributes.offset).abs().lt(1) - ) - } else { - return ( - line.x1 === line.x2 && - Math.sign(originPoint.y1 - originPoint.y2) === Math.sign(line.y1 - line.y2) && - Big(originPoint.x1).minus(Big(line.x1)).abs().minus(horizonLine.attributes.offset).abs().lt(1) - ) - } - }) - - if (horizonRoof) { - let horizonPoint - if (horizonRoof.y1 === horizonRoof.y2) { - const minX = Math.min(horizonRoof.x1, horizonRoof.x2, horizonLine.attributes.originPoint.x1, horizonLine.attributes.originPoint.x2) - const maxX = Math.max(horizonRoof.x1, horizonRoof.x2, horizonLine.attributes.originPoint.x1, horizonLine.attributes.originPoint.x2) - horizonPoint = [minX, horizonRoof.y1, maxX, horizonRoof.y1] - } else { - const minY = Math.min(horizonRoof.y1, horizonRoof.y2, horizonLine.attributes.originPoint.y1, horizonLine.attributes.originPoint.y2) - const maxY = Math.max(horizonRoof.y1, horizonRoof.y2, horizonLine.attributes.originPoint.y1, horizonLine.attributes.originPoint.y2) - horizonPoint = [horizonRoof.x1, minY, horizonRoof.x1, maxY] - } - let addLine - const alreadyHorizonLines = baseHipLines.find( - (hipLine) => - hipLine.x1 === horizonPoint[0] && hipLine.y1 === horizonPoint[1] && hipLine.x2 === horizonPoint[2] && hipLine.y2 === horizonPoint[3], - ) - if (!alreadyHorizonLines) { - addLine = drawHipLine(horizonPoint, canvas, roof, textMode, prevDegree, currentDegree) - baseHipLines.push({ - x1: horizonPoint[0], - y1: horizonPoint[1], - x2: horizonPoint[2], - y2: horizonPoint[3], - line: addLine, - }) - } else { - addLine = alreadyHorizonLines - } - - let verticalPoint - if (addLine.y1 === addLine.y2) { - verticalPoint = [hip.x2, hip.y2, hip.x2, addLine.y1] - } else { - verticalPoint = [hip.x2, hip.y2, addLine.x1, hip.y2] - } - const alreadyVerticalLine = baseHipLines.find( - (hipLine) => - hipLine.x1 === verticalPoint[0] && hipLine.y1 === verticalPoint[1] && hipLine.x2 === verticalPoint[2] && hipLine.y2 === verticalPoint[3], - ) - if (!alreadyVerticalLine) { - addLine = drawHipLine(verticalPoint, canvas, roof, textMode, prevDegree, currentDegree) - baseHipLines.push({ - x1: verticalPoint[0], - y1: verticalPoint[1], - x2: verticalPoint[2], - y2: verticalPoint[3], - line: addLine, - }) - } - } - }) - - ridgeAllPoints.forEach((current) => { - ridgeAllPoints - .filter((point) => point !== current) - .forEach((point) => { - let checkRidgeLine, checkHipLine - /** 직선인 경우 마루 확인*/ - if ( - baseRidgeCount < getMaxRidge(baseLines.length) && - ((point.x === current.x && point.y !== current.y) || (point.x !== current.x && point.y === current.y)) - ) { - checkRidgeLine = { x1: current.x, y1: current.y, x2: point.x, y2: point.y } - } - /** 대각선인 경우 hip 확인*/ - const hipX = Big(current.x).minus(Big(point.x)).abs() - const hipY = Big(current.y).minus(Big(point.y)).abs() - if (hipX.eq(hipY) && hipX.gt(0) && hipY.gt(0)) { - checkHipLine = { x1: current.x, y1: current.y, x2: point.x, y2: point.y } - } - - if (checkRidgeLine) { - const ridgePoints = [checkRidgeLine.x1, checkRidgeLine.y1, checkRidgeLine.x2, checkRidgeLine.y2] - - let baseIntersection = false - const ridgeInterSection = [] - const ridgeEdge = { - vertex1: { x: ridgePoints[0], y: ridgePoints[1] }, - vertex2: { x: ridgePoints[2], y: ridgePoints[3] }, - } - baseLines.forEach((line) => { - const intersection = edgesIntersection(ridgeEdge, { - vertex1: { x: line.x1, y: line.y1 }, - vertex2: { x: line.x2, y: line.y2 }, - }) - if (intersection && !intersection.isIntersectionOutside) { - ridgeInterSection.push(intersection) - } - }) - baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection(ridgeEdge, { - vertex1: { x: line.x1, y: line.y1 }, - vertex2: { x: line.x2, y: line.y2 }, - }) - if (intersection && !intersection.isIntersectionOutside) { - ridgeInterSection.push(intersection) - } - }) - baseHipLines.forEach((line) => { - const intersection = edgesIntersection(ridgeEdge, { - vertex1: { x: line.x1, y: line.y1 }, - vertex2: { x: line.x2, y: line.y2 }, - }) - if (intersection && !intersection.isIntersectionOutside) { - ridgeInterSection.push(intersection) - } - }) - const otherRidgeInterSection = ridgeInterSection.filter( - (intersection) => - !( - (intersection.x === ridgePoints[0] && intersection.y === ridgePoints[1]) || - (intersection.x === ridgePoints[2] && intersection.y === ridgePoints[3]) - ), - ) - const alreadyRidges = baseRidgeLines.filter( - (line) => - (line.x1 === ridgePoints[0] && line.y1 === ridgePoints[1] && line.x2 === ridgePoints[2] && line.y2 === ridgePoints[3]) || - (line.x1 === ridgePoints[2] && line.y1 === ridgePoints[3] && line.x2 === ridgePoints[0] && line.y2 === ridgePoints[1]), - ) - - if ( - !baseIntersection && - alreadyRidges.length === 0 && - otherRidgeInterSection.length === 0 && - baseRidgeCount < getMaxRidge(baseLines.length) - ) { - baseRidgeCount = baseRidgeCount + 1 - const ridgeLine = drawRidgeLine(ridgePoints, canvas, roof, textMode) - baseRidgeLines.push(ridgeLine) - } - } - if (checkHipLine) { - const hipPoints = [checkHipLine.x1, checkHipLine.y1, checkHipLine.x2, checkHipLine.y2] - - let baseIntersection = false - let hipInterSection = [] - const hipEdge = { - vertex1: { x: hipPoints[0], y: hipPoints[1] }, - vertex2: { x: hipPoints[2], y: hipPoints[3] }, - } - baseLines.forEach((line) => { - const intersection = edgesIntersection(hipEdge, { - vertex1: { x: line.x1, y: line.y1 }, - vertex2: { x: line.x2, y: line.y2 }, - }) - if (intersection && !intersection.isIntersectionOutside && eavesType.includes(line.attributes.type)) { - baseIntersection = true - } - }) - baseRidgeLines.forEach((line) => { - const intersection = edgesIntersection(hipEdge, { - vertex1: { x: line.x1, y: line.y1 }, - vertex2: { x: line.x2, y: line.y2 }, - }) - if (intersection && !intersection.isIntersectionOutside) { - hipInterSection.push(intersection) - } - }) - baseHipLines.forEach((line) => { - const intersection = edgesIntersection(hipEdge, { - vertex1: { x: line.x1, y: line.y1 }, - vertex2: { x: line.x2, y: line.y2 }, - }) - if (intersection && !intersection.isIntersectionOutside) { - hipInterSection.push(intersection) - } - }) - const otherHipInterSection = hipInterSection.filter( - (intersection) => - !( - (intersection.x === hipPoints[0] && intersection.y === hipPoints[1]) || - (intersection.x === hipPoints[2] && intersection.y === hipPoints[3]) - ), - ) - const alreadyHips = baseHipLines.filter( - (line) => - (line.x1 === hipPoints[0] && line.y1 === hipPoints[1] && line.x2 === hipPoints[2] && line.y2 === hipPoints[3]) || - (line.x1 === hipPoints[2] && line.y1 === hipPoints[3] && line.x2 === hipPoints[0] && line.y2 === hipPoints[1]), - ) - - if (!baseIntersection && alreadyHips.length === 0 && otherHipInterSection.length === 0) { - const hipLine = drawHipLine(hipPoints, canvas, roof, textMode, prevDegree, currentDegree) - baseHipLines.push({ x1: hipPoints[0], y1: hipPoints[1], x2: hipPoints[2], y2: hipPoints[3], line: hipLine }) - } - } - }) - }) - - const innerLines = [...baseRidgeLines, ...baseGableRidgeLines, ...baseGableLines, ...baseHipLines.map((line) => line.line)] - const uniqueInnerLines = [] - - innerLines.forEach((currentLine) => { - if (currentLine.length === 0) { - canvas.remove(currentLine) - } else { - const sameLines = uniqueInnerLines.filter( - (line) => - line !== currentLine && - ((line.x1 === currentLine.x1 && line.y1 === currentLine.y1 && line.x2 === currentLine.x2 && line.y2 === currentLine.y2) || - (line.x1 === currentLine.x2 && line.y1 === currentLine.y2 && line.x2 === currentLine.x1 && line.y2 === currentLine.y1)), - ) - - if (sameLines.length === 0) { - uniqueInnerLines.push(currentLine) - } else { - canvas.remove(currentLine) - } - } - }) - canvas.renderAll() - roof.innerLines = uniqueInnerLines - - roof.innerLines.forEach((line) => { - line.bringToFront() - }) - /** 확인용 라인 제거 */ - canvas - .getObjects() - .filter((obj) => obj.name === 'checkCircle' || obj.name === 'checkLine') - .forEach((obj) => canvas.remove(obj)) - canvas.renderAll() - - /* - drawCenterLine(roof, canvas, textMode) - */ -} /** * 추녀 마루를 그린다. @@ -12887,7 +5505,6 @@ const drawHipLine = (points, canvas, roof, textMode, prevDegree, currentDegree) textMode: textMode, attributes: { roofId: roof.id, - // currentRoofId: currentRoof.id, planeSize: calcLinePlaneSize({ x1: points[0], y1: points[1], @@ -12915,52 +5532,6 @@ const drawHipLine = (points, canvas, roof, textMode, prevDegree, currentDegree) return hip } -/** - * 라인의 흐름 방향에서 마주치는 지붕선의 포인트를 찾는다. - * @param roof - * @param baseLine - * @param endPoint - * @returns {*} - */ -const findRoofIntersection = (roof, baseLine, endPoint) => { - let intersectPoints = [] - const { x1, y1, x2, y2 } = baseLine - - const baseEdge = { - vertex1: { x: x1, y: y1 }, - vertex2: { x: x2, y: y2 }, - } - - /** 외벽선에서 라인 겹치는 경우에 대한 확인*/ - roof.lines.forEach((line) => { - const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } } - const intersection = edgesIntersection(baseEdge, lineEdge) - if ( - intersection && - !intersection.isIntersectionOutside && - Math.sign(endPoint.x - baseLine.x1) === Math.sign(endPoint.x - intersection.x) && - Math.sign(endPoint.y - baseLine.y1) === Math.sign(endPoint.y - intersection.y) - ) { - const intersectSize = endPoint.x - .minus(Big(intersection.x)) - .pow(2) - .plus(endPoint.y.minus(Big(intersection.y)).pow(2)) - .abs() - .sqrt() - .toNumber() - - intersectPoints.push({ - intersection, - size: intersectSize, - }) - } - }) - - return intersectPoints.reduce((prev, current) => { - return prev.size < current.size ? prev : current - }, intersectPoints[0]) -} - /** * 마루를 그린다. * @param points @@ -13081,35 +5652,6 @@ const getHalfAngleVector = (line1, line2) => { return normalizeVector(summedVector) } -/** - * 두 선분이 겹치는지 확인 - * @param line1 - * @param line2 - * @returns {boolean} - */ -export const segmentsOverlap = (line1, line2) => { - if (line1.y1 === line1.y2 && line2.y1 === line2.y2 && line1.y1 === line2.y1) { - if ((line1.x1 <= line2.x1 && line1.x2 >= line2.x1) || (line1.x1 <= line2.x2 && line1.x2 >= line2.x2)) { - return true - } - } - if (line1.x1 === line1.x2 && line2.x1 === line2.x2 && line1.x1 === line2.x1) { - if ((line1.y1 <= line2.y1 && line1.y2 >= line2.y1) || (line1.y1 <= line2.y2 && line1.y2 >= line2.y2)) { - return true - } - } - return false -} - -/** - * 최대 생성 마루 갯수 - * @param length - * @returns {number} - */ -const getMaxRidge = (length) => { - return (length - 4) / 2 + 1 -} - /** * 지붕 모양 을 변경한다. * @param polygon @@ -13169,7 +5711,7 @@ const reDrawPolygon = (polygon, canvas) => { * @param canvas * @param textMode */ -const drawCenterLine = (roof, canvas, textMode) => { +/*const drawCenterLine = (roof, canvas, textMode) => { //현재 지붕의 centerLine을 다 지운다. canvas .getObjects() @@ -13390,7 +5932,7 @@ const drawCenterLine = (roof, canvas, textMode) => { } } }) -} +}*/ function arePointsEqual(point1, point2) { return Math.abs(point1.x - point2.x) <= 1 && Math.abs(point1.y - point2.y) <= 1 @@ -13406,7 +5948,7 @@ export const toGeoJSON = (pointsArray) => { return coordinates } -export const inPolygon = (polygonPoints, rectPoints) => { +/*export const inPolygon = (polygonPoints, rectPoints) => { const polygonCoordinates = toGeoJSON(polygonPoints) const rectCoordinates = toGeoJSON(rectPoints) @@ -13426,7 +5968,7 @@ export const inPolygon = (polygonPoints, rectPoints) => { }) return allPointsInsidePolygon && noPolygonPointsInsideRect -} +}*/ /** * 포인트를 기준으로 선의 길이를 구한다. 선의 길이는 10을 곱하여 사용한다. @@ -13466,7 +6008,7 @@ export const createLinesFromPolygon = (points) => { } /** 포인트 정렬 가장왼쪽, 가장위 부터 */ -const getSortedPoint = (points, lines) => { +/*const getSortedPoint = (points, lines) => { const startPoint = points .filter((point) => point.x === Math.min(...points.map((point) => point.x))) .reduce((prev, curr) => { @@ -13541,8 +6083,9 @@ const getSortedPoint = (points, lines) => { } } return sortedPoints -} +}*/ +/* const reCalculateSize = (line) => { const oldPlaneSize = line.attributes.planeSize const oldActualSize = line.attributes.actualSize @@ -13571,6 +6114,7 @@ const reCalculateSize = (line) => { ) return { planeSize, actualSize } } +*/ /** * 직교 다각형(축에 평행한 변들로만 구성된 다각형)의 점들을 시계방향으로 정렬 From faa619d12459a9f72b022f9513d96ed09d359874 Mon Sep 17 00:00:00 2001 From: ysCha Date: Mon, 5 Jan 2026 18:59:43 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EB=A9=94=EC=9D=B8=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=83=88=EB=A1=9C=EA=B3=A0=EC=B9=A8=20chagePasswordPopOpen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Main.jsx | 37 ++++++++++++++++++----- src/components/main/ChangePasswordPop.jsx | 2 +- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/components/Main.jsx b/src/components/Main.jsx index 9afadca7..ad7dd3d3 100644 --- a/src/components/Main.jsx +++ b/src/components/Main.jsx @@ -18,8 +18,9 @@ import Config from '@/config/config.export' export default function MainPage() { const [sessionState, setSessionState] = useRecoilState(sessionStore) - const [chagePasswordPopOpen, setChagePasswordPopOpen] = useState(false) - + const [changePasswordPopOpen, setChangePasswordPopOpen] = useState(false) + // 데이터 확인 완료 여부 상태 추가 + const [isSessionLoaded, setIsSessionLoaded] = useState(false) const router = useRouter() const { getMessage } = useMessage() @@ -52,6 +53,14 @@ export default function MainPage() { } } + useEffect(() => { + if (isObjectNotEmpty(sessionState)) { + if (sessionState?.pwdInitYn !== 'Y') { + setChangePasswordPopOpen(true) + } + } + }, [sessionState]) + // 라디오 변경 이벤트 const handleOnChangeRadio = (e) => { setSearchRadioType(e.target.value) @@ -77,7 +86,7 @@ export default function MainPage() { useEffect(() => { if (isObjectNotEmpty(sessionState)) { if (sessionState?.pwdInitYn !== 'Y') { - setChagePasswordPopOpen(true) + setChangePasswordPopOpen(true) } } }, [sessionState]) @@ -86,10 +95,25 @@ export default function MainPage() { const [open, setOpen] = useState(false) const [modalNoticeNo, setModalNoticeNo] = useState('') + useEffect(() => { + if (isObjectNotEmpty(sessionState)) { + if (sessionState?.pwdInitYn !== 'Y') { + setChangePasswordPopOpen(true) + } else { + // pwdInitYn이 'Y'라면 팝업을 닫음 (false) + setChangePasswordPopOpen(false) + } + } + }, [sessionState]) + + //if (!isSessionLoaded) return null + return ( <> {open && } - {(!chagePasswordPopOpen && ( + {changePasswordPopOpen ? ( + + ) : ( <>
@@ -131,11 +155,8 @@ export default function MainPage() {
- )) || ( - <> - - )} + ) } diff --git a/src/components/main/ChangePasswordPop.jsx b/src/components/main/ChangePasswordPop.jsx index 54075153..efae3bb5 100644 --- a/src/components/main/ChangePasswordPop.jsx +++ b/src/components/main/ChangePasswordPop.jsx @@ -114,7 +114,7 @@ export default function ChangePasswordPop(props) { const result = { ...sessionState, pwdInitYn: 'Y' } setSession(result) setSessionState(result) - props.setChagePasswordPopOpen(false) + props.setChangePasswordPopOpen(false) await login() }, })