From 4101a3ede99c5b97fcfe49058a7af15183ef09d5 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Fri, 7 Feb 2025 21:37:34 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EC=9E=91=EC=97=85=EC=A4=91=20dev=EC=99=80?= =?UTF-8?q?=20merge=20=EA=B8=88=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/components/fabric/QLine.js | 129 +- src/components/fabric/QPolygon.js | 24 +- src/hooks/roofcover/useEavesGableEdit.js | 5 +- src/hooks/roofcover/useOuterLineWall.js | 29 +- src/hooks/roofcover/usePropertiesSetting.js | 6 +- src/hooks/roofcover/useRoofShapeSetting.js | 5 +- src/hooks/useMode.js | 52 +- src/hooks/useMouse.js | 15 +- src/util/canvas-util.js | 7 +- src/util/qpolygon-utils.js | 1185 ++++++++++++------- 11 files changed, 960 insertions(+), 498 deletions(-) diff --git a/package.json b/package.json index 9321f939..c2b9e6cf 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@nextui-org/react": "^2.4.2", "ag-grid-react": "^32.0.2", "axios": "^1.7.8", + "big.js": "^6.2.2", "chart.js": "^4.4.6", "dayjs": "^1.11.13", "fabric": "^5.3.0", diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 17892dfe..7fc1afc1 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -28,6 +28,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { this.idx = options.idx ?? 0 this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) + this.textMode = options.textMode ?? 'plane' // plane:복시도, actual:실측, none:표시안함 if (length !== 0) { this.length = length } else { @@ -60,70 +61,84 @@ export const QLine = fabric.util.createClass(fabric.Line, { }, setLength() { - const scaleX = this.scaleX - const scaleY = this.scaleY - const x1 = this.left - const y1 = this.top - const x2 = this.left + this.width * scaleX - const y2 = this.top + this.height * scaleY - const dx = x2 - x1 - const dy = y2 - y1 - this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) + if (this.attributes?.actualSize !== undefined && this.attributes?.planeSize !== undefined) { + if (this.textMode === 'plane') { + this.length = this.attributes.planeSize / 10 + } else if (this.textMode === 'actual') { + this.length = this.attributes.actualSize / 10 + } + } else { + const scaleX = this.scaleX + const scaleY = this.scaleY + const x1 = this.left + const y1 = this.top + const x2 = this.left + this.width * scaleX + const y2 = this.top + this.height * scaleY + const dx = x2 - x1 + const dy = y2 - y1 + this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) + } }, addLengthText() { const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id) - this.setLength() - const scaleX = this.scaleX - const scaleY = this.scaleY - const x1 = this.left - const y1 = this.top - const x2 = this.left + this.width * scaleX - const y2 = this.top + this.height * scaleY + if (this.textMode === 'none') { + if (thisText) { + this.canvas.remove(thisText) + } + } else { + this.setLength() + const scaleX = this.scaleX + const scaleY = this.scaleY + const x1 = this.left + const y1 = this.top + const x2 = this.left + this.width * scaleX + const y2 = this.top + this.height * scaleY - if (thisText) { - thisText.set({ text: this.getLength().toString(), left: (x1 + x2) / 2, top: (y1 + y2) / 2 }) - this.text = thisText - return + if (thisText) { + thisText.set({ text: this.getLength().toString(), left: (x1 + x2) / 2, top: (y1 + y2) / 2 }) + this.text = thisText + return + } + let left, top + if (this.direction === 'left' || this.direction === 'right') { + left = (x1 + x2) / 2 + top = (y1 + y2) / 2 + 10 + } else if (this.direction === 'top' || this.direction === 'bottom') { + left = (x1 + x2) / 2 + 10 + top = (y1 + y2) / 2 + } + + const minX = this.left + const maxX = this.left + this.width + const minY = this.top + const maxY = this.top + this.length + const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI + + const text = new fabric.Textbox(this.getLength().toString(), { + left: left, + top: top, + fontSize: this.fontSize, + minX, + maxX, + minY, + maxY, + parentDirection: this.direction, + parentDegree: degree, + parentId: this.id, + editable: false, + selectable: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + parent: this, + name: 'lengthText', + }) + + this.text = text + this.canvas.add(text) } - let left, top - if (this.direction === 'left' || this.direction === 'right') { - left = (x1 + x2) / 2 - top = (y1 + y2) / 2 + 10 - } else if (this.direction === 'top' || this.direction === 'bottom') { - left = (x1 + x2) / 2 + 10 - top = (y1 + y2) / 2 - } - - const minX = this.left - const maxX = this.left + this.width - const minY = this.top - const maxY = this.top + this.length - const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI - - const text = new fabric.Textbox(this.getLength().toString(), { - left: left, - top: top, - fontSize: this.fontSize, - minX, - maxX, - minY, - maxY, - parentDirection: this.direction, - parentDegree: degree, - parentId: this.id, - editable: false, - selectable: true, - lockRotation: true, - lockScalingX: true, - lockScalingY: true, - parent: this, - name: 'lengthText', - }) - - this.text = text - this.canvas.add(text) }, setFontSize(fontSize) { this.fontSize = fontSize diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index e095de42..26563ad3 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -5,6 +5,7 @@ import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import * as turf from '@turf/turf' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' +import Big from 'big.js' export const QPolygon = fabric.util.createClass(fabric.Polygon, { type: 'QPolygon', @@ -188,7 +189,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }, // 보조선 그리기 - drawHelpLine() { + drawHelpLine(settingModalFirstOptions) { const types = [] this.lines.forEach((line) => types.push(line.attributes.type)) @@ -205,7 +206,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { (gableOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableEven.every((type) => gableType.includes(type))) || (gableEven.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && gableOdd.every((type) => gableType.includes(type))) ) { - drawGabledRoof(this.id, this.canvas) + drawGabledRoof(this.id, this.canvas, settingModalFirstOptions) } else if (hasShed) { const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED) const areLinesParallel = function (line1, line2) { @@ -232,18 +233,18 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false) const isGable = gables.every((line) => gableType.includes(line.attributes.type)) if (isGable) { - drawShedRoof(this.id, this.canvas) + drawShedRoof(this.id, this.canvas, settingModalFirstOptions) } else { - drawRidgeRoof(this.id, this.canvas) + drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) } } else { - drawRidgeRoof(this.id, this.canvas) + drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) } } else { - drawRidgeRoof(this.id, this.canvas) + drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) } } else { - drawRidgeRoof(this.id, this.canvas) + drawRidgeRoof(this.id, this.canvas, settingModalFirstOptions) } }, @@ -262,15 +263,16 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { const end = points[(i + 1) % points.length] // planeSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10, // actualSize: Math.round(Math.sqrt(Math.pow(newLine.x1 - newLine.x2, 2) + Math.pow(newLine.y1 - newLine.y2, 2))) * 10, - const dx = end.x - start.x - const dy = end.y - start.y - const length = Math.round(Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2))) * 10 + const dx = Big(end.x).minus(Big(start.x)) + const dy = Big(end.y).minus(Big(start.y)) + // const length = Math.round(Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2))) * 10 + const length = dx.pow(2).plus(dy.pow(2)).sqrt().times(10).round().toNumber() let midPoint midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2) - const degree = (Math.atan2(dy, dx) * 180) / Math.PI + const degree = Big(Math.atan2(dy.toNumber(), dx.toNumber())).times(180).div(Math.PI).toNumber() // Create new text object if it doesn't exist const text = new fabric.Text(length.toString(), { diff --git a/src/hooks/roofcover/useEavesGableEdit.js b/src/hooks/roofcover/useEavesGableEdit.js index 7e69941a..7e84994e 100644 --- a/src/hooks/roofcover/useEavesGableEdit.js +++ b/src/hooks/roofcover/useEavesGableEdit.js @@ -10,6 +10,7 @@ import { outerLineFixState } from '@/store/outerLineAtom' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { getChonByDegree } from '@/util/canvas-util' +import { settingModalFirstOptionsState } from '@/store/settingAtom' // 처마.케라바 변경 export function useEavesGableEdit(id) { @@ -46,6 +47,8 @@ export function useEavesGableEdit(id) { { id: 4, name: getMessage('shed'), type: TYPES.SHED }, ] + const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState) + useEffect(() => { const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') if (!outerLineFix || outerLines.length === 0) { @@ -180,7 +183,7 @@ export function useEavesGableEdit(id) { const roof = drawRoofPolygon(wallLine) canvas?.renderAll() - roof.drawHelpLine() + roof.drawHelpLine(settingModalFirstOptions) }) wallLines.forEach((wallLine) => { diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 74bfcbcc..7e94f074 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -31,6 +31,7 @@ import { fabric } from 'fabric' import { outlineDisplaySelector } from '@/store/settingAtom' import { usePopup } from '@/hooks/usePopup' import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting' +import Big from 'big.js' //외벽선 그리기 export function useOuterLineWall(id, propertiesId) { @@ -141,6 +142,8 @@ export function useOuterLineWall(id, propertiesId) { const mouseDown = (e) => { let pointer = getIntersectMousePoint(e) + pointer = { x: Big(pointer.x).round(1).toNumber(), y: Big(pointer.y).round(1).toNumber() } + console.log('mouseDown', pointer, points) if (points.length === 0) { setPoints((prev) => [...prev, pointer]) @@ -148,24 +151,30 @@ export function useOuterLineWall(id, propertiesId) { const lastPoint = points[points.length - 1] let newPoint = { x: pointer.x, y: pointer.y } const length = distanceBetweenPoints(lastPoint, newPoint) + console.log('length', length) if (verticalHorizontalMode) { const vector = { - x: pointer.x - points[points.length - 1].x, - y: pointer.y - points[points.length - 1].y, + x: Big(pointer.x).minus(Big(points[points.length - 1].x)), + y: Big(pointer.y).minus(Big(points[points.length - 1].y)), } - const slope = Math.abs(vector.y / vector.x) // 기울기 계산 + // const slope = Math.abs(vector.y / vector.x) // 기울기 계산 + console.log('vector', vector.x.toNumber(), vector.y.toNumber(), Math.abs(vector.y.toNumber() / vector.x.toNumber()) >= 1) + const slope = vector.x.eq(0) ? Big(1) : vector.y.div(vector.x).abs() // 기울기 계산 let scaledVector - if (slope >= 1) { + // if (slope >= 1) { + if (slope.gte(1)) { // 기울기가 1 이상이면 x축 방향으로 그림 scaledVector = { x: 0, - y: vector.y >= 0 ? Number(length) : -Number(length), + // y: vector.y >= 0 ? Number(length) : -Number(length), + y: vector.y.gte(0) ? Big(length).toNumber() : Big(length).neg().toNumber(), } } else { // 기울기가 1 미만이면 y축 방향으로 그림 scaledVector = { - x: vector.x >= 0 ? Number(length) : -Number(length), + // x: vector.x >= 0 ? Number(length) : -Number(length), + x: vector.x.gte(0) ? Big(length).toNumber() : Big(length).neg().toNumber(), y: 0, } } @@ -173,9 +182,11 @@ export function useOuterLineWall(id, propertiesId) { const verticalLength = scaledVector.y const horizontalLength = scaledVector.x + console.log('verticalLength', verticalLength, 'horizontalLength', horizontalLength) + newPoint = { - x: lastPoint.x + horizontalLength, - y: lastPoint.y + verticalLength, + x: Big(lastPoint.x).plus(horizontalLength).toNumber(), + y: Big(lastPoint.y).plus(verticalLength).toNumber(), } } setPoints((prev) => [...prev, newPoint]) @@ -865,6 +876,8 @@ export function useOuterLineWall(id, propertiesId) { const firstPoint = points[0] + console.log('points 좌표 : ', points) + points.forEach((point, idx) => { if (idx === 0 || !isAllRightAngle) { return diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js index 425f0642..72a9ed0b 100644 --- a/src/hooks/roofcover/usePropertiesSetting.js +++ b/src/hooks/roofcover/usePropertiesSetting.js @@ -1,12 +1,13 @@ import { useEffect, useRef } from 'react' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' -import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' +import { useRecoilValue, useResetRecoilState } from 'recoil' import { canvasState, currentObjectState } from '@/store/canvasAtom' import { useMode } from '@/hooks/useMode' import { usePolygon } from '@/hooks/usePolygon' import { useLine } from '@/hooks/useLine' import { outerLinePointsState } from '@/store/outerLineAtom' import { usePopup } from '@/hooks/usePopup' +import { settingModalFirstOptionsState } from '@/store/settingAtom' // 외벽선 속성 설정 export function usePropertiesSetting(id) { @@ -16,6 +17,7 @@ export function usePropertiesSetting(id) { const { drawRoofPolygon } = useMode() const setPoints = useResetRecoilState(outerLinePointsState) + const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState) const { addPolygonByLines } = usePolygon() const { removeLine, hideLine } = useLine() @@ -156,7 +158,7 @@ export function usePropertiesSetting(id) { setPoints([]) canvas.renderAll() - roof.drawHelpLine() + roof.drawHelpLine(settingModalFirstOptions) closePopup(id) return diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 3bd89625..8ce7454e 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -10,6 +10,7 @@ import { outerLineFixState } from '@/store/outerLineAtom' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { getChonByDegree } from '@/util/canvas-util' +import { settingModalFirstOptionsState } from '@/store/settingAtom' // 지붕형상 설정 export function useRoofShapeSetting(id) { @@ -48,6 +49,8 @@ export function useRoofShapeSetting(id) { const history = useRef([]) const { closePopup } = usePopup() + const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState) + useEffect(() => { pitchRef.current = currentAngleType === ANGLE_TYPE.SLOPE ? pitch : getChonByDegree(pitch) }, [pitch]) @@ -423,7 +426,7 @@ export function useRoofShapeSetting(id) { const roof = drawRoofPolygon(polygon) canvas?.renderAll() - roof.drawHelpLine() + roof.drawHelpLine(settingModalFirstOptions) isFixRef.current = true closePopup(id) } diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 009df2e7..f973eba3 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -37,6 +37,8 @@ import offsetPolygon from '@/util/qpolygon-utils' import { isObjectNotEmpty } from '@/util/common-utils' import * as turf from '@turf/turf' import { INPUT_TYPE, LINE_TYPE, Mode, POLYGON_TYPE } from '@/common/common' +import Big from 'big.js' +import { settingModalFirstOptionsState } from '@/store/settingAtom' export function useMode() { const [mode, setMode] = useRecoilState(modeState) @@ -78,6 +80,8 @@ export function useMode() { const [objectPlacementMode, setObjectPlacementModeState] = useRecoilState(objectPlacementModeState) + const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState) + useEffect(() => { // if (!canvas) { // canvas?.setZoom(0.8) @@ -1554,7 +1558,7 @@ export function useMode() { }) const roof = drawRoofPolygon(polygon) //지붕 그리기 - roof.drawHelpLine() + roof.drawHelpLine(settingModalFirstOptions) // roof.divideLine() } @@ -1664,11 +1668,18 @@ export function useMode() { } } + /** + * polygon 을 기준으로 margin 된 polygon 을 작성한다. + * @param polygon + * @param lines + * @param arcSegments + * @returns {{vertices, edges: *[], minX: *, minY: *, maxX: *, maxY: *}} + */ function createMarginPolygon(polygon, lines, arcSegments = 0) { const offsetEdges = [] polygon.edges.forEach((edge, i) => { - const offset = lines[i % lines.length].attributes.offset === 0 ? 1 : lines[i % lines.length].attributes.offset + const offset = lines[i % lines.length].attributes.offset === 0 ? 0.1 : lines[i % lines.length].attributes.offset const dx = edge.outwardNormal.x * offset const dy = edge.outwardNormal.y * offset offsetEdges.push(createOffsetEdge(edge, dx, dy)) @@ -1692,6 +1703,13 @@ export function useMode() { return marginPolygon } + /** + * polygon 을 기준으로 padding 된 polygon 을 작성한다. + * @param polygon + * @param lines + * @param arcSegments + * @returns {{vertices, edges: *[], minX: *, minY: *, maxX: *, maxY: *}} + */ function createPaddingPolygon(polygon, lines, arcSegments = 0) { const offsetEdges = [] @@ -1720,7 +1738,13 @@ export function useMode() { return paddingPolygon } + /** + * 외벽선을 기준으로 지붕을 그린다. + * @param wall + * @returns {*} + */ const drawRoofPolygon = (wall) => { + //외벽선의 순서를 최좌측 선을 기준으로 반시계방향으로 정리한다. 지붕선과 순서를 맞추기 위함. const startLine = wall.lines .filter((line) => line.x1 === Math.min(...wall.lines.map((line) => line.x1))) .reduce((prev, current) => { @@ -1740,12 +1764,15 @@ export function useMode() { wall.lines = afterLine.concat(beforeLine) + //외벽선을 기준으로 polygon을 생성한다. 지붕선의 기준이 됨. const polygon = createRoofPolygon(wall.points) const originPolygon = new QPolygon(wall.points, { fontSize: 0 }) originPolygon.setViewLengthText(false) let offsetPolygon let result = createMarginPolygon(polygon, wall.lines).vertices + + //margin polygon 의 point가 기준 polygon의 밖에 있는지 판단한다. const allPointsOutside = result.every((point) => !originPolygon.inPolygon(point)) if (allPointsOutside) { @@ -1759,6 +1786,7 @@ export function useMode() { return { x1: point.x, y1: point.y } }), ) + if (wall.direction) { roof.direction = wall.direction } @@ -1769,9 +1797,11 @@ export function useMode() { roof.setWall(wall) roof.lines.forEach((line, index) => { - const lineLength = Math.sqrt( - Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), - ) + const x1 = Big(line.x1) + const x2 = Big(line.x2) + const y1 = Big(line.y1) + const y2 = Big(line.y2) + const lineLength = x1.minus(x2).abs().pow(2).plus(y1.minus(y2).abs().pow(2)).sqrt().times(10).round().toNumber() line.attributes = { roofId: roof.id, planeSize: lineLength, @@ -1789,14 +1819,18 @@ export function useMode() { roofId: roof.id, } + //외벽선 삭제 canvas .getObjects() .filter((line) => line.attributes?.wallId === wall.id) .forEach((line) => canvas.remove(line)) + wall.lines.forEach((line, index) => { - const lineLength = Math.sqrt( - Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), - ) + const x1 = Big(line.x1) + const x2 = Big(line.x2) + const y1 = Big(line.y1) + const y2 = Big(line.y2) + const lineLength = x1.minus(x2).abs().pow(2).plus(y1.minus(y2).abs().pow(2)).sqrt().times(10).round().toNumber() line.attributes.roofId = roof.id line.attributes.currentRoofId = roof.lines[index].id line.attributes.planeSize = lineLength @@ -1829,6 +1863,8 @@ export function useMode() { wallStrokeWidth = 4 break } + + //외벽선의 색깔 표시를 위해 라인을 추가한다. const wallLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], { parentId: wall.id, name: 'wallLine', diff --git a/src/hooks/useMouse.js b/src/hooks/useMouse.js index 033fea59..456ab278 100644 --- a/src/hooks/useMouse.js +++ b/src/hooks/useMouse.js @@ -1,12 +1,12 @@ import { useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' -import { calculateIntersection, getInterSectionLineNotOverCoordinate } from '@/util/canvas-util' +import { getInterSectionLineNotOverCoordinate } from '@/util/canvas-util' export function useMouse() { const canvas = useRecoilValue(canvasState) //가로선, 세로선의 교차점을 return - const getIntersectMousePoint = (e) => { + /*const getIntersectMousePoint = (e) => { let pointer = canvas.getPointer(e.e) const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine') @@ -15,6 +15,17 @@ export function useMouse() { } return getInterSectionLineNotOverCoordinate(mouseLines[0], mouseLines[1]) || pointer + }*/ + //가로선, 세로선의 교차점을 return + const getIntersectMousePoint = (e) => { + let pointer = canvas.getPointer(e.e) + const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine') + + if (mouseLines.length < 2) { + return { x: Math.round(pointer.x), y: Math.round(pointer.y) } + } + + return getInterSectionLineNotOverCoordinate(mouseLines[0], mouseLines[1]) || { x: Math.round(pointer.x), y: Math.round(pointer.y) } } return { diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 5df32879..4ec7a4be 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -1,5 +1,6 @@ import { intersect } from 'mathjs' import * as turf from '@turf/turf' +import Big from 'big.js' /** * Collection of function to use on canvas @@ -128,9 +129,9 @@ export const formattedWithComma = (value, unit = 'mm') => { } export const distanceBetweenPoints = (point1, point2) => { - const dx = point2.x - point1.x - const dy = point2.y - point1.y - return Math.sqrt(dx * dx + dy * dy) + const dx = Big(point2.x).minus(Big(point1.x)) + const dy = Big(point2.y).minus(Big(point1.y)) + return dx.pow(2).plus(dy.pow(2)).sqrt().round(1).toNumber() } /** diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 643c640d..8632cd54 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -6,6 +6,7 @@ import { QPolygon } from '@/components/fabric/QPolygon' import * as turf from '@turf/turf' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { OUTER_LINE_TYPE } from '@/store/outerLineAtom' +import Big from 'big.js' const TWO_PI = Math.PI * 2 @@ -15,9 +16,15 @@ export const defineQPloygon = () => { } } +/** + * point1에서 point2를 잇는 방향의 각도를 구한다. + * @param point1 + * @param point2 + * @returns {number} + */ export const calculateAngle = (point1, point2) => { - const deltaX = point2.x - point1.x - const deltaY = point2.y - point1.y + const deltaX = Big(point2.x).minus(point1.x).toNumber() + const deltaY = Big(point2.y).minus(point1.y).toNumber() const angleInRadians = Math.atan2(deltaY, deltaX) return angleInRadians * (180 / Math.PI) } @@ -86,13 +93,19 @@ function createPolygon(vertices) { } } +/** + * edgeA와 edgeB가 마주치는 포인트의 좌표를 반환한다. + * @param edgeA + * @param edgeB + * @returns {{x: *, y: *, isIntersectionOutside: boolean}|null} + */ function edgesIntersection(edgeA, edgeB) { const den = (edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex2.x - edgeA.vertex1.x) - (edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex2.y - edgeA.vertex1.y) if (den === 0) { - return null // lines are parallel or coincident + return null // 선들이 평행하거나 일치합니다 } const ua = @@ -105,7 +118,7 @@ function edgesIntersection(edgeA, edgeB) { (edgeA.vertex2.y - edgeA.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) / den - // Edges are not intersecting but the lines defined by them are + // 교차점이 두 선분의 범위 내에 있는지 확인 const isIntersectionOutside = ua < 0 || ub < 0 || ua > 1 || ub > 1 return { @@ -295,7 +308,7 @@ export const isSamePoint = (a, b) => { * @param roofId * @param canvas */ -export const drawGabledRoof = (roofId, canvas) => { +export const drawGabledRoof = (roofId, canvas, settingModalFirstOptions) => { const roof = canvas?.getObjects().find((object) => object.id === roofId) const roofLines = roof.lines const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines @@ -633,7 +646,7 @@ export const drawGabledRoof = (roofId, canvas) => { * @param roofId * @param canvas */ -export const drawShedRoof = (roofId, canvas) => { +export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => { const roof = canvas?.getObjects().find((object) => object.id === roofId) const hasNonParallelLines = roof.lines.filter((line) => Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1) if (hasNonParallelLines.length > 0) { @@ -689,6 +702,8 @@ export const drawShedRoof = (roofId, canvas) => { x2 = eave.x1 } points.sort((a, b) => a - b) + const planeSize = Math.round(Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)) * 10) + const actualSize = Math.round(Math.sqrt(Math.pow(planeSize, 2) + Math.pow(getHeight(planeSize, shedDegree), 2)) * 10) const line = new QLine([x1, y1, x2, y2], { parentId: roof.id, stroke: '#000000', @@ -699,6 +714,8 @@ export const drawShedRoof = (roofId, canvas) => { attributes: { roofId: roof.id, type: 'pitchSizeLine', + planeSize: planeSize, + actualSize: actualSize, }, }) pitchSizeLines.push(line) @@ -717,18 +734,36 @@ export const drawShedRoof = (roofId, canvas) => { maxLine.setLengthText(lengthText) } -export const drawRidgeRoof = (roofId, canvas) => { +export const drawRidgeRoof = (roofId, canvas, settingModalFirstOptions) => { const roof = canvas?.getObjects().find((object) => object.id === roofId) - const hasNonParallelLines = roof.lines.filter((line) => Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1) + let textMode = 'plane' + + const dimensionDisplay = settingModalFirstOptions?.dimensionDisplay.find((opt) => opt.selected).id + ? settingModalFirstOptions?.dimensionDisplay.find((opt) => opt.selected).id + : 1 + switch (dimensionDisplay) { + case 1: + textMode = 'plane' + break + case 2: + textMode = 'actual' + break + case 3: + textMode = 'none' + break + } + //Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1 + 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) { alert('대각선이 존재합니다.') return } - drawRidge(roof, canvas) - drawHips(roof, canvas) - connectLinePoint(roof, canvas) - modifyRidge(roof, canvas) - drawCenterLine(roof, canvas) + + drawRidge(roof, canvas, textMode) + drawHips(roof, canvas, textMode) + connectLinePoint(roof, canvas, textMode) + modifyRidge(roof, canvas, textMode) + // drawCenterLine(roof, canvas, textMode) } /** @@ -736,8 +771,12 @@ export const drawRidgeRoof = (roofId, canvas) => { * * @param roof * @param canvas + * @param textMode */ -const drawRidge = (roof, canvas) => { +const drawRidge = (roof, canvas, textMode) => { + console.log('roof.lines : ', roof.lines) + console.log('textMode : ', textMode) + const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines // 외벽의 라인 const roofLines = roof.lines // 지붕의 라인 let ridgeRoof = [] @@ -750,9 +789,12 @@ const drawRidge = (roof, canvas) => { prevRoof = index === 0 ? wallLines[wallLines.length - 1] : wallLines[index - 1] nextRoof = index === wallLines.length - 1 ? wallLines[0] : index === wallLines.length ? wallLines[1] : wallLines[index + 1] - const angle1 = calculateAngle(prevRoof.startPoint, prevRoof.endPoint) - const angle2 = calculateAngle(nextRoof.startPoint, nextRoof.endPoint) - if (Math.round(Math.abs(angle1 - angle2)) === 180 && currentWall.attributes.planeSize <= currentRoof.attributes.planeSize) { + const angle1 = Big(calculateAngle(prevRoof.startPoint, prevRoof.endPoint)) + const angle2 = Big(calculateAngle(nextRoof.startPoint, nextRoof.endPoint)) + if ( + angle1.minus(angle2).abs().round(Big.roundHalfUp).toNumber() === 180 && + currentWall.attributes.planeSize <= currentRoof.attributes.planeSize + ) { ridgeRoof.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize }) } }) @@ -776,75 +818,91 @@ const drawRidge = (roof, canvas) => { const anotherRoof = roofLines.filter((roof) => roof !== currentRoof && roof !== prevRoof && roof !== nextRoof) - let currentX1 = currentRoof.x1, - currentY1 = currentRoof.y1, - currentX2 = currentRoof.x2, - currentY2 = currentRoof.y2 - let ridgeMaxLength = Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize) / 10 - let ridgeMinLength = Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize) / 10 + let currentX1 = Big(currentRoof.x1), + currentY1 = Big(currentRoof.y1), + currentX2 = Big(currentRoof.x2), + currentY2 = Big(currentRoof.y2) + let ridgeMaxLength = Big(Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize)).div(10) + let ridgeMinLength = Big(Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize)).div(10) - const currentAngle = Math.atan2(currentY2 - currentY1, currentX2 - currentX1) * (180 / Math.PI) + console.log('ridgeMinLength : ', ridgeMinLength.toNumber(), 'ridgeMaxLength : ', ridgeMaxLength.toNumber()) + + const currentAngle = Math.atan2(currentY2.minus(currentY1).toNumber(), currentX2.minus(currentX1).toNumber()) * (180 / Math.PI) anotherRoof .filter((roof) => isInnerLine(prevRoof, currentRoof, nextRoof, roof)) .forEach((innerRoof) => { - const vector1 = { x: currentRoof.x2 - currentRoof.x1, y: currentRoof.y2 - currentRoof.y1 } - const vector2 = { x: innerRoof.x2 - innerRoof.x1, y: innerRoof.y2 - innerRoof.y1 } + const vector1 = { x: currentX2.minus(currentX1), y: currentY2.minus(currentY1) } + const vector2 = { x: Big(innerRoof.x2).minus(Big(innerRoof.x1)), y: Big(innerRoof.y2).minus(Big(innerRoof.y1)) } - const dotProduct = vector1.x * vector2.x + vector1.y * vector2.y - const magnitude1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y) - const magnitude2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y) - const angle = (Math.acos(dotProduct / (magnitude1 * magnitude2)) * 180) / Math.PI + const dotProduct = vector1.x.times(vector2.x).plus(vector1.y.times(vector2.y)) + const magnitude1 = vector1.x.pow(2).plus(vector1.y.pow(2)).sqrt() + const magnitude2 = vector2.x.pow(2).plus(vector2.y.pow(2)).sqrt() + const angle = (Math.acos(dotProduct.div(magnitude1.times(magnitude2).toNumber())) * 180) / Math.PI - //현재 지붕선과 직각인 선 + // 현재 지붕선과 직각인 선 if (Math.abs(angle) === 90) { const innerBefore = roofLines.find((line) => innerRoof.x1 === line.x2 && innerRoof.y1 === line.y2) - const ibAngle = Math.atan2(innerBefore.y2 - innerBefore.y1, innerBefore.x2 - innerBefore.x1) * (180 / Math.PI) - if (Math.abs(currentAngle - ibAngle) === 180) { + const ibAngle = + Math.atan2(Big(innerBefore.y2).minus(Big(innerBefore.y1)).toNumber(), Big(innerBefore.x2).minus(Big(innerBefore.x1)).toNumber()) * + (180 / Math.PI) + if (Math.abs(Big(currentAngle).minus(Big(ibAngle))) === 180) { if (currentAngle === 0 || currentAngle === 180) { currentX2 = innerRoof.x1 - ridgeMinLength = - Math.round( - Math.sqrt( - Math.pow(Math.round(Math.abs(nextRoof.x1 - nextRoof.x2) * 10), 2) + - Math.pow(Math.round(Math.abs(nextRoof.y1 - innerRoof.y2) * 10), 2), - ), - ) / 10 + ridgeMinLength = Big(nextRoof.x1) + .minus(Big(nextRoof.x2)) + .times(10) + .round() + .pow(2) + .plus(Big(nextRoof.y1).minus(Big(nextRoof.y2)).times(10).round().pow(2)) + .sqrt() + .div(10) + console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) + console.log('check ridgeMinLength', calcLinePlaneSize({ x1: nextRoof.x1, y1: nextRoof.y1, x2: nextRoof.x2, y2: nextRoof.y2 })) } if (currentAngle === 90 || currentAngle === 270) { currentY2 = innerRoof.y1 - ridgeMinLength = - Math.round( - Math.sqrt( - Math.pow(Math.round(Math.abs(nextRoof.x1 - innerRoof.x2) * 10), 2) + - Math.pow(Math.round(Math.abs(nextRoof.y1 - nextRoof.y2) * 10), 2), - ), - ) / 10 + ridgeMinLength = Big(nextRoof.x1) + .minus(Big(innerRoof.x2)) + .times(10) + .round() + .pow(2) + .plus(Big(nextRoof.y1).minus(Big(nextRoof.y2)).times(10).round().pow(2)) + .sqrt() + .div(10) + console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) + console.log('check ridgeMinLength', calcLinePlaneSize({ x1: nextRoof.x1, y1: nextRoof.y1, x2: innerRoof.x2, y2: nextRoof.y2 })) } } if (Math.abs(currentAngle - ibAngle) === 0) { if (currentAngle === 0 || currentAngle === 180) { currentX1 = innerRoof.x2 - ridgeMinLength = - Math.round( - Math.sqrt( - Math.pow(Math.round(Math.abs(prevRoof.x1 - prevRoof.x2) * 10), 2) + - Math.pow(Math.round(Math.abs(prevRoof.y1 - innerRoof.y1) * 10), 2), - ), - ) / 10 + ridgeMinLength = Big(prevRoof.x1) + .minus(Big(prevRoof.x2)) + .times(10) + .round() + .pow(2) + .plus(Big(prevRoof.y1).minus(Big(innerRoof.y1)).times(10).round().pow(2)) + .sqrt() + .div(10) + console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) + console.log('check ridgeMinLength', calcLinePlaneSize({ x1: prevRoof.x1, y1: prevRoof.y1, x2: prevRoof.x2, y2: innerRoof.y1 })) } if (currentAngle === 90 || currentAngle === 270) { currentY1 = innerRoof.y2 - ridgeMinLength = - Math.round( - Math.sqrt( - Math.pow(Math.round(Math.abs(prevRoof.x1 - innerRoof.x1) * 10), 2) + - Math.pow(Math.round(Math.abs(prevRoof.y1 - prevRoof.y2) * 10), 2), - ), - ) / 10 + ridgeMinLength = Big(prevRoof.x1) + .minus(innerRoof.x1) + .times(10) + .round() + .pow(2) + .plus(Big(prevRoof.y2).minus(prevRoof.y2).times(10).round().pow(2)) + .sqrt() + .div(10) + console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) + console.log('check ridgeMinLength', calcLinePlaneSize({ x1: prevRoof.x1, y1: prevRoof.y1, x2: innerRoof.x2, y2: prevRoof.y2 })) } } } - //현재 지붕선과 반대인 선 + // 현재 지붕선과 반대인 선 if (Math.abs(angle) === 180) { if (currentAngle === 0 || currentAngle === 180) { } @@ -853,24 +911,39 @@ const drawRidge = (roof, canvas) => { } }) - const midX = (currentX1 + currentX2) / 2 // 지붕의 X 중심 - const midY = (currentY1 + currentY2) / 2 // 지붕의 Y 중심 - const alpha = (currentRoof.x1 + currentRoof.x2) / 2 - (wallLine.x1 + wallLine.x2) / 2 // 벽과 지붕의 X 거리 - const beta = (currentRoof.y1 + currentRoof.y2) / 2 - (wallLine.y1 + wallLine.y2) / 2 // 벽과 지붕의 Y 거리 - const hypotenuse = Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) // 벽과 지붕의 거리 + // 지붕선의 X 중심 + const midX = currentX1.plus(currentX2).div(2) + // 지붕선의 Y 중심 + const midY = currentY1.plus(currentY2).div(2) - const currentPlaneSize = Math.sqrt( - Math.pow(Math.round(Math.abs(currentX1 - currentX2) * 10), 2) + Math.pow(Math.round(Math.abs(currentY1 - currentY2) * 10), 2), - ) - let ridgeBaseLength = Math.round(currentPlaneSize / 2) / 10 // 지붕의 기반 길이 + // 외선벽과 지붕선의 X 거리 + const alpha = Big(currentRoof.x1) + .plus(Big(currentRoof.x2)) + .div(2) + .minus(Big(wallLine.x1).plus(Big(wallLine.x2)).div(2)) + // 외벽벽과 지붕선의 Y 거리 + const beta = Big(currentRoof.y1) + .plus(Big(currentRoof.y2)) + .div(2) + .minus(Big(wallLine.y1).plus(Big(wallLine.y2)).div(2)) + // 외벽벽과 지붕선의 거리 + const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() - startXPoint = Math.round(midX + (-1 * (alpha / hypotenuse) * (currentPlaneSize / 2)) / 10) - startYPoint = Math.round(midY + (-1 * (beta / hypotenuse) * (currentPlaneSize / 2)) / 10) + // 지붕선의 평면길이 + const currentPlaneSize = Big(calcLinePlaneSize({ x1: currentX1, y1: currentY1, x2: currentX2, y2: currentY2 })) + // 용마루의 기반길이(지붕선에서 떨어진 정도) + let ridgeBaseLength = currentPlaneSize.div(2).round().div(10) - const checkEndXPoint = Math.round(startXPoint + Math.sign(alpha) * -1 * (ridgeMaxLength + ridgeBaseLength)) - const checkEndYPoint = Math.round(startYPoint + Math.sign(beta) * -1 * (ridgeMaxLength + ridgeBaseLength)) + // 시작점은 현재 지붕선을 대각선으로 한 직각이등변삼각형으로 판단하고 현재 지붕선의 가운데에서 지붕에서 90도방향으로 지붕선의 절반만큼 떨어진 방향으로 설정한다. + startXPoint = midX.plus(alpha.div(hypotenuse).times(currentPlaneSize.div(2)).neg().div(10)) + startYPoint = midY.plus(beta.div(hypotenuse).times(currentPlaneSize.div(2)).neg().div(10)) - const checkLine = new QLine([startXPoint, startYPoint, checkEndXPoint, checkEndYPoint], { + // 종료점은 시작점에서 용마루의 최대길이 + 기반길이 만큼 그려진것으로 판단하여 늘린다. + const checkEndXPoint = startXPoint.plus(Big(Math.sign(alpha.toNumber())).times(ridgeMaxLength.plus(ridgeBaseLength)).neg()) + const checkEndYPoint = startYPoint.plus(Big(Math.sign(beta.toNumber())).times(ridgeMaxLength.plus(ridgeBaseLength)).neg()) + + // 맞은편 외벽선을 확인하기 위한 라인을 생성 + const checkLine = new QLine([startXPoint.toNumber(), startYPoint.toNumber(), checkEndXPoint.toNumber(), checkEndYPoint.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: 'red', @@ -878,6 +951,11 @@ const drawRidge = (roof, canvas) => { name: LINE_TYPE.SUBLINE.HIP, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, actualSize: 0 }, }) + // 디버그시 주석제거해서 라인 확인 + // canvas.add(checkLine) + // canvas.renderAll() + + // checkLine 과 마주치는 지붕선을 모두 찾아낸다. const intersectLines = [] roofLines.forEach((line) => { const intersection = edgesIntersection( @@ -888,62 +966,98 @@ const drawRidge = (roof, canvas) => { intersectLines.push({ x: intersection.x, y: intersection.y, line: line }) } }) + // intersectLines 중 현재 지붕선과 가장 가까운 지붕선을 찾는다. if (intersectLines.length > 0) { intersectLines.reduce((prev, current) => { if (prev !== undefined) { - const prevDistance = Math.sqrt(Math.pow(prev.x - startXPoint, 2) + Math.pow(prev.y - startYPoint, 2)) - const currentDistance = Math.sqrt(Math.pow(current.x - startXPoint, 2) + Math.pow(current.y - startYPoint, 2)) + const prevDistance = Big(prev.x).minus(startXPoint).pow(2).plus(Big(prev.y).minus(startYPoint).pow(2)).sqrt() + const currentDistance = Big(current.x).minus(startXPoint).pow(2).plus(Big(current.y).minus(startYPoint).pow(2)).sqrt() return prevDistance > currentDistance ? current : prev } else { return current } }, undefined) } - + // 현재 지붕선과 마주하는 지붕선이 있는 경우 if (intersectLines.length > 0) { + // 마주하는 지붕선 const intersectLine = intersectLines[0] - const diffX = Math.round(intersectLine.x - startXPoint) - const diffY = Math.round(intersectLine.y - startYPoint) - endXPoint = Math.sign(diffX) * Math.round(Math.abs(diffX) - ridgeBaseLength) + startXPoint - endYPoint = Math.sign(diffY) * Math.round(Math.abs(diffY) - ridgeBaseLength) + startYPoint - const hypo = Math.sqrt(Math.pow(Math.abs(startXPoint - endXPoint), 2) + Math.pow(Math.abs(startYPoint - endYPoint), 2)) + //지붕선에서 마주하는 지붕선까지의 x,y 좌표의 차이 - const intersectLength = Math.sqrt(Math.pow(Math.abs(midX - intersectLine.x), 2) + Math.pow(Math.abs(midY - intersectLine.y), 2)) - if (intersectLength < prevRoof.attributes.planeSize / 10 && intersectLength < nextRoof.attributes.planeSize / 10) { + const diffX = Big(intersectLine.x).minus(startXPoint).round(1).abs().lt(1) ? Big(0) : Big(intersectLine.x).minus(startXPoint).round(1) + const diffY = Big(intersectLine.y).minus(startYPoint).round(1).abs().lt(1) ? Big(0) : Big(intersectLine.y).minus(startYPoint).round(1) + // 시작점에서 ridgeBaseLength 만큼 떨어진 지점까지 용마루 길이로 본다. + console.log('diffX : ', diffX.toNumber(), 'diffY : ', diffY.toNumber()) + console.log('ridgeBaseLength : ', ridgeBaseLength.toNumber()) + console.log('Math.sign(diffX.toNumber()) : ', Math.sign(diffX.toNumber()), diffX.abs().minus(ridgeBaseLength).toNumber()) + console.log('Math.sign(diffY.toNumber()) : ', Math.sign(diffY.toNumber()), diffY.abs().minus(ridgeBaseLength).toNumber()) + endXPoint = startXPoint.plus(Big(Math.sign(diffX.toNumber())).times(diffX.abs().minus(ridgeBaseLength))) + endYPoint = startYPoint.plus(Big(Math.sign(diffY.toNumber())).times(diffY.abs().minus(ridgeBaseLength))) + console.log( + 'intersectLine : ', + Big(intersectLine.x).minus(startXPoint).round(1).toNumber(), + Big(intersectLine.y).minus(startYPoint).round(1).toNumber(), + ) + console.log('startXPoint : ', startXPoint.toNumber(), 'startYPoint : ', startYPoint.toNumber()) + console.log('endXPoint : ', endXPoint.toNumber(), 'endYPoint : ', endYPoint.toNumber()) + + // 시작점에서 종료점까지의 평면길이 + //startXPoint.minus(endXPoint).abs().pow(2).plus(startYPoint.minus(endYPoint).abs().pow(2)).sqrt() + const hypo = Big( + calcLinePlaneSize({ x1: startXPoint.toNumber(), y1: startYPoint.toNumber(), x2: endXPoint.toNumber(), y2: endYPoint.toNumber() }), + ).div(10) + // 현재 지붕선과 마주하는 지붕선을 잇는 선분의 교차점까지의 길이 + const intersectLength = Big(calcLinePlaneSize({ x1: midX.toNumber(), y1: midY.toNumber(), x2: intersectLine.x, y2: intersectLine.y })).div(10) + //마주하는 지붕선까지의 길이가 현재 지붕선의 이전, 다음 지붕선의 길이보다 작을때 + if (intersectLength.lt(Big(prevRoof.attributes.planeSize).div(10)) && intersectLength.lt(Big(nextRoof.attributes.planeSize).div(10))) { endXPoint = startXPoint endYPoint = startYPoint } else { - if (ridgeMinLength < hypo) { - endXPoint = Math.round(startXPoint + Math.sign(diffX) * ridgeMinLength) - endYPoint = Math.round(startYPoint + Math.sign(diffY) * ridgeMinLength) + if (ridgeMinLength.lt(hypo)) { + endXPoint = startXPoint.plus(Big(Math.sign(diffX.toNumber())).times(ridgeMinLength)) + endYPoint = startYPoint.plus(Big(Math.sign(diffY.toNumber())).times(ridgeMinLength)) } } } else { - endXPoint = Math.round(startXPoint + Math.sign(alpha) * -1 * ridgeMinLength) - endYPoint = Math.round(startYPoint + Math.sign(beta) * -1 * ridgeMinLength) + endXPoint = startXPoint.plus(Big(Math.sign(alpha.toNumber())).times(ridgeMinLength).neg()) + endYPoint = startYPoint.plus(Big(Math.sign(beta.toNumber())).times(ridgeMinLength).neg()) } - const ridge = new QLine([startXPoint, startYPoint, endXPoint, endYPoint], { + // 용마루 선을 그린다. + const ridge = new QLine([startXPoint.toNumber(), startYPoint.toNumber(), endXPoint.toNumber(), endYPoint.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.RIDGE, - attributes: { roofId: roof.id }, + textMode: textMode, + attributes: { + roofId: roof.id, + planeSize: calcLinePlaneSize({ + x1: startXPoint.toNumber(), + y1: startYPoint.toNumber(), + x2: endXPoint.toNumber(), + y2: endYPoint.toNumber(), + }), + actualSize: calcLinePlaneSize({ + x1: startXPoint.toNumber(), + y1: startYPoint.toNumber(), + x2: endXPoint.toNumber(), + y2: endYPoint.toNumber(), + }), + }, }) - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - + // 용마루의 길이가 0보다 클때만 canvas 에 추가 한다. if (ridge.attributes.planeSize > 0) { canvas.add(ridge) roof.ridges.push(ridge) roof.innerLines.push(ridge) - const distance = (x1, y1, x2, y2) => Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)) - const dist1 = distance(startXPoint, startYPoint, currentRoof.x1, currentRoof.y1) - const dist2 = distance(endXPoint, endYPoint, currentRoof.x1, currentRoof.y1) + const distance = (x1, y1, x2, y2) => x2.minus(x1).pow(2).plus(y2.minus(y1).pow(2)).sqrt() + const dist1 = distance(startXPoint, startYPoint, Big(currentRoof.x1), Big(currentRoof.y1)) + const dist2 = distance(endXPoint, endYPoint, Big(currentRoof.x1), Big(currentRoof.y1)) currentRoof.attributes.ridgeCoordinate = { x1: dist1 < dist2 ? startXPoint : endXPoint, @@ -964,22 +1078,28 @@ const drawRidge = (roof, canvas) => { 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 = new QLine([x1, y1, x2, y2], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.RIDGE, - attributes: { roofId: roof.id }, + textMode: textMode, + attributes: { + roofId: roof.id, + planeSize: calcLinePlaneSize({ x1, y1, x2, y2 }), + actualSize: calcLinePlaneSize({ x1, y1, x2, y2 }), + }, }) + //겹치는 용마루를 제거한다. roof.canvas.remove(ridge) roof.canvas.remove(ridge2) + roof.ridges = roof.ridges.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2)) roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2)) - newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) canvas.add(newRidge) roof.ridges.push(newRidge) roof.innerLines.push(newRidge) @@ -1034,8 +1154,10 @@ export const segmentsOverlap = (line1, line2) => { * 추녀마루를 그린다. * @param roof * @param canvas + * @param textMode */ -const drawHips = (roof, canvas) => { +const drawHips = (roof, canvas, textMode) => { + console.log('textMode : ', textMode) const roofLines = roof.lines const ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roof.id) @@ -1049,50 +1171,58 @@ const drawHips = (roof, canvas) => { const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree + //용마루 작성시 입력된 용마루 좌표가 있는 경우 처리 const ridgeCoordinate = currentRoof.attributes.ridgeCoordinate - const vectorX1 = ridgeCoordinate.x1 - currentRoof.x1 - const vectorY1 = ridgeCoordinate.y1 - currentRoof.y1 - const angle1 = Math.atan2(vectorY1, vectorX1) * (180 / Math.PI) - if (Math.abs(Math.round(angle1)) % 45 === 0) { + const vectorX1 = Big(ridgeCoordinate.x1).minus(Big(currentRoof.x1)) + const vectorY1 = Big(ridgeCoordinate.y1).minus(Big(currentRoof.y1)) + //현재 지붕선의 좌표와 용마루 좌표의 각도를 구한다. + const angle1 = Big(Math.atan2(vectorY1.toNumber(), vectorX1.toNumber())).times(Big(180).div(Math.PI)) + + // 용마루 까지의 각도가 45도 인 경우 작성. + if (Big(angle1.abs().toNumber()).mod(45).eq(0)) { const hip1 = new QLine([currentRoof.x1, currentRoof.y1, ridgeCoordinate.x1, ridgeCoordinate.y1], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, - attributes: { roofId: roof.id, currentRoofId: currentRoof.id, actualSize: 0 }, + attributes: { + roofId: roof.id, + currentRoofId: currentRoof.id, + planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }), + actualSize: + prevDegree === currentDegree + ? calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }, currentDegree) + : 0, + }, }) canvas.add(hip1) - const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 - const hip1Height = Math.round(hip1Base / Math.tan(((90 - currentDegree) * Math.PI) / 180)) - hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 - if (prevDegree === currentDegree) { - hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) - } roof.hips.push(hip1) roof.innerLines.push(hip1) } - const vectorX2 = ridgeCoordinate.x1 - currentRoof.x2 - const vectorY2 = ridgeCoordinate.y1 - currentRoof.y2 - const angle2 = Math.atan2(vectorY2, vectorX2) * (180 / Math.PI) - if (Math.abs(Math.round(angle2)) % 45 === 0) { + const vectorX2 = Big(ridgeCoordinate.x1).minus(Big(currentRoof.x2)) + const vectorY2 = Big(ridgeCoordinate.y1).minus(Big(currentRoof.y2)) + const angle2 = Big(Math.atan2(vectorY2.toNumber(), vectorX2.toNumber())).times(Big(180).div(Math.PI)) + if (Big(angle2.abs().toNumber()).mod(45).eq(0)) { const hip2 = new QLine([currentRoof.x2, currentRoof.y2, ridgeCoordinate.x1, ridgeCoordinate.y1], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, - attributes: { roofId: roof.id, currentRoofId: currentRoof.id, actualSize: 0 }, + attributes: { + roofId: roof.id, + currentRoofId: currentRoof.id, + planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }), + actualSize: + prevDegree === currentDegree + ? calcLineActualSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }, currentDegree) + : 0, + }, }) canvas.add(hip2) - const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 - const hip2Height = Math.round(hip2Base / Math.tan(((90 - currentDegree) * Math.PI) / 180)) - hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 - if (nextDegree === currentDegree) { - hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) - } roof.hips.push(hip2) roof.innerLines.push(hip2) } @@ -1121,26 +1251,29 @@ const drawHips = (roof, canvas) => { let ridgePoints = [] ridgeLines.forEach((ridge) => { - const deltaX1 = Math.round((ridge.x1 - currentRoof.x1) * 10) / 10 - const deltaY1 = Math.round((ridge.y1 - currentRoof.y1) * 10) / 10 - const deltaX2 = Math.round((ridge.x2 - currentRoof.x1) * 10) / 10 - const deltaY2 = Math.round((ridge.y2 - currentRoof.y1) * 10) / 10 + const deltaX1 = Big(ridge.x1).minus(Big(currentRoof.x1)) + const deltaY1 = Big(ridge.y1).minus(Big(currentRoof.y1)) + const deltaX2 = Big(ridge.x2).minus(Big(currentRoof.x1)) + const deltaY2 = Big(ridge.y2).minus(Big(currentRoof.y1)) - if (Math.round(Math.abs(deltaY1 / deltaX1) * 10) / 10 === 1) { + if (deltaY1.div(deltaX1).abs().round(1).eq(1)) { ridgePoints.push({ x: ridge.x1, y: ridge.y1 }) } - if (Math.round(Math.abs(deltaY2 / deltaX2) * 10) / 10 === 1) { + if (deltaY2.div(deltaX2).abs().round(1).eq(1)) { ridgePoints.push({ x: ridge.x2, y: ridge.y2 }) } }) + console.log('currentRoof : ', currentRoof.length) + console.log(ridgePoints) ridgePoints = ridgePoints.reduce((prev, current) => { if (prev !== undefined) { - const deltaPrevX = Math.abs(prev.x - currentRoof.x1) - const deltaPrevY = Math.abs(prev.y - currentRoof.y1) - const deltaCurrentX = Math.abs(current.x - currentRoof.x1) - const deltaCurrentY = Math.abs(current.y - currentRoof.y1) - if (deltaPrevX < deltaCurrentX && deltaPrevY < deltaCurrentY) { + // Math.abs(prev.x - currentRoof.x1) + const deltaPrevX = Big(prev.x).minus(Big(currentRoof.x1)).abs() + const deltaPrevY = Big(prev.y).minus(Big(currentRoof.y1)).abs() + const deltaCurrentX = Big(current.x).minus(Big(currentRoof.x1)).abs() + const deltaCurrentY = Big(current.y).minus(Big(currentRoof.y1)).abs() + if (deltaPrevX.lt(deltaCurrentX) && deltaPrevY.lt(deltaCurrentY)) { return prev } else { return current @@ -1157,19 +1290,26 @@ const drawHips = (roof, canvas) => { stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, - attributes: { roofId: roof.id, currentRoofId: currentRoof.id, actualSize: 0 }, + attributes: { + roofId: roof.id, + currentRoofId: currentRoof.id, + planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgePoints.x, y2: ridgePoints.y }), + actualSize: + prevDegree === currentDegree + ? calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgePoints.x, y2: ridgePoints.y }, currentDegree) + : 0, + }, }) canvas.add(hip) - const hipBase = ((Math.abs(hip.x1 - hip.x2) + Math.abs(hip.y1 - hip.y2)) / 2) * 10 - const hipHeight = Math.round(hipBase / Math.tan(((90 - currentDegree) * Math.PI) / 180)) - hip.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip.x1 - hip.x2, 2) + Math.pow(hip.y1 - hip.y2, 2))) * 10 - if (prevDegree === currentDegree) { - hip.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip.attributes.planeSize, 2) + Math.pow(hipHeight, 2))) - } roof.hips.push(hip) roof.innerLines.push(hip) } }) + roof.innerLines.forEach((hip) => { + console.log('hip 길이 : ', hip.attributes.planeSize, ' actual : ', hip.attributes.actualSize) + hip.textMode = 'actual' + hip.addLengthText() + }) canvas?.renderAll() } @@ -1177,10 +1317,18 @@ const drawHips = (roof, canvas) => { * 3개 이상 이어지지 않은 라인 포인트 계산 * 모임지붕에서 point 는 3개 이상의 라인과 접해야 함. * @param polygon + * @param canvas + * @param textMode */ -const connectLinePoint = (polygon) => { +const connectLinePoint = (polygon, canvas, textMode) => { // 연결되지 않은 모든 라인의 포인트를 구한다. let missedPoints = [] + + const lineDegrees = [ + ...new Set(polygon.lines.map((line) => (line.attributes.pitch > 0 ? getDegreeByChon(line.attributes.pitch) : line.attributes.degree))), + ] + console.log('lineDegrees : ', lineDegrees) + //마루 polygon.ridges.forEach((ridge) => { if (ridge.x1 === ridge.x2) { @@ -1260,13 +1408,16 @@ const connectLinePoint = (polygon) => { missedLine.forEach((p) => { const line = new QLine([p.x1, p.y1, p.x2, p.y2], { parentId: polygon.id, - attributes: { roofId: polygon.id }, + attributes: { + roofId: polygon.id, + planeSize: calcLinePlaneSize(p), + actualSize: lineDegrees.length > 0 ? 0 : calcLineActualSize(p, lineDegrees[0]), + }, fontSize: polygon.fontSize, stroke: '#1083E3', strokeWidth: 2, + textMode: textMode, }) - line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 - line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10 polygon.canvas.add(line) polygon.innerLines.push(line) }) @@ -1318,10 +1469,15 @@ const connectLinePoint = (polygon) => { missedLine.forEach((p) => { const line = new QLine([p.x1, p.y1, p.x2, p.y2], { - attributes: { roofId: polygon.id }, + attributes: { + roofId: polygon.id, + planeSize: calcLinePlaneSize(p), + actualSize: lineDegrees.length > 0 ? 0 : calcLineActualSize(p, lineDegrees[0]), + }, fontSize: polygon.fontSize, stroke: '#1083E3', strokeWidth: 2, + textMode: textMode, }) line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) @@ -1377,7 +1533,12 @@ const connectLinePoint = (polygon) => { stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.RIDGE, - attributes: { roofId: polygon.id }, + textMode: textMode, + attributes: { + roofId: polygon.id, + planeSize: calcLinePlaneSize(ridge), + actualSize: lineDegrees.length > 0 ? 0 : calcLineActualSize(ridge, lineDegrees[0]), + }, }) if (polygon.ridges.filter((r) => newRidge.x1 === r.x1 && newRidge.y1 === r.y1 && newRidge.x2 === r.x2 && newRidge.y2 === r.y2).length === 0) { polygon.canvas.remove(ridge) @@ -1399,7 +1560,13 @@ const connectLinePoint = (polygon) => { polygon.canvas.renderAll() } -const modifyRidge = (roof, canvas) => { +/** + * 외벽선 속성에 따라서 모양을 수정한다. + * @param roof + * @param canvas + * @param textMode + */ +const modifyRidge = (roof, canvas, textMode) => { const ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roof.id) const hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roof.id) @@ -1429,19 +1596,19 @@ const modifyRidge = (roof, canvas) => { if (currentRoof !== undefined) { switch (currentRoof.attributes.type) { case LINE_TYPE.WALLLINE.EAVES: - changeEavesRoof(currentRoof, canvas) + changeEavesRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.GABLE: - changeGableRoof(currentRoof, canvas) + changeGableRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.HIPANDGABLE: - changeHipAndGableRoof(currentRoof, canvas) + changeHipAndGableRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.JERKINHEAD: - changeJerkInHeadRoof(currentRoof, canvas) + changeJerkInHeadRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.WALL: - changeWallRoof(currentRoof, canvas) + changeWallRoof(currentRoof, canvas, textMode) break } } @@ -1469,19 +1636,19 @@ const modifyRidge = (roof, canvas) => { if (currentRoof !== undefined) { switch (currentRoof.attributes.type) { case LINE_TYPE.WALLLINE.EAVES: - changeEavesRoof(currentRoof, canvas) + changeEavesRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.GABLE: - changeGableRoof(currentRoof, canvas) + changeGableRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.HIPANDGABLE: - changeHipAndGableRoof(currentRoof, canvas) + changeHipAndGableRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.JERKINHEAD: - changeJerkInHeadRoof(currentRoof, canvas) + changeJerkInHeadRoof(currentRoof, canvas, textMode) break case LINE_TYPE.WALLLINE.WALL: - changeWallRoof(currentRoof, canvas) + changeWallRoof(currentRoof, canvas, textMode) break } } @@ -1500,8 +1667,9 @@ const getMaxRidge = (length) => { * 처마지붕으로 변경 * @param currentRoof * @param canvas + * @param textMode */ -const changeEavesRoof = (currentRoof, canvas) => { +const changeEavesRoof = (currentRoof, canvas, textMode) => { if (currentRoof.attributes.type === LINE_TYPE.WALLLINE.EAVES) { const roofId = currentRoof.attributes.roofId const wall = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId) @@ -1521,15 +1689,15 @@ const changeEavesRoof = (currentRoof, canvas) => { } }) - const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 - const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 - const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심 - const midWallY = (wallLine.y1 + wallLine.y2) / 2 // 벽의 Y 중심 - const alpha = midX - midWallX // 벽과 지붕의 X 거리 - const beta = midY - midWallY // 벽과 지붕의 Y 거리 - const hypotenuse = Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) // 벽과 지붕의 거리 - const hipX2 = Math.round(midX + -1 * (alpha / hypotenuse) * (currentRoof.length / 2)) - const hipY2 = Math.round(midY + -1 * (beta / hypotenuse) * (currentRoof.length / 2)) + const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심 + const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심 + const midWallX = Big(wallLine.x1).plus(wallLine.x).div(2) + const midWallY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) // 벽의 Y 중심 + const alpha = midX.minus(midWallX) // 벽과 지붕의 X 거리 + const beta = midY.minus(midWallY) // 벽과 지붕의 Y 거리 + const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() // 벽과 지붕의 거리 + const hipX2 = midX.plus(alpha.div(hypotenuse).times(Big(currentRoof.length).div(2)).neg()) + const hipY2 = midY.plus(beta.div(hypotenuse).times(Big(currentRoof.length).div(2)).neg()) const innerLines = canvas ?.getObjects() @@ -1607,8 +1775,8 @@ const changeEavesRoof = (currentRoof, canvas) => { const ridge = ridgeLines[0] if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) { ridge.set({ - x1: hipX2, - y1: hipY2, + x1: hipX2.toNumber(), + y1: hipY2.toNumber(), x2: ridge.x2, y2: ridge.y2, }) @@ -1618,13 +1786,14 @@ const changeEavesRoof = (currentRoof, canvas) => { ridge.set({ x1: ridge.x1, y1: ridge.y1, - x2: hipX2, - y2: hipY2, + x2: hipX2.toNumber(), + y2: hipY2.toNumber(), }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + //Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) + ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) } hipLines.forEach((hip) => { @@ -1638,47 +1807,51 @@ const changeEavesRoof = (currentRoof, canvas) => { const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree - const hip1 = new QLine([currentRoof.x1, currentRoof.y1, hipX2, hipY2], { + const hip1 = new QLine([currentRoof.x1, currentRoof.y1, hipX2.toNumber(), hipY2.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, + planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: hipX2.toNumber(), y2: hipY2.toNumber() }), + actualSize: + prevDegree === currentDegree + ? calcLineActualSize( + { x1: currentRoof.x1, y1: currentRoof.y1, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - currentDegree).toNumber(), + ) + : 0, }, }) canvas?.add(hip1) roof.innerLines.push(hip1) - const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 - const hip1Height = Math.round(hip1Base / Math.tan(((90 - currentDegree) * Math.PI) / 180)) - hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 - if (prevDegree === currentDegree) { - hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) - } - const hip2 = new QLine([currentRoof.x2, currentRoof.y2, hipX2, hipY2], { + const hip2 = new QLine([currentRoof.x2, currentRoof.y2, hipX2.toNumber(), hipY2.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: hipX2.toNumber(), y2: hipY2.toNumber() }), + actualSize: + currentDegree === nextDegree + ? calcLineActualSize( + { x1: currentRoof.x2, y1: currentRoof.y2, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - currentDegree).toNumber(), + ) + : 0, }, }) canvas?.add(hip2) roof.innerLines.push(hip2) - const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 - const hip2Height = Math.round(hip2Base / Math.tan(((90 - currentDegree) * Math.PI) / 180)) - hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 - if (currentDegree === nextDegree) { - hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) - } } } @@ -1686,17 +1859,17 @@ const changeEavesRoof = (currentRoof, canvas) => { * 박공지붕으로 변경 * @param currentRoof * @param canvas + * @param textMode */ -const changeGableRoof = (currentRoof, canvas) => { +const changeGableRoof = (currentRoof, canvas, textMode) => { if (currentRoof.attributes.type === LINE_TYPE.WALLLINE.GABLE) { const roofId = currentRoof.attributes.roofId - console.log('roofId', roofId) const roof = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.ROOF && object.id === roofId) let hipLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.HIP && object.attributes.roofId === roofId) let ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roofId) - const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 - const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 + const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심 + const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심 const innerLines = canvas ?.getObjects() @@ -1794,8 +1967,8 @@ const changeGableRoof = (currentRoof, canvas) => { const ridge = ridgeLines[0] if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) { ridge.set({ - x1: midX, - y1: midY, + x1: midX.toNumber(), + y1: midY.toNumber(), x2: ridge.x2, y2: ridge.y2, }) @@ -1805,33 +1978,36 @@ const changeGableRoof = (currentRoof, canvas) => { ridge.set({ x1: ridge.x1, y1: ridge.y1, - x2: midX, - y2: midY, + x2: midX.toNumber(), + y2: midY.toNumber(), }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) + ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) - let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], { + let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX.toNumber(), midY.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, attributes: { roofId: roofId, currentRoofId: currentRoof.id, + planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.toNumber(), y2: midY.toNumber() }), + actualSize: calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.toNumber(), y2: midY.toNumber() }, Big(90 - prevDegree)), }, }) canvas?.add(hip1) - const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 - const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) - hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 - hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) + // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + // const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + // hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + // hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) roof.innerLines.push(hip1) - let hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX, midY], { + let hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX.toNumber(), midY.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', @@ -1840,15 +2016,18 @@ const changeGableRoof = (currentRoof, canvas) => { attributes: { roofId: roofId, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.toNumber(), y2: midY.toNumber() }), + actualSize: calcLineActualSize( + { x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.toNumber(), y2: midY.toNumber() }, + Big(90 - nextDegree).toNumber(), + ), }, }) canvas?.add(hip2) - const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 - const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) - hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 - hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) + // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + // const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + // hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + // hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) roof.innerLines.push(hip2) canvas?.renderAll() } @@ -1859,8 +2038,9 @@ const changeGableRoof = (currentRoof, canvas) => { * 팔작지붕으로 변경 * @param currentRoof * @param canvas + * @param textMode */ -const changeHipAndGableRoof = (currentRoof, canvas) => { +const changeHipAndGableRoof = (currentRoof, canvas, textMode) => { if ( currentRoof.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE && currentRoof.attributes.width !== undefined && @@ -1884,19 +2064,35 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { } }) - const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 - const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 - const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심 - const midWallY = (wallLine.y1 + wallLine.y2) / 2 // 벽의 Y 중심 - const alpha = midX - midWallX // 벽과 지붕의 X 거리 - const beta = midY - midWallY // 벽과 지붕의 Y 거리 - const hypotenuse = Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) // 벽과 지붕의 거리 - const xWidth = Math.sign(midX - midWallX) * (alpha / hypotenuse) * currentRoof.attributes.width // 지붕의 X 너비 - const yWidth = Math.sign(midY - midWallY) * (beta / hypotenuse) * currentRoof.attributes.width // 지붕의 Y 너비 - const hipX2 = Math.sign(midX - midWallX) * (alpha / hypotenuse) * (currentRoof.length / 2) // 추녀마루의 X 너비 - const hipY2 = Math.sign(midY - midWallY) * (beta / hypotenuse) * (currentRoof.length / 2) // 추녀마루의 Y 너비 + const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심 + const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심 + const midWallX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2) // 벽의 X 중심 + const midWallY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) // 벽의 Y 중심 + const alpha = midX.minus(midWallX) // 벽과 지붕의 X 거리 + const beta = midY.minus(midWallY) // 벽과 지붕의 Y 거리 + // Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) + const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() // 벽과 지붕의 거리 + const xWidth = Big(Math.sign(midX.minus(midWallX).toNumber())) + .times(alpha.div(hypotenuse)) + .times(currentRoof.attributes.width) // 지붕의 X 너비 + const yWidth = Big(Math.sign(midY.minus(midWallY))) + .times(beta.div(hypotenuse)) + .times(currentRoof.attributes.width) // 지붕의 Y 너비 + const hipX2 = Big(Math.sign(midX.minus(midWallX).toNumber())) + .times(alpha.div(hypotenuse)) + .times(currentRoof.length / 2) // 추녀마루의 X 너비 + const hipY2 = Big(Math.sign(midY.minus(midWallY))) + .times(beta.div(hypotenuse)) + .times(currentRoof.length / 2) // 추녀마루의 Y 너비 - if (Math.sqrt(Math.pow(xWidth, 2) + Math.pow(yWidth, 2)) < Math.sqrt(Math.pow(hipX2, 2) + Math.pow(hipY2, 2))) { + // if (Math.sqrt(Math.pow(xWidth, 2) + Math.pow(yWidth, 2)) < Math.sqrt(Math.pow(hipX2, 2) + Math.pow(hipY2, 2))) { + if ( + xWidth + .pow(2) + .plus(yWidth.pow(2)) + .sqrt() + .lt(hipX2.pow(2).plus(hipY2.pow(2)).sqrt()) + ) { const innerLines = canvas ?.getObjects() .filter( @@ -1979,69 +2175,80 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { if (ridgeLines.length > 0) { const ridge = ridgeLines[0] if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) { - const signX = Math.sign(midX - ridge.x1) - const signY = Math.sign(midY - ridge.y1) + const signX = Math.sign(midX.minus(ridge.x1).toNumber()) + const signY = Math.sign(midY.minus(ridge.y1).toNumber()) ridge.set({ - x1: midX - signX * Math.abs(xWidth), - y1: midY - signY * Math.abs(yWidth), + x1: midX.minus(xWidth.abs().times(signX)).toNumber(), + y1: midY.minus(yWidth.abs().times(signY)).toNumber(), x2: ridge.x2, y2: ridge.y2, }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x1, y1: ridge.y1 } } if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) { - const signX = Math.sign(midX - ridge.x2) - const signY = Math.sign(midY - ridge.y2) + const signX = Math.sign(midX.minus(ridge.x2).toNumber()) + const signY = Math.sign(midY.minus(ridge.y2).toNumber()) ridge.set({ x1: ridge.x1, y1: ridge.y1, - x2: midX - signX * Math.abs(xWidth), - y2: midY - signY * Math.abs(yWidth), + x2: midX.minus(xWidth.abs().times(signX)).toNumber(), + y2: midY.minus(yWidth.abs().times(signY)).toNumber(), }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) + ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) } - const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoofId: currentRoof.id, - }, - }) const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree - const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 - const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) - hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 - hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) - canvas?.add(hip1) - roof.innerLines.push(hip1) - - const hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX + hipX2, midY + hipY2], { + const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX.plus(hipX2).toNumber(), midY.plus(hipY2).toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, + planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }), + actualSize: calcLineActualSize( + { x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }, + Big(90 - prevDegree).toNumber(), + ), }, }) - const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 - const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) - hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 - hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) + + // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + // const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + // hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + // hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) + canvas?.add(hip1) + roof.innerLines.push(hip1) + + const hip2 = new QLine([currentRoof.x2, currentRoof.y2, midX.plus(hipX2).toNumber(), midY.plus(hipY2).toNumber()], { + parentId: roof.id, + fontSize: roof.fontSize, + stroke: '#1083E3', + strokeWidth: 2, + name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, + attributes: { + roofId: roof.id, + currentRoofId: currentRoof.id, + planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }), + actualSize: calcLineActualSize( + { x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }, + Big(90 - nextDegree).toNumber(), + ), + }, + }) + // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + // const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + // hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + // hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) roof.innerLines.push(hip2) @@ -2049,8 +2256,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { hipLines.push(hip2) hipLines.forEach((hip) => { - const singHipX = Math.sign(hip.x1 - midWallX) - const singHipY = Math.sign(hip.y1 - midWallY) + const singHipX = Math.sign(hip.x1 - midWallX.toNumber()) + const singHipY = Math.sign(hip.y1 - midWallY.toNumber()) hip.set({ x1: hip.x1, @@ -2060,6 +2267,7 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { }) }) + const gableDegree = i === 0 ? prevDegree : nextDegree hipLines.forEach((hip, i) => { const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], { parentId: roof.id, @@ -2070,15 +2278,25 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - actualSize: 0, + textMode: textMode, + planeSize: calcLinePlaneSize({ + x1: hip.x2, + y1: hip.y2, + x2: currentRoof.attributes.ridgeCoordinate.x1, + y2: currentRoof.attributes.ridgeCoordinate.y1, + }), + actualSize: calcLineActualSize( + { x1: hip.x2, y1: hip.y2, x2: currentRoof.attributes.ridgeCoordinate.x1, y2: currentRoof.attributes.ridgeCoordinate.y1 }, + Big(90 - gableDegree).toNumber(), + ), }, }) - const gableDegree = i === 0 ? prevDegree : nextDegree - const gableBase = ((Math.abs(gableLine.x1 - gableLine.x2) + Math.abs(gableLine.y1 - gableLine.y2)) / 2) * 10 - const gableHeight = Math.round(gableBase / Math.tan(((90 - gableDegree) * Math.PI) / 180)) - gableLine.attributes.planeSize = - Math.round(Math.sqrt(Math.pow(gableLine.x1 - gableLine.x2, 2) + Math.pow(gableLine.y1 - gableLine.y2, 2))) * 10 - gableLine.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gableLine.attributes.planeSize, 2) + Math.pow(gableHeight, 2))) + + // const gableBase = ((Math.abs(gableLine.x1 - gableLine.x2) + Math.abs(gableLine.y1 - gableLine.y2)) / 2) * 10 + // const gableHeight = Math.round(gableBase / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + // gableLine.attributes.planeSize = + // Math.round(Math.sqrt(Math.pow(gableLine.x1 - gableLine.x2, 2) + Math.pow(gableLine.y1 - gableLine.y2, 2))) * 10 + // gableLine.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gableLine.attributes.planeSize, 2) + Math.pow(gableHeight, 2))) canvas?.add(gableLine) roof.innerLines.push(gableLine) }) @@ -2091,8 +2309,9 @@ const changeHipAndGableRoof = (currentRoof, canvas) => { * 반절처 지붕으로 변경 * @param currentRoof * @param canvas + * @param textMode */ -const changeJerkInHeadRoof = (currentRoof, canvas) => { +const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { if ( currentRoof.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD && currentRoof.attributes.width !== undefined && @@ -2120,21 +2339,36 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree - const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심 - const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심 - const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심 - const midWallY = (wallLine.y1 + wallLine.y2) / 2 // 벽의 Y 중심 - const alpha = midX - midWallX // 벽과 지붕의 X 거리 - const beta = midY - midWallY // 벽과 지붕의 Y 거리 - const hypotenuse = Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) // 벽과 지붕의 거리 - const xWidth = Math.sign(midX - midWallX) * (alpha / hypotenuse) * (currentRoof.attributes.width / 2) // 지붕의 X 너비 - const yWidth = Math.sign(midY - midWallY) * (beta / hypotenuse) * (currentRoof.attributes.width / 2) // 지붕의 Y 너비 - const addHipX2 = Math.sign(midX - midWallX) * (alpha / hypotenuse) * (currentRoof.length / 2) // 추녀마루의 X 너비 - const addHipY2 = Math.sign(midY - midWallY) * (beta / hypotenuse) * (currentRoof.length / 2) // 추녀마루의 Y 너비 + const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심 + const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심 + const midWallX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2) // 벽의 X 중심 + const midWallY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) // 벽의 Y 중심 + const alpha = midX.minus(midWallX) // 벽과 지붕의 X 거리 + const beta = midY.minus(midWallY) // 벽과 지붕의 Y 거리 + // Math.sqrt(Math.pow(alpha, 2) + Math.pow(beta, 2)) + const hypotenuse = alpha.pow(2).plus(beta.pow(2)).sqrt() // 벽과 지붕의 거리 + const xWidth = Big(Math.sign(midX.minus(midWallX).toNumber())) + .times(alpha.div(hypotenuse)) + .times(currentRoof.attributes.width / 2) // 지붕의 X 너비 + const yWidth = Big(Math.sign(midY.minus(midWallY))) + .times(beta.div(hypotenuse)) + .times(currentRoof.attributes.width / 2) // 지붕의 Y 너비 + const addHipX2 = Big(Math.sign(midX.minus(midWallX).toNumber())) + .times(alpha.div(hypotenuse)) + .times(currentRoof.length / 2) // 추녀마루의 X 너비 + const addHipY2 = Big(Math.sign(midY.minus(midWallY))) + .times(beta.div(hypotenuse)) + .times(currentRoof.length / 2) // 추녀마루의 Y 너비 let hipX2 = 0 let hipY2 = 0 - if (Math.sqrt(Math.pow(xWidth, 2) + Math.pow(yWidth, 2)) < Math.sqrt(Math.pow(addHipX2, 2) + Math.pow(addHipY2, 2))) { + // if (Math.sqrt(Math.pow(xWidth, 2) + Math.pow(yWidth, 2)) < Math.sqrt(Math.pow(addHipX2, 2) + Math.pow(addHipY2, 2))) { + if ( + xWidth + .pow(2) + .plus(yWidth.pow(2)) + .lt(addHipX2.pow(2).plus(addHipY2.pow(2))) + ) { // reDrawPolygon(roof, canvas) const innerLines = canvas @@ -2219,11 +2453,11 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { if (ridgeLines.length > 0) { const ridge = ridgeLines[0] if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) { - const signX = Math.sign(midX - ridge.x1) - const signY = Math.sign(midY - ridge.y1) + const signX = Math.sign(midX.minus(ridge.x1).toNumber()) + const signY = Math.sign(midY.minus(ridge.y1).toNumber()) ridge.set({ - x1: midX - signX * Math.abs(xWidth), - y1: midY - signY * Math.abs(yWidth), + x1: midX.minus(xWidth.abs().times(signX)).toNumber(), + y1: midY.minus(yWidth.abs().times(signY)).toNumber(), x2: ridge.x2, y2: ridge.y2, }) @@ -2238,60 +2472,80 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { ridge.set({ x1: ridge.x1, y1: ridge.y1, - x2: midX - signX * Math.abs(xWidth), - y2: midY - signY * Math.abs(yWidth), + x2: midX.minus(xWidth.abs().times(signX)).toNumber(), + y2: midY.minus(yWidth.abs().times(signY)).toNumber(), }) currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 } hipX2 = ridge.x2 hipY2 = ridge.y2 } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) + ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) } let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2 let hipY1 = (Math.sign(currentRoof.y1 - midY) * currentRoof.attributes.width) / 2 - const gable1 = new QLine([midX + hipX1, midY + hipY1, hipX2, hipY2], { + const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch) + const gable1 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2.toNumber(), hipY2.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.GABLE, + textMode: textMode, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - actualSize: 0, + planeSize: calcLinePlaneSize({ + x1: midX.plus(hipX1).toNumber(), + y1: midY.plus(hipY1).toNumber(), + x2: hipX2.toNumber(), + y2: hipY2.toNumber(), + }), + actualSize: calcLineActualSize( + { x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - gableDegree).toNumber(), + ), }, }) - const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch) - const gable1Base = ((Math.abs(gable1.x1 - gable1.x2) + Math.abs(gable1.y1 - gable1.y2)) / 2) * 10 - const gable1Height = Math.round(gable1Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) - gable1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable1.x1 - gable1.x2, 2) + Math.pow(gable1.y1 - gable1.y2, 2))) * 10 - gable1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable1.attributes.planeSize, 2) + Math.pow(gable1Height, 2))) + // const gable1Base = ((Math.abs(gable1.x1 - gable1.x2) + Math.abs(gable1.y1 - gable1.y2)) / 2) * 10 + // const gable1Height = Math.round(gable1Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + // gable1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable1.x1 - gable1.x2, 2) + Math.pow(gable1.y1 - gable1.y2, 2))) * 10 + // gable1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable1.attributes.planeSize, 2) + Math.pow(gable1Height, 2))) canvas?.add(gable1) roof.innerLines.push(gable1) hipX1 = (Math.sign(currentRoof.x2 - midX) * currentRoof.attributes.width) / 2 hipY1 = (Math.sign(currentRoof.y2 - midY) * currentRoof.attributes.width) / 2 - const gable2 = new QLine([midX + hipX1, midY + hipY1, hipX2, hipY2], { + const gable2 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2.toNumber(), hipY2.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.GABLE, + textMode: textMode, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - actualSize: 0, + planeSize: calcLinePlaneSize({ + x1: midX.plus(hipX1).toNumber(), + y1: midY.plus(hipY1).toNumber(), + x2: hipX2.toNumber(), + y2: hipY2.toNumber(), + }), + actualSize: calcLineActualSize( + { x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - gableDegree).toNumber(), + ), }, }) - const gable2Base = ((Math.abs(gable2.x1 - gable2.x2) + Math.abs(gable2.y1 - gable2.y2)) / 2) * 10 - const gable2Height = Math.round(gable2Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) - gable2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable2.x1 - gable2.x2, 2) + Math.pow(gable2.y1 - gable2.y2, 2))) * 10 - gable2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable2.attributes.planeSize, 2) + Math.pow(gable2Height, 2))) + // const gable2Base = ((Math.abs(gable2.x1 - gable2.x2) + Math.abs(gable2.y1 - gable2.y2)) / 2) * 10 + // const gable2Height = Math.round(gable2Base / Math.tan(((90 - gableDegree) * Math.PI) / 180)) + // gable2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable2.x1 - gable2.x2, 2) + Math.pow(gable2.y1 - gable2.y2, 2))) * 10 + // gable2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable2.attributes.planeSize, 2) + Math.pow(gable2Height, 2))) canvas?.add(gable2) roof.innerLines.push(gable2) @@ -2301,14 +2555,17 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.GABLE, + textMode: textMode, + visible: false, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - actualSize: 0, + planeSize: calcLinePlaneSize({ x1: gable1.x1, y1: gable1.y1, x2: gable2.x1, y2: gable2.y1 }), + actualSize: calcLinePlaneSize({ x1: gable1.x1, y1: gable1.y1, x2: gable2.x1, y2: gable2.y1 }), }, }) - gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 - gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 + // gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 + // gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10 canvas?.add(gable3) // roof.innerLines.push(gable3) @@ -2318,16 +2575,19 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, + visible: false, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - actualSize: 0, + planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: gable1.x1, y2: gable1.y1 }), + actualSize: calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: gable1.x1, y2: gable1.y1 }, Big(90 - prevDegree).toNumber()), }, }) - const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 - const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) - hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 - hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) + // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + // const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + // hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + // hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) canvas?.add(hip1) // roof.innerLines.push(hip1) @@ -2337,25 +2597,28 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { stroke: '#1083E3', strokeWidth: 2, name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, + visible: false, attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - actualSize: 0, + planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: gable2.x1, y2: gable2.y1 }), + actualSize: calcLineActualSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: gable2.x1, y2: gable2.y1 }, Big(90 - nextDegree).toNumber()), }, }) - const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 - const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) - hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 - hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) + // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + // const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + // hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + // hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) console.log('currentRoof.id : ', currentRoof.id) - hip1.set({ visible: false }) + // hip1.set({ visible: false }) hip1.setViewLengthText(false) - gable3.set({ visible: false }) + // gable3.set({ visible: false }) gable3.setViewLengthText(false) - hip2.set({ visible: false }) + // hip2.set({ visible: false }) hip2.setViewLengthText(false) } } @@ -2365,8 +2628,9 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => { * 벽지붕으로 변경 * @param currentRoof * @param canvas + * @param textMode */ -const changeWallRoof = (currentRoof, canvas) => { +const changeWallRoof = (currentRoof, canvas, textMode) => { const roofId = currentRoof.attributes.roofId const roof = canvas?.getObjects().find((object) => object.name === 'roof' && object.id === roofId) const roofLines = roof.lines @@ -2397,31 +2661,31 @@ const changeWallRoof = (currentRoof, canvas) => { (hip) => (hip.x1 === currentRoof.x1 && hip.y1 === currentRoof.y1) || (hip.x1 === currentRoof.x2 && hip.y1 === currentRoof.y2), ) - const wallMidX = (wallLine.x1 + wallLine.x2) / 2 - const wallMidY = (wallLine.y1 + wallLine.y2) / 2 - const roofMidX = (currentRoof.x1 + currentRoof.x2) / 2 - const roofMidY = (currentRoof.y1 + currentRoof.y2) / 2 + const wallMidX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2) + const wallMidY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) + const roofMidX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) + const roofMidY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) - const alpha = wallMidX - roofMidX === 0 ? 0 : wallMidX - roofMidX - const beta = wallMidY - roofMidY === 0 ? 0 : wallMidY - roofMidY + const alpha = wallMidX.minus(roofMidX) + const beta = wallMidY.minus(roofMidY) currentRoof.set({ - x1: currentRoof.x1 + alpha, - y1: currentRoof.y1 + beta, - x2: currentRoof.x2 + alpha, - y2: currentRoof.y2 + beta, + x1: alpha.plus(currentRoof.x1).toNumber(), + y1: beta.plus(currentRoof.y1).toNumber(), + x2: alpha.plus(currentRoof.x2).toNumber(), + y2: beta.plus(currentRoof.y2).toNumber(), }) prevRoof.set({ x1: prevRoof.x1, y1: prevRoof.y1, - x2: prevRoof.x2 + alpha, - y2: prevRoof.y2 + beta, + x2: alpha.plus(prevRoof.x2), + y2: beta.plus(prevRoof.y2), }) nextRoof.set({ - x1: nextRoof.x1 + alpha, - y1: nextRoof.y1 + beta, + x1: alpha.plus(nextRoof.x1), + y1: beta.plus(nextRoof.y1), x2: nextRoof.x2, y2: nextRoof.y2, }) @@ -2463,10 +2727,10 @@ const changeWallRoof = (currentRoof, canvas) => { const prevWidthY = prevSignY === 0 ? 0 : prevSignY * currentRoof.attributes.width const nextWidthX = nextSignX === 0 ? 0 : nextSignX * currentRoof.attributes.width const nextWidthY = nextSignY === 0 ? 0 : nextSignY * currentRoof.attributes.width - const prevX2 = prevRoof.x2 - prevWidthX - const prevY2 = prevRoof.y2 - prevWidthY - const nextX1 = nextRoof.x1 + nextWidthX - const nextY1 = nextRoof.y1 + nextWidthY + const prevX2 = Big(prevRoof.x2).minus(prevWidthX) + const prevY2 = Big(prevRoof.y2).minus(prevWidthY) + const nextX1 = Big(nextRoof.x1).plus(nextWidthX) + const nextY1 = Big(nextRoof.y1).plus(nextWidthY) currentRoof.set({ x1: wallLine.x1, @@ -2478,54 +2742,126 @@ const changeWallRoof = (currentRoof, canvas) => { prevRoof.set({ x1: prevRoof.x1, y1: prevRoof.y1, - x2: prevX2, - y2: prevY2, + x2: prevX2.toNumber(), + y2: prevY2.toNumber(), }) nextRoof.set({ - x1: nextX1, - y1: nextY1, + x1: nextX1.toNumber(), + y1: nextY1.toNumber(), x2: nextRoof.x2, y2: nextRoof.y2, }) - const addPrevWallLine1 = new QLine([prevX2, prevY2, wallLine.x1 - prevWidthX, wallLine.y1 - prevWidthY], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: 'roofLine', - attributes: { roofId: roofId, type: LINE_TYPE.WALLLINE.ETC }, - }) - - const addPrevWallLine2 = new QLine( - [addPrevWallLine1.x2, addPrevWallLine1.y2, addPrevWallLine1.x2 + prevWidthX, addPrevWallLine1.y2 + prevWidthY], + const addPrevWallLine1 = new QLine( + [prevX2.toNumber(), prevY2.toNumber(), Big(wallLine.x1).minus(prevWidthX).toNumber(), Big(wallLine.y1).minus(prevWidthY).toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: 'roofLine', - attributes: { roofId: roofId, type: LINE_TYPE.WALLLINE.ETC }, + textMode: textMode, + attributes: { + roofId: roofId, + type: LINE_TYPE.WALLLINE.ETC, + planeSize: calcLinePlaneSize({ + x1: prevX2.toNumber(), + y1: prevY2.toNumber(), + x2: Big(wallLine.x1).minus(prevWidthX).toNumber(), + y2: Big(wallLine.y1).minus(prevWidthY).toNumber(), + }), + actualSize: calcLinePlaneSize({ + x1: prevX2.toNumber(), + y1: prevY2.toNumber(), + x2: Big(wallLine.x1).minus(prevWidthX).toNumber(), + y2: Big(wallLine.y1).minus(prevWidthY).toNumber(), + }), + }, }, ) - const addNextWallLine1 = new QLine([wallLine.x2, wallLine.y2, wallLine.x2 + nextWidthX, wallLine.y2 + nextWidthY], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: 'roofLine', - attributes: { roofId: roofId, type: LINE_TYPE.WALLLINE.ETC }, - }) + const addPrevWallLine2 = new QLine( + [ + addPrevWallLine1.x2, + addPrevWallLine1.y2, + Big(addPrevWallLine1.x2).plus(prevWidthX).toNumber(), + Big(addPrevWallLine1.y2).plus(prevWidthY).toNumber(), + ], + { + parentId: roof.id, + fontSize: roof.fontSize, + stroke: '#1083E3', + strokeWidth: 2, + name: 'roofLine', + textMode: textMode, + attributes: { + roofId: roofId, + type: LINE_TYPE.WALLLINE.ETC, + planeSize: calcLinePlaneSize({ + x1: addPrevWallLine1.x2, + y1: addPrevWallLine1.y2, + x2: Big(addPrevWallLine1.x2).plus(prevWidthX).toNumber(), + y2: Big(addPrevWallLine1.y2).plus(prevWidthY).toNumber(), + }), + actualSize: calcLinePlaneSize({ + x1: addPrevWallLine1.x2, + y1: addPrevWallLine1.y2, + x2: Big(addPrevWallLine1.x2).plus(prevWidthX).toNumber(), + y2: Big(addPrevWallLine1.y2).plus(prevWidthY).toNumber(), + }), + }, + }, + ) - const addNextWallLine2 = new QLine([addNextWallLine1.x2, addNextWallLine1.y2, nextX1, nextY1], { + const addNextWallLine1 = new QLine( + [wallLine.x2, wallLine.y2, Big(wallLine.x2).plus(nextWidthX).toNumber(), Big(wallLine.y2).plus(nextWidthY).toNumber()], + { + parentId: roof.id, + fontSize: roof.fontSize, + stroke: '#1083E3', + strokeWidth: 2, + name: 'roofLine', + textMode: textMode, + attributes: { + roofId: roofId, + type: LINE_TYPE.WALLLINE.ETC, + planeSize: calcLinePlaneSize({ + x1: wallLine.x2, + y1: wallLine.y2, + x2: Big(wallLine.x2).plus(nextWidthX).toNumber(), + y2: Big(wallLine.y2).plus(nextWidthY).toNumber(), + }), + actualSize: calcLinePlaneSize({ + x1: wallLine.x2, + y1: wallLine.y2, + }), + }, + }, + ) + + const addNextWallLine2 = new QLine([addNextWallLine1.x2, addNextWallLine1.y2, nextX1.toNumber(), nextY1.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', strokeWidth: 2, name: 'roofLine', - attributes: { roofId: roofId, type: LINE_TYPE.WALLLINE.ETC }, + attributes: { + roofId: roofId, + type: LINE_TYPE.WALLLINE.ETC, + planeSize: calcLinePlaneSize({ + x1: addNextWallLine1.x2, + y1: addNextWallLine1.y2, + x2: nextX1.toNumber(), + y2: nextY1.toNumber(), + }), + actualSize: calcLinePlaneSize({ + x1: addNextWallLine1.x2, + y1: addNextWallLine1.y2, + x2: nextX1.toNumber(), + y2: nextY1.toNumber(), + }), + }, }) canvas?.renderAll() @@ -2541,31 +2877,54 @@ const changeWallRoof = (currentRoof, canvas) => { if (ridgeLines.length > 0) { const ridge = ridgeLines[0] if (ridge.x1 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y1 === currentRoof.attributes.ridgeCoordinate.y1) { - const diffX = ridge.x1 - wallMidX === 0 ? 0 : ridge.x1 - wallMidX - const diffY = ridge.y1 - wallMidY === 0 ? 0 : ridge.y1 - wallMidY + const diffX = Big(ridge.x1).minus(wallMidX) + const diffY = Big(ridge.y1).minus(wallMidY) ridge.set({ - x1: ridge.x1 - diffX, - y1: ridge.y1 - diffY, + x1: Big(ridge.x1).minus(diffX).toNumber(), + y1: Big(ridge.y1).minus(diffY).toNumber(), x2: ridge.x2, y2: ridge.y2, }) } if (ridge.x2 === currentRoof.attributes.ridgeCoordinate.x1 && ridge.y2 === currentRoof.attributes.ridgeCoordinate.y1) { - const diffX = ridge.x2 - wallMidX === 0 ? 0 : ridge.x2 - wallMidX - const diffY = ridge.y2 - wallMidY === 0 ? 0 : ridge.y2 - wallMidY + const diffX = Big(ridge.x2).minus(wallMidX) + const diffY = Big(ridge.y2).minus(wallMidY) ridge.set({ x1: ridge.x1, y1: ridge.y1, - x2: ridge.x2 - diffX, - y2: ridge.y2 - diffY, + x2: Big(ridge.x2).minus(diffX).toNumber(), + y2: Big(ridge.y2).minus(diffY).toNumber(), }) } - ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) - ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + // ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10) + ridge.attributes.planeSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) + ridge.attributes.actualSize = calcLinePlaneSize({ x1: ridge.x1, y1: ridge.y1, x2: ridge.x2, y2: ridge.y2 }) - let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], { + let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX.toNumber(), wallMidY.toNumber()], { + parentId: roof.id, + fontSize: roof.fontSize, + stroke: '#1083E3', + strokeWidth: 2, + name: LINE_TYPE.SUBLINE.HIP, + textMode: textMode, + attributes: { + roofId: roof.id, + currentRoofId: currentRoof.id, + planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }), + actualSize: calcLineActualSize( + { x1: currentRoof.x1, y1: currentRoof.y1, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }, + Big(90 - prevDegree).toNumber(), + ), + }, + }) + // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 + // const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) + // hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 + // hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) + + let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX.toNumber(), wallMidY.toNumber()], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', @@ -2574,31 +2933,17 @@ const changeWallRoof = (currentRoof, canvas) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - actualSize: 0, + planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }), + actualSize: calcLineActualSize( + { x1: currentRoof.x2, y1: currentRoof.y2, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }, + Big(90 - nextDegree).toNumber(), + ), }, }) - const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 - const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180)) - hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10 - hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2))) - - let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX, wallMidY], { - parentId: roof.id, - fontSize: roof.fontSize, - stroke: '#1083E3', - strokeWidth: 2, - name: LINE_TYPE.SUBLINE.HIP, - attributes: { - roofId: roof.id, - currentRoofId: currentRoof.id, - planeSize: currentRoof.length, - actualSize: currentRoof.length, - }, - }) - const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 - const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) - hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 - hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) + // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 + // const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180)) + // hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10 + // hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip1) canvas?.add(hip2) roof.innerLines.push(hip1) @@ -2723,12 +3068,13 @@ const reDrawPolygon = (polygon, canvas) => { line.attributes = l.attributes } }) - const lineLength = Math.sqrt( - Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), - ) + // const lineLength = Math.sqrt( + // Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2), + // ) + const lineLength = calcLinePlaneSize({ x1: line.x1, y1: line.y1, x2: line.x2, y2: line.y2 }) if (line.attributes !== undefined) { line.attributes.planeSize = lineLength - line.attributes.actualSize = line + line.attributes.actualSize = lineLength } else { line.attributes = { roofId: newPolygon.id, @@ -2744,7 +3090,13 @@ const reDrawPolygon = (polygon, canvas) => { return newPolygon } -const drawCenterLine = (roof, canvas) => { +/** + * 지붕의 centerLine을 그린다. + * @param roof + * @param canvas + * @param textMode + */ +const drawCenterLine = (roof, canvas, textMode) => { //현재 지붕의 centerLine을 다 지운다. canvas .getObjects() @@ -3083,3 +3435,26 @@ export const inPolygon = (polygonPoints, rectPoints) => { return allPointsInsidePolygon && noPolygonPointsInsideRect } + +/** + * 포인트를 기준으로 선의 길이를 구한다. 선의 길이는 10을 곱하여 사용한다. + * @param points {{x1, y1, x2, y2}} + */ +export const calcLinePlaneSize = (points) => { + const { x1, y1, x2, y2 } = points + return Big(x1).minus(x2).pow(2).plus(Big(y1).minus(y2).pow(2)).sqrt().abs().times(10).round().toNumber() +} + +/** + * 포인트와 기울기를 기준으로 선의 길이를 구한다. + * @param points + * @param degree + * @returns number + */ +export const calcLineActualSize = (points, degree) => { + const { x1, y1, x2, y2 } = points + const planeSize = calcLinePlaneSize(points) + const height = Big(Math.tan(Big(degree).times(Math.PI / 180))).times(planeSize) + // Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2))) + return Big(planeSize).pow(2).plus(height.pow(2)).sqrt().abs().round().toNumber() +} From 84323b2c1d5bff55fe8e27f30f0c0faf887586f5 Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Sun, 9 Feb 2025 10:36:17 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/qpolygon-utils.js | 225 ++++++++++++++++++++++++++++++------- 1 file changed, 184 insertions(+), 41 deletions(-) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 8632cd54..e7e2de42 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -11,7 +11,7 @@ import Big from 'big.js' const TWO_PI = Math.PI * 2 export const defineQPloygon = () => { - fabric.QPolygon.fromObject = function (object, callback) { + fabric.QPolygon.fromObject = function(object, callback) { fabric.Object._fromObject('QPolygon', object, callback, 'points') } } @@ -631,7 +631,7 @@ export const drawGabledRoof = (roofId, canvas, settingModalFirstOptions) => { const adjust = Math.sqrt( Math.pow(Math.round(Math.abs(pitchSizeLine.x1 - pitchSizeLine.x2) * 10), 2) + - Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), + Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), ) const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree const height = Math.tan(currentDegree * (Math.PI / 180)) * adjust @@ -664,7 +664,7 @@ export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => { if (shedDegree === 0) { shedDegree = getDegreeByChon(shedChon) } - const getHeight = function (adjust, degree) { + const getHeight = function(adjust, degree) { return Math.tan(degree * (Math.PI / 180)) * adjust } @@ -832,7 +832,10 @@ const drawRidge = (roof, canvas, textMode) => { .filter((roof) => isInnerLine(prevRoof, currentRoof, nextRoof, roof)) .forEach((innerRoof) => { const vector1 = { x: currentX2.minus(currentX1), y: currentY2.minus(currentY1) } - const vector2 = { x: Big(innerRoof.x2).minus(Big(innerRoof.x1)), y: Big(innerRoof.y2).minus(Big(innerRoof.y1)) } + const vector2 = { + x: Big(innerRoof.x2).minus(Big(innerRoof.x1)), + y: Big(innerRoof.y2).minus(Big(innerRoof.y1)), + } const dotProduct = vector1.x.times(vector2.x).plus(vector1.y.times(vector2.y)) const magnitude1 = vector1.x.pow(2).plus(vector1.y.pow(2)).sqrt() @@ -857,7 +860,12 @@ const drawRidge = (roof, canvas, textMode) => { .sqrt() .div(10) console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ x1: nextRoof.x1, y1: nextRoof.y1, x2: nextRoof.x2, y2: nextRoof.y2 })) + console.log('check ridgeMinLength', calcLinePlaneSize({ + x1: nextRoof.x1, + y1: nextRoof.y1, + x2: nextRoof.x2, + y2: nextRoof.y2, + })) } if (currentAngle === 90 || currentAngle === 270) { currentY2 = innerRoof.y1 @@ -870,7 +878,12 @@ const drawRidge = (roof, canvas, textMode) => { .sqrt() .div(10) console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ x1: nextRoof.x1, y1: nextRoof.y1, x2: innerRoof.x2, y2: nextRoof.y2 })) + console.log('check ridgeMinLength', calcLinePlaneSize({ + x1: nextRoof.x1, + y1: nextRoof.y1, + x2: innerRoof.x2, + y2: nextRoof.y2, + })) } } if (Math.abs(currentAngle - ibAngle) === 0) { @@ -885,7 +898,12 @@ const drawRidge = (roof, canvas, textMode) => { .sqrt() .div(10) console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ x1: prevRoof.x1, y1: prevRoof.y1, x2: prevRoof.x2, y2: innerRoof.y1 })) + console.log('check ridgeMinLength', calcLinePlaneSize({ + x1: prevRoof.x1, + y1: prevRoof.y1, + x2: prevRoof.x2, + y2: innerRoof.y1, + })) } if (currentAngle === 90 || currentAngle === 270) { currentY1 = innerRoof.y2 @@ -898,7 +916,12 @@ const drawRidge = (roof, canvas, textMode) => { .sqrt() .div(10) console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ x1: prevRoof.x1, y1: prevRoof.y1, x2: innerRoof.x2, y2: prevRoof.y2 })) + console.log('check ridgeMinLength', calcLinePlaneSize({ + x1: prevRoof.x1, + y1: prevRoof.y1, + x2: innerRoof.x2, + y2: prevRoof.y2, + })) } } } @@ -1005,10 +1028,20 @@ const drawRidge = (roof, canvas, textMode) => { // 시작점에서 종료점까지의 평면길이 //startXPoint.minus(endXPoint).abs().pow(2).plus(startYPoint.minus(endYPoint).abs().pow(2)).sqrt() const hypo = Big( - calcLinePlaneSize({ x1: startXPoint.toNumber(), y1: startYPoint.toNumber(), x2: endXPoint.toNumber(), y2: endYPoint.toNumber() }), + calcLinePlaneSize({ + x1: startXPoint.toNumber(), + y1: startYPoint.toNumber(), + x2: endXPoint.toNumber(), + y2: endYPoint.toNumber(), + }), ).div(10) // 현재 지붕선과 마주하는 지붕선을 잇는 선분의 교차점까지의 길이 - const intersectLength = Big(calcLinePlaneSize({ x1: midX.toNumber(), y1: midY.toNumber(), x2: intersectLine.x, y2: intersectLine.y })).div(10) + const intersectLength = Big(calcLinePlaneSize({ + x1: midX.toNumber(), + y1: midY.toNumber(), + x2: intersectLine.x, + y2: intersectLine.y, + })).div(10) //마주하는 지붕선까지의 길이가 현재 지붕선의 이전, 다음 지붕선의 길이보다 작을때 if (intersectLength.lt(Big(prevRoof.attributes.planeSize).div(10)) && intersectLength.lt(Big(nextRoof.attributes.planeSize).div(10))) { endXPoint = startXPoint @@ -1190,10 +1223,20 @@ const drawHips = (roof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: ridgeCoordinate.x1, + y2: ridgeCoordinate.y1, + }), actualSize: prevDegree === currentDegree - ? calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }, currentDegree) + ? calcLineActualSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: ridgeCoordinate.x1, + y2: ridgeCoordinate.y1, + }, currentDegree) : 0, }, }) @@ -1215,10 +1258,20 @@ const drawHips = (roof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: ridgeCoordinate.x1, + y2: ridgeCoordinate.y1, + }), actualSize: prevDegree === currentDegree - ? calcLineActualSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: ridgeCoordinate.x1, y2: ridgeCoordinate.y1 }, currentDegree) + ? calcLineActualSize({ + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: ridgeCoordinate.x1, + y2: ridgeCoordinate.y1, + }, currentDegree) : 0, }, }) @@ -1293,10 +1346,20 @@ const drawHips = (roof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgePoints.x, y2: ridgePoints.y }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: ridgePoints.x, + y2: ridgePoints.y, + }), actualSize: prevDegree === currentDegree - ? calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: ridgePoints.x, y2: ridgePoints.y }, currentDegree) + ? calcLineActualSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: ridgePoints.x, + y2: ridgePoints.y, + }, currentDegree) : 0, }, }) @@ -1379,7 +1442,7 @@ const connectLinePoint = (polygon, canvas, textMode) => { .reduce((prev, current) => { if (prev !== undefined) { return Math.sqrt(Math.pow(Math.abs(current.x - p1.x), 2) + Math.pow(Math.abs(current.y - p1.y), 2)) < - Math.sqrt(Math.pow(Math.abs(prev.x - p1.x), 2) + Math.pow(Math.abs(prev.y - p1.y), 2)) + Math.sqrt(Math.pow(Math.abs(prev.x - p1.x), 2) + Math.pow(Math.abs(prev.y - p1.y), 2)) ? current : prev } else { @@ -1691,7 +1754,7 @@ const changeEavesRoof = (currentRoof, canvas, textMode) => { const midX = Big(currentRoof.x1).plus(Big(currentRoof.x2)).div(2) // 지붕의 X 중심 const midY = Big(currentRoof.y1).plus(Big(currentRoof.y2)).div(2) // 지붕의 Y 중심 - const midWallX = Big(wallLine.x1).plus(wallLine.x).div(2) + const midWallX = Big(wallLine.x1).plus(Big(wallLine.x2)).div(2) const midWallY = Big(wallLine.y1).plus(Big(wallLine.y2)).div(2) // 벽의 Y 중심 const alpha = midX.minus(midWallX) // 벽과 지붕의 X 거리 const beta = midY.minus(midWallY) // 벽과 지붕의 Y 거리 @@ -1817,13 +1880,18 @@ const changeEavesRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: hipX2.toNumber(), y2: hipY2.toNumber() }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: hipX2.toNumber(), + y2: hipY2.toNumber(), + }), actualSize: prevDegree === currentDegree ? calcLineActualSize( - { x1: currentRoof.x1, y1: currentRoof.y1, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, - Big(90 - currentDegree).toNumber(), - ) + { x1: currentRoof.x1, y1: currentRoof.y1, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - currentDegree).toNumber(), + ) : 0, }, }) @@ -1840,13 +1908,18 @@ const changeEavesRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: hipX2.toNumber(), y2: hipY2.toNumber() }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: hipX2.toNumber(), + y2: hipY2.toNumber(), + }), actualSize: currentDegree === nextDegree ? calcLineActualSize( - { x1: currentRoof.x2, y1: currentRoof.y2, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, - Big(90 - currentDegree).toNumber(), - ) + { x1: currentRoof.x2, y1: currentRoof.y2, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - currentDegree).toNumber(), + ) : 0, }, }) @@ -1996,8 +2069,18 @@ const changeGableRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roofId, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.toNumber(), y2: midY.toNumber() }), - actualSize: calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.toNumber(), y2: midY.toNumber() }, Big(90 - prevDegree)), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: midX.toNumber(), + y2: midY.toNumber(), + }), + actualSize: calcLineActualSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: midX.toNumber(), + y2: midY.toNumber(), + }, Big(90 - prevDegree)), }, }) canvas?.add(hip1) @@ -2016,7 +2099,12 @@ const changeGableRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roofId, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.toNumber(), y2: midY.toNumber() }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: midX.toNumber(), + y2: midY.toNumber(), + }), actualSize: calcLineActualSize( { x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.toNumber(), y2: midY.toNumber() }, Big(90 - nextDegree).toNumber(), @@ -2213,9 +2301,19 @@ const changeHipAndGableRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: midX.plus(hipX2).toNumber(), + y2: midY.plus(hipY2).toNumber(), + }), actualSize: calcLineActualSize( - { x1: currentRoof.x1, y1: currentRoof.y1, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }, + { + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: midX.plus(hipX2).toNumber(), + y2: midY.plus(hipY2).toNumber(), + }, Big(90 - prevDegree).toNumber(), ), }, @@ -2238,9 +2336,19 @@ const changeHipAndGableRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: midX.plus(hipX2).toNumber(), + y2: midY.plus(hipY2).toNumber(), + }), actualSize: calcLineActualSize( - { x1: currentRoof.x2, y1: currentRoof.y2, x2: midX.plus(hipX2).toNumber(), y2: midY.plus(hipY2).toNumber() }, + { + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: midX.plus(hipX2).toNumber(), + y2: midY.plus(hipY2).toNumber(), + }, Big(90 - nextDegree).toNumber(), ), }, @@ -2286,7 +2394,12 @@ const changeHipAndGableRoof = (currentRoof, canvas, textMode) => { y2: currentRoof.attributes.ridgeCoordinate.y1, }), actualSize: calcLineActualSize( - { x1: hip.x2, y1: hip.y2, x2: currentRoof.attributes.ridgeCoordinate.x1, y2: currentRoof.attributes.ridgeCoordinate.y1 }, + { + x1: hip.x2, + y1: hip.y2, + x2: currentRoof.attributes.ridgeCoordinate.x1, + y2: currentRoof.attributes.ridgeCoordinate.y1, + }, Big(90 - gableDegree).toNumber(), ), }, @@ -2505,7 +2618,12 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { y2: hipY2.toNumber(), }), actualSize: calcLineActualSize( - { x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + { + x1: midX.plus(hipX1).toNumber(), + y1: midY.plus(hipY1).toNumber(), + x2: hipX2.toNumber(), + y2: hipY2.toNumber(), + }, Big(90 - gableDegree).toNumber(), ), }, @@ -2537,7 +2655,12 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { y2: hipY2.toNumber(), }), actualSize: calcLineActualSize( - { x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + { + x1: midX.plus(hipX1).toNumber(), + y1: midY.plus(hipY1).toNumber(), + x2: hipX2.toNumber(), + y2: hipY2.toNumber(), + }, Big(90 - gableDegree).toNumber(), ), }, @@ -2581,7 +2704,12 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { roofId: roof.id, currentRoofId: currentRoof.id, planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: gable1.x1, y2: gable1.y1 }), - actualSize: calcLineActualSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: gable1.x1, y2: gable1.y1 }, Big(90 - prevDegree).toNumber()), + actualSize: calcLineActualSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: gable1.x1, + y2: gable1.y1, + }, Big(90 - prevDegree).toNumber()), }, }) // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 @@ -2603,7 +2731,12 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { roofId: roof.id, currentRoofId: currentRoof.id, planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: gable2.x1, y2: gable2.y1 }), - actualSize: calcLineActualSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: gable2.x1, y2: gable2.y1 }, Big(90 - nextDegree).toNumber()), + actualSize: calcLineActualSize({ + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: gable2.x1, + y2: gable2.y1, + }, Big(90 - nextDegree).toNumber()), }, }) // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 @@ -2912,7 +3045,12 @@ const changeWallRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: wallMidX.toNumber(), + y2: wallMidY.toNumber(), + }), actualSize: calcLineActualSize( { x1: currentRoof.x1, y1: currentRoof.y1, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }, Big(90 - prevDegree).toNumber(), @@ -2933,7 +3071,12 @@ const changeWallRoof = (currentRoof, canvas, textMode) => { attributes: { roofId: roof.id, currentRoofId: currentRoof.id, - planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }), + planeSize: calcLinePlaneSize({ + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: wallMidX.toNumber(), + y2: wallMidY.toNumber(), + }), actualSize: calcLineActualSize( { x1: currentRoof.x2, y1: currentRoof.y2, x2: wallMidX.toNumber(), y2: wallMidY.toNumber() }, Big(90 - nextDegree).toNumber(), @@ -3334,7 +3477,7 @@ const drawCenterLine = (roof, canvas, textMode) => { const adjust = Math.sqrt( Math.pow(Math.round(Math.abs(pitchSizeLine.x1 - pitchSizeLine.x2) * 10), 2) + - Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), + Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), ) const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree const height = Math.tan(currentDegree * (Math.PI / 180)) * adjust From c667e44596a4e5c1c894e8879ee7a74cfa3ebb8b Mon Sep 17 00:00:00 2001 From: Jaeyoung Lee Date: Sun, 9 Feb 2025 16:01:22 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EB=8D=AE=EA=B0=9C=20p?= =?UTF-8?q?oints=20=EC=A1=B0=EC=A0=95=20=EB=B0=8F=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 10 +- src/util/qpolygon-utils.js | 245 +++++++++++++------------------------ 2 files changed, 95 insertions(+), 160 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index f973eba3..539b8af4 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1815,9 +1815,13 @@ export function useMode() { } }) - wall.attributes = { - roofId: roof.id, - } + wall.set({ + originX: 'center', + originY: 'center', + attributes: { + roofId: roof.id, + }, + }) //외벽선 삭제 canvas diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 97f4f88d..91116ee8 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -11,7 +11,7 @@ import Big from 'big.js' const TWO_PI = Math.PI * 2 export const defineQPloygon = () => { - fabric.QPolygon.fromObject = function(object, callback) { + fabric.QPolygon.fromObject = function (object, callback) { fabric.Object._fromObject('QPolygon', object, callback, 'points') } } @@ -632,7 +632,7 @@ export const drawGabledRoof = (roofId, canvas, settingModalFirstOptions) => { const adjust = Math.sqrt( Math.pow(Math.round(Math.abs(pitchSizeLine.x1 - pitchSizeLine.x2) * 10), 2) + - Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), + Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), ) const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree const height = Math.tan(currentDegree * (Math.PI / 180)) * adjust @@ -665,7 +665,7 @@ export const drawShedRoof = (roofId, canvas, settingModalFirstOptions) => { if (shedDegree === 0) { shedDegree = getDegreeByChon(shedChon) } - const getHeight = function(adjust, degree) { + const getHeight = function (adjust, degree) { return Math.tan(degree * (Math.PI / 180)) * adjust } @@ -764,7 +764,7 @@ export const drawRidgeRoof = (roofId, canvas, settingModalFirstOptions) => { drawHips(roof, canvas, textMode) connectLinePoint(roof, canvas, textMode) modifyRidge(roof, canvas, textMode) - // drawCenterLine(roof, canvas, textMode) + drawCenterLine(roof, canvas, textMode) } /** @@ -776,8 +776,6 @@ export const drawRidgeRoof = (roofId, canvas, settingModalFirstOptions) => { */ const drawRidge = (roof, canvas, textMode) => { console.log('roof.lines : ', roof.lines) - console.log('textMode : ', textMode) - const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines // 외벽의 라인 const roofLines = roof.lines // 지붕의 라인 let ridgeRoof = [] @@ -802,7 +800,6 @@ const drawRidge = (roof, canvas, textMode) => { // 지붕의 길이가 짧은 순으로 정렬 ridgeRoof.sort((a, b) => a.length - b.length) - console.log('마루 순서 : ', ridgeRoof.map((item) => item.length).join(',')) ridgeRoof.forEach((item) => { if (getMaxRidge(roofLines.length) > roof.ridges.length) { @@ -826,8 +823,6 @@ const drawRidge = (roof, canvas, textMode) => { let ridgeMaxLength = Big(Math.max(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize)).div(10) let ridgeMinLength = Big(Math.min(prevRoof.attributes.planeSize, nextRoof.attributes.planeSize)).div(10) - console.log('ridgeMinLength : ', ridgeMinLength.toNumber(), 'ridgeMaxLength : ', ridgeMaxLength.toNumber()) - const currentAngle = Math.atan2(currentY2.minus(currentY1).toNumber(), currentX2.minus(currentX1).toNumber()) * (180 / Math.PI) anotherRoof .filter((roof) => isInnerLine(prevRoof, currentRoof, nextRoof, roof)) @@ -860,13 +855,6 @@ const drawRidge = (roof, canvas, textMode) => { .plus(Big(nextRoof.y1).minus(Big(nextRoof.y2)).times(10).round().pow(2)) .sqrt() .div(10) - console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ - x1: nextRoof.x1, - y1: nextRoof.y1, - x2: nextRoof.x2, - y2: nextRoof.y2, - })) } if (currentAngle === 90 || currentAngle === 270) { currentY2 = innerRoof.y1 @@ -878,13 +866,6 @@ const drawRidge = (roof, canvas, textMode) => { .plus(Big(nextRoof.y1).minus(Big(nextRoof.y2)).times(10).round().pow(2)) .sqrt() .div(10) - console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ - x1: nextRoof.x1, - y1: nextRoof.y1, - x2: innerRoof.x2, - y2: nextRoof.y2, - })) } } if (Math.abs(currentAngle - ibAngle) === 0) { @@ -898,13 +879,6 @@ const drawRidge = (roof, canvas, textMode) => { .plus(Big(prevRoof.y1).minus(Big(innerRoof.y1)).times(10).round().pow(2)) .sqrt() .div(10) - console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ - x1: prevRoof.x1, - y1: prevRoof.y1, - x2: prevRoof.x2, - y2: innerRoof.y1, - })) } if (currentAngle === 90 || currentAngle === 270) { currentY1 = innerRoof.y2 @@ -916,13 +890,6 @@ const drawRidge = (roof, canvas, textMode) => { .plus(Big(prevRoof.y2).minus(prevRoof.y2).times(10).round().pow(2)) .sqrt() .div(10) - console.log('ridgeMinLength : ', ridgeMinLength.toNumber()) - console.log('check ridgeMinLength', calcLinePlaneSize({ - x1: prevRoof.x1, - y1: prevRoof.y1, - x2: innerRoof.x2, - y2: prevRoof.y2, - })) } } } @@ -1012,19 +979,8 @@ const drawRidge = (roof, canvas, textMode) => { const diffX = Big(intersectLine.x).minus(startXPoint).round(1).abs().lt(1) ? Big(0) : Big(intersectLine.x).minus(startXPoint).round(1) const diffY = Big(intersectLine.y).minus(startYPoint).round(1).abs().lt(1) ? Big(0) : Big(intersectLine.y).minus(startYPoint).round(1) // 시작점에서 ridgeBaseLength 만큼 떨어진 지점까지 용마루 길이로 본다. - console.log('diffX : ', diffX.toNumber(), 'diffY : ', diffY.toNumber()) - console.log('ridgeBaseLength : ', ridgeBaseLength.toNumber()) - console.log('Math.sign(diffX.toNumber()) : ', Math.sign(diffX.toNumber()), diffX.abs().minus(ridgeBaseLength).toNumber()) - console.log('Math.sign(diffY.toNumber()) : ', Math.sign(diffY.toNumber()), diffY.abs().minus(ridgeBaseLength).toNumber()) endXPoint = startXPoint.plus(Big(Math.sign(diffX.toNumber())).times(diffX.abs().minus(ridgeBaseLength))) endYPoint = startYPoint.plus(Big(Math.sign(diffY.toNumber())).times(diffY.abs().minus(ridgeBaseLength))) - console.log( - 'intersectLine : ', - Big(intersectLine.x).minus(startXPoint).round(1).toNumber(), - Big(intersectLine.y).minus(startYPoint).round(1).toNumber(), - ) - console.log('startXPoint : ', startXPoint.toNumber(), 'startYPoint : ', startYPoint.toNumber()) - console.log('endXPoint : ', endXPoint.toNumber(), 'endYPoint : ', endYPoint.toNumber()) // 시작점에서 종료점까지의 평면길이 //startXPoint.minus(endXPoint).abs().pow(2).plus(startYPoint.minus(endYPoint).abs().pow(2)).sqrt() @@ -1037,12 +993,14 @@ const drawRidge = (roof, canvas, textMode) => { }), ).div(10) // 현재 지붕선과 마주하는 지붕선을 잇는 선분의 교차점까지의 길이 - const intersectLength = Big(calcLinePlaneSize({ - x1: midX.toNumber(), - y1: midY.toNumber(), - x2: intersectLine.x, - y2: intersectLine.y, - })).div(10) + const intersectLength = Big( + calcLinePlaneSize({ + x1: midX.toNumber(), + y1: midY.toNumber(), + x2: intersectLine.x, + y2: intersectLine.y, + }), + ).div(10) //마주하는 지붕선까지의 길이가 현재 지붕선의 이전, 다음 지붕선의 길이보다 작을때 if (intersectLength.lt(Big(prevRoof.attributes.planeSize).div(10)) && intersectLength.lt(Big(nextRoof.attributes.planeSize).div(10))) { endXPoint = startXPoint @@ -1191,7 +1149,6 @@ export const segmentsOverlap = (line1, line2) => { * @param textMode */ const drawHips = (roof, canvas, textMode) => { - console.log('textMode : ', textMode) const roofLines = roof.lines const ridgeLines = canvas?.getObjects().filter((object) => object.name === LINE_TYPE.SUBLINE.RIDGE && object.attributes.roofId === roof.id) @@ -1232,12 +1189,15 @@ const drawHips = (roof, canvas, textMode) => { }), actualSize: prevDegree === currentDegree - ? calcLineActualSize({ - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: ridgeCoordinate.x1, - y2: ridgeCoordinate.y1, - }, currentDegree) + ? calcLineActualSize( + { + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: ridgeCoordinate.x1, + y2: ridgeCoordinate.y1, + }, + currentDegree, + ) : 0, }, }) @@ -1267,12 +1227,15 @@ const drawHips = (roof, canvas, textMode) => { }), actualSize: prevDegree === currentDegree - ? calcLineActualSize({ - x1: currentRoof.x2, - y1: currentRoof.y2, - x2: ridgeCoordinate.x1, - y2: ridgeCoordinate.y1, - }, currentDegree) + ? calcLineActualSize( + { + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: ridgeCoordinate.x1, + y2: ridgeCoordinate.y1, + }, + currentDegree, + ) : 0, }, }) @@ -1318,8 +1281,6 @@ const drawHips = (roof, canvas, textMode) => { } }) - console.log('currentRoof : ', currentRoof.length) - console.log(ridgePoints) ridgePoints = ridgePoints.reduce((prev, current) => { if (prev !== undefined) { // Math.abs(prev.x - currentRoof.x1) @@ -1355,12 +1316,15 @@ const drawHips = (roof, canvas, textMode) => { }), actualSize: prevDegree === currentDegree - ? calcLineActualSize({ - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: ridgePoints.x, - y2: ridgePoints.y, - }, currentDegree) + ? calcLineActualSize( + { + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: ridgePoints.x, + y2: ridgePoints.y, + }, + currentDegree, + ) : 0, }, }) @@ -1369,11 +1333,6 @@ const drawHips = (roof, canvas, textMode) => { roof.innerLines.push(hip) } }) - roof.innerLines.forEach((hip) => { - console.log('hip 길이 : ', hip.attributes.planeSize, ' actual : ', hip.attributes.actualSize) - hip.textMode = 'actual' - hip.addLengthText() - }) canvas?.renderAll() } @@ -1391,7 +1350,6 @@ const connectLinePoint = (polygon, canvas, textMode) => { const lineDegrees = [ ...new Set(polygon.lines.map((line) => (line.attributes.pitch > 0 ? getDegreeByChon(line.attributes.pitch) : line.attributes.degree))), ] - console.log('lineDegrees : ', lineDegrees) //마루 polygon.ridges.forEach((ridge) => { @@ -1443,7 +1401,7 @@ const connectLinePoint = (polygon, canvas, textMode) => { .reduce((prev, current) => { if (prev !== undefined) { return Math.sqrt(Math.pow(Math.abs(current.x - p1.x), 2) + Math.pow(Math.abs(current.y - p1.y), 2)) < - Math.sqrt(Math.pow(Math.abs(prev.x - p1.x), 2) + Math.pow(Math.abs(prev.y - p1.y), 2)) + Math.sqrt(Math.pow(Math.abs(prev.x - p1.x), 2) + Math.pow(Math.abs(prev.y - p1.y), 2)) ? current : prev } else { @@ -1890,9 +1848,9 @@ const changeEavesRoof = (currentRoof, canvas, textMode) => { actualSize: prevDegree === currentDegree ? calcLineActualSize( - { x1: currentRoof.x1, y1: currentRoof.y1, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, - Big(90 - currentDegree).toNumber(), - ) + { x1: currentRoof.x1, y1: currentRoof.y1, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - currentDegree).toNumber(), + ) : 0, }, }) @@ -1918,9 +1876,9 @@ const changeEavesRoof = (currentRoof, canvas, textMode) => { actualSize: currentDegree === nextDegree ? calcLineActualSize( - { x1: currentRoof.x2, y1: currentRoof.y2, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, - Big(90 - currentDegree).toNumber(), - ) + { x1: currentRoof.x2, y1: currentRoof.y2, x2: hipX2.toNumber(), y2: hipY2.toNumber() }, + Big(90 - currentDegree).toNumber(), + ) : 0, }, }) @@ -1987,8 +1945,6 @@ const changeGableRoof = (currentRoof, canvas, textMode) => { hipLines = hipLines.filter( (hip) => (hip.x1 === currentRoof.x1 && hip.y1 === currentRoof.y1) || (hip.x1 === currentRoof.x2 && hip.y1 === currentRoof.y2), ) - console.log('ridgeLines : ', ridgeLines) - console.log('hipLines : ', hipLines) if (hipLines === undefined || hipLines.length === 0) { hipLines = innerLines.filter( @@ -2076,12 +2032,15 @@ const changeGableRoof = (currentRoof, canvas, textMode) => { x2: midX.toNumber(), y2: midY.toNumber(), }), - actualSize: calcLineActualSize({ - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: midX.toNumber(), - y2: midY.toNumber(), - }, Big(90 - prevDegree)), + actualSize: calcLineActualSize( + { + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: midX.toNumber(), + y2: midY.toNumber(), + }, + Big(90 - prevDegree), + ), }, }) canvas?.add(hip1) @@ -2376,8 +2335,8 @@ const changeHipAndGableRoof = (currentRoof, canvas, textMode) => { }) }) - const gableDegree = i === 0 ? prevDegree : nextDegree hipLines.forEach((hip, i) => { + const gableDegree = i === 0 ? prevDegree : nextDegree const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], { parentId: roof.id, fontSize: roof.fontSize, @@ -2602,7 +2561,7 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { let hipY1 = (Math.sign(currentRoof.y1 - midY) * currentRoof.attributes.width) / 2 const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch) - const gable1 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2.toNumber(), hipY2.toNumber()], { + const gable1 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2, hipY2], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', @@ -2615,15 +2574,15 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { planeSize: calcLinePlaneSize({ x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), - x2: hipX2.toNumber(), - y2: hipY2.toNumber(), + x2: hipX2, + y2: hipY2, }), actualSize: calcLineActualSize( { x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), - x2: hipX2.toNumber(), - y2: hipY2.toNumber(), + x2: hipX2, + y2: hipY2, }, Big(90 - gableDegree).toNumber(), ), @@ -2639,7 +2598,7 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { hipX1 = (Math.sign(currentRoof.x2 - midX) * currentRoof.attributes.width) / 2 hipY1 = (Math.sign(currentRoof.y2 - midY) * currentRoof.attributes.width) / 2 - const gable2 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2.toNumber(), hipY2.toNumber()], { + const gable2 = new QLine([midX.plus(hipX1).toNumber(), midY.plus(hipY1).toNumber(), hipX2, hipY2], { parentId: roof.id, fontSize: roof.fontSize, stroke: '#1083E3', @@ -2652,15 +2611,15 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { planeSize: calcLinePlaneSize({ x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), - x2: hipX2.toNumber(), - y2: hipY2.toNumber(), + x2: hipX2, + y2: hipY2, }), actualSize: calcLineActualSize( { x1: midX.plus(hipX1).toNumber(), y1: midY.plus(hipY1).toNumber(), - x2: hipX2.toNumber(), - y2: hipY2.toNumber(), + x2: hipX2, + y2: hipY2, }, Big(90 - gableDegree).toNumber(), ), @@ -2705,12 +2664,15 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { roofId: roof.id, currentRoofId: currentRoof.id, planeSize: calcLinePlaneSize({ x1: currentRoof.x1, y1: currentRoof.y1, x2: gable1.x1, y2: gable1.y1 }), - actualSize: calcLineActualSize({ - x1: currentRoof.x1, - y1: currentRoof.y1, - x2: gable1.x1, - y2: gable1.y1, - }, Big(90 - prevDegree).toNumber()), + actualSize: calcLineActualSize( + { + x1: currentRoof.x1, + y1: currentRoof.y1, + x2: gable1.x1, + y2: gable1.y1, + }, + Big(90 - prevDegree).toNumber(), + ), }, }) // const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10 @@ -2732,12 +2694,15 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { roofId: roof.id, currentRoofId: currentRoof.id, planeSize: calcLinePlaneSize({ x1: currentRoof.x2, y1: currentRoof.y2, x2: gable2.x1, y2: gable2.y1 }), - actualSize: calcLineActualSize({ - x1: currentRoof.x2, - y1: currentRoof.y2, - x2: gable2.x1, - y2: gable2.y1, - }, Big(90 - nextDegree).toNumber()), + actualSize: calcLineActualSize( + { + x1: currentRoof.x2, + y1: currentRoof.y2, + x2: gable2.x1, + y2: gable2.y1, + }, + Big(90 - nextDegree).toNumber(), + ), }, }) // const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10 @@ -2746,8 +2711,6 @@ const changeJerkInHeadRoof = (currentRoof, canvas, textMode) => { // hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2))) canvas?.add(hip2) - console.log('currentRoof.id : ', currentRoof.id) - // hip1.set({ visible: false }) hip1.setViewLengthText(false) // gable3.set({ visible: false }) @@ -3253,7 +3216,6 @@ const drawCenterLine = (roof, canvas, textMode) => { const hips = roof.innerLines.filter( (line) => (currentRoof.x1 === line.x1 && currentRoof.y1 === line.y1) || (currentRoof.x2 === line.x1 && currentRoof.y2 === line.y1), ) - // console.log('hips : ', hips) const ridge = roof.innerLines .filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE) @@ -3279,41 +3241,17 @@ const drawCenterLine = (roof, canvas, textMode) => { } return prevDistance < currentDistance ? prev : current }, null) - /*console.log('currentRoof : ', currentRoof.attributes.planeSize, currentRoof) - console.log( - roof.innerLines - .filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE) - .filter((line) => { - if (currentRoof.x1 === currentRoof.x2) { - console.log('currentRoof.x1 === currentRoof.x2', line.x1 === line.x2, line) - if (line.x1 === line.x2) { - return line - } - } else { - console.log('currentRoof.x1 !== currentRoof.x2', line.y1 === line.y2, line) - if (line.y1 === line.y2) { - return line - } - } - }), - ) - console.log('currentRoof.x1 === currentRoof.x2 : ', currentRoof.x1 === currentRoof.x2) - console.log('ridge : ', ridge) - console.log('hips : ', hips)*/ let points = [] if (hips.length === 2 && Math.abs(hips[0].x2 - hips[1].x2) < 1 && Math.abs(hips[0].y2 - hips[1].y2) < 1) { - // console.log('삼각') const x1 = (currentRoof.x1 + currentRoof.x2) / 2 const y1 = (currentRoof.y1 + currentRoof.y2) / 2 points.push(x1, y1, hips[0].x2, hips[0].y2) } else if (hips.length > 1) { - // console.log('삼각 아님') if ( ((ridge?.x1 === hips[0].x2 && ridge?.y1 === hips[0].y2) || (ridge?.x2 === hips[0].x2 && ridge?.y2 === hips[0].y2)) && ((ridge?.x1 === hips[1].x2 && ridge?.y1 === hips[1].y2) || (ridge?.x2 === hips[1].x2 && ridge?.y2 === hips[1].y2)) ) { //사각이면 마루와 현재 라인 사이에 길이를 구한다 - // console.log('사각') if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) { const yPoints = [currentRoof.y1, currentRoof.y2, ridge.y1, ridge.y2].sort((a, b) => a - b) const x1 = (currentRoof.x1 + currentRoof.x2) / 2 @@ -3338,7 +3276,6 @@ const drawCenterLine = (roof, canvas, textMode) => { } } } else { - // console.log('사각 아님') if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) { let xPoints = [] xPoints.push(ridge?.x1, ridge?.x2) @@ -3424,7 +3361,6 @@ const drawCenterLine = (roof, canvas, textMode) => { } } } else { - // console.log('else : ') if (currentRoof.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) { const gables = canvas .getObjects() @@ -3461,6 +3397,7 @@ const drawCenterLine = (roof, canvas, textMode) => { } } if (points !== null) { + const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree const pitchSizeLine = new QLine(points, { parentId: roof.id, stroke: '#000000', @@ -3468,22 +3405,16 @@ const drawCenterLine = (roof, canvas, textMode) => { strokeDashArray: [5, 5], selectable: false, fontSize: roof.fontSize, + textMode: textMode, attributes: { roofId: roof.id, type: 'pitchSizeLine', + planeSize: calcLineActualSize({ x1: points[0], y1: points[1], x2: points[2], y2: points[3] }, currentDegree), + actualSize: calcLineActualSize({ x1: points[0], y1: points[1], x2: points[2], y2: points[3] }, currentDegree), }, }) canvas.add(pitchSizeLine) canvas.renderAll() - - const adjust = Math.sqrt( - Math.pow(Math.round(Math.abs(pitchSizeLine.x1 - pitchSizeLine.x2) * 10), 2) + - Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2), - ) - const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree - const height = Math.tan(currentDegree * (Math.PI / 180)) * adjust - const lengthText = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2))) - pitchSizeLine.setLengthText(lengthText) } }) }