diff --git a/src/components/floor-plan/modal/object/ObjectSetting.jsx b/src/components/floor-plan/modal/object/ObjectSetting.jsx index d5fe934e..764535e3 100644 --- a/src/components/floor-plan/modal/object/ObjectSetting.jsx +++ b/src/components/floor-plan/modal/object/ObjectSetting.jsx @@ -46,6 +46,7 @@ export default function ObjectSetting({ setShowObjectSettingModal }) { heightRef: useRef(null), pitchRef: useRef(null), offsetRef: useRef(null), + offsetWidthRef: useRef(null), directionRef: useRef(null), } diff --git a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx index e2aeea15..73f9c5d8 100644 --- a/src/components/floor-plan/modal/object/type/PentagonDormer.jsx +++ b/src/components/floor-plan/modal/object/type/PentagonDormer.jsx @@ -1,8 +1,17 @@ import Image from 'next/image' import { useMessage } from '@/hooks/useMessage' +import { forwardRef, useState } from 'react' -export default function PentagonDormer() { +const PentagonDormer = forwardRef((props, refs) => { const { getMessage } = useMessage() + const [direction, setDirection] = useState('down') + refs.directionRef.current = direction + + const getDirection = (e) => { + setDirection(e.target.value) + refs.directionRef.current = e.target.value + } + return ( <>
@@ -18,7 +27,7 @@ export default function PentagonDormer() {
- +
mm
@@ -29,7 +38,7 @@ export default function PentagonDormer() {
- +
mm
@@ -40,18 +49,18 @@ export default function PentagonDormer() {
- +
mm
-
{getMessage('modal.object.setting.offset.depth')}
+
{getMessage('modal.object.setting.offset.width')}
- +
mm
@@ -62,7 +71,7 @@ export default function PentagonDormer() {
- +
@@ -80,13 +89,15 @@ export default function PentagonDormer() { {getMessage('commons.east')} {getMessage('commons.south')} {getMessage('commons.west')} - - - - + + + +
) -} +}) + +export default PentagonDormer diff --git a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx index 9ab7712d..f2a8a1f0 100644 --- a/src/components/floor-plan/modal/object/type/TriangleDormer.jsx +++ b/src/components/floor-plan/modal/object/type/TriangleDormer.jsx @@ -5,7 +5,6 @@ import { forwardRef, useState } from 'react' const TriangleDormer = forwardRef((props, refs) => { const { getMessage } = useMessage() const [direction, setDirection] = useState('down') - refs.directionRef.current = direction const getDirection = (e) => { diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index 7229f470..9ad8af5d 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -4,14 +4,7 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { canvasState } from '@/store/canvasAtom' import { INPUT_TYPE, BATCH_TYPE } from '@/common/common' import { useEvent } from '@/hooks/useEvent' -import { - polygonToTurfPolygon, - rectToPolygon, - triangleToPolygon, - pointsToTurfPolygon, - splitDormerTriangle, - setSurfaceShapePattern, -} from '@/util/canvas-util' +import { polygonToTurfPolygon, rectToPolygon, triangleToPolygon, pointsToTurfPolygon, setSurfaceShapePattern } from '@/util/canvas-util' import { useSwal } from '@/hooks/useSwal' import * as turf from '@turf/turf' import { QPolygon } from '@/components/fabric/QPolygon' @@ -211,11 +204,13 @@ export function useObjectBatch() { const dormerName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER : BATCH_TYPE.PENTAGON_DORMER const dormerTempName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER_TEMP : BATCH_TYPE.PENTAGON_DORMER_TEMP const height = dormerPlacement.heightRef.current.value / 10 + const width = dormerPlacement.widthRef.current.value / 10 const pitch = dormerPlacement.pitchRef.current.value - const directionRef = dormerPlacement.directionRef.current const offsetRef = dormerPlacement.offsetRef.current.value === '' ? 0 : parseInt(dormerPlacement.offsetRef.current.value) / 10 + const offsetWidthRef = dormerPlacement.offsetWidthRef.current.value === '' ? 0 : parseInt(dormerPlacement.offsetWidthRef.current.value) / 10 + const directionRef = dormerPlacement.directionRef.current - let dormer, dormerOffset, isDown, selectedSurface + let dormer, dormerOffset, isDown, selectedSurface, pentagonPoints, pentagonOffsetPoints console.log('dormerPlacement', dormerPlacement) @@ -229,8 +224,6 @@ export function useObjectBatch() { const bottomLength = height / (pitch * 0.25) const bottomOffsetLength = (height + offsetRef) / (pitch * 0.25) - console.log(bottomOffsetLength) - addCanvasMouseEventListener('mouse:move', (e) => { isDown = true if (!isDown) return @@ -305,16 +298,16 @@ export function useObjectBatch() { addCanvasMouseEventListener('mouse:up', (e) => { if (dormer) { - // const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer)) - // const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface) + const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer)) + const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface) - // //지붕 밖으로 그렸을때 - // if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) { - // swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) - // //일단 지워 - // deleteTempObjects() - // return - // } + //지붕 밖으로 그렸을때 + if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) { + swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) + //일단 지워 + deleteTempObjects() + return + } //각도 추가 let originAngle = 0 //기본 남쪽 @@ -387,6 +380,183 @@ export function useObjectBatch() { drawDirectionArrow(leftTriangle) drawDirectionArrow(rightTriangle) + isDown = false + initEvent() + } + }) + } else if (buttonAct === 4) { + const heightLength = height - (width / 2) * (pitch * 0.25) + //(동의길이 깊이)+출폭(깊이)-[(입력한 폭값)/2+출폭(폭)]*(0.25*입력한 寸) + const heightOffsetLength = height + offsetRef - (width / 2 + offsetWidthRef) * (pitch * 0.25) + + addCanvasMouseEventListener('mouse:move', (e) => { + isDown = true + if (!isDown) return + + canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === dormerTempName)) //움직일때 일단 지워가면서 움직임 + const pointer = canvas.getPointer(e.e) + + surfaceShapePolygons.forEach((surface) => { + if (surface.inPolygon({ x: pointer.x, y: pointer.y })) { + selectedSurface = surface + } + }) + + let angle = 0 + if (directionRef === 'left') { + //서 + angle = 90 + } else if (directionRef === 'right') { + //동 + angle = 270 + } else if (directionRef === 'up') { + //북 + angle = 180 + } + + pentagonPoints = [ + { x: pointer.x, y: pointer.y }, + { x: pointer.x - width / 2, y: pointer.y + (height - heightLength) }, + { x: pointer.x - width / 2, y: pointer.y + height }, + { x: pointer.x + width / 2, y: pointer.y + height }, + { x: pointer.x + width / 2, y: pointer.y + (height - heightLength) }, + ] + + pentagonOffsetPoints = [ + { x: pointer.x, y: pointer.y }, + { x: pointer.x - width / 2 - offsetWidthRef, y: pointer.y + height + offsetRef - heightOffsetLength }, + { x: pointer.x - width / 2 - offsetWidthRef, y: pointer.y + height + offsetRef }, + { x: pointer.x + width / 2 + offsetWidthRef, y: pointer.y + height + offsetRef }, + { x: pointer.x + width / 2 + offsetWidthRef, y: pointer.y + height + offsetRef - heightOffsetLength }, + ] + + dormer = new QPolygon(pentagonPoints, { + fill: 'white', + stroke: 'red', + strokeDashArray: [5, 5], + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: dormerTempName, + originX: 'center', + originY: 'top', + angle: angle, + }) + canvas?.add(dormer) + + if (offsetRef > 0 || offsetWidthRef > 0) { + dormerOffset = new QPolygon(pentagonOffsetPoints, { + fill: 'gray', + stroke: 'red', + strokeDashArray: [5, 5], + strokeWidth: 1, + selectable: true, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: dormerTempName, + originX: 'center', + originY: 'top', + angle: angle, + }) + canvas?.add(dormerOffset) + } + }) + + addCanvasMouseEventListener('mouse:up', (e) => { + if (dormer) { + // const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer)) + // const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface) + + // //지붕 밖으로 그렸을때 + // if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) { + // swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) + // //일단 지워 + // deleteTempObjects() + // return + // } + + //각도 추가 + let originAngle = 0 //기본 남쪽 + let direction = 'south' + + if (directionRef === 'left') { + //서 + originAngle = 90 + direction = 'west' + } else if (directionRef === 'right') { + //동 + originAngle = 270 + direction = 'east' + } else if (directionRef === 'up') { + //북 + originAngle = 180 + direction = 'north' + } + + const offsetMode = offsetRef > 0 || offsetWidthRef > 0 ? 'offset' : 'normal' + let splitedPentagon = + offsetRef > 0 || offsetWidthRef > 0 + ? splitDormerPentagon(dormerOffset, directionRef, offsetMode) + : splitDormerPentagon(dormer, directionRef, offsetMode) + canvas?.remove(offsetRef > 0 || offsetWidthRef > 0 ? dormerOffset : dormer) + + if (offsetRef > 0) + dormer.set({ + name: dormerName, + stroke: 'black', + strokeWidth: 1, + strokeDashArray: [0], + }) //오프셋이 있을땐 같이 도머로 만든다 + + const leftPentagon = new QPolygon(splitedPentagon[0], { + fill: 'transparent', + stroke: 'red', + strokeWidth: 1, + selectable: true, + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + viewLengthText: true, + fontSize: 14, + direction: direction, + originX: 'center', + originY: 'center', + name: dormerName, + }) + + const rightPentagon = new QPolygon(splitedPentagon[1], { + fill: 'transparent', + stroke: 'red', + strokeWidth: 1, + selectable: true, + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + viewLengthText: true, + fontSize: 14, + direction: direction, + originX: 'center', + originY: 'center', + name: dormerName, + }) + + canvas?.add(leftPentagon) + canvas?.add(rightPentagon) + + //패턴 + setSurfaceShapePattern(leftPentagon) + setSurfaceShapePattern(rightPentagon) + //방향 + drawDirectionArrow(leftPentagon) + drawDirectionArrow(rightPentagon) + isDown = false initEvent() } @@ -408,8 +578,140 @@ export function useObjectBatch() { initEvent() //이벤트 초기화 } + const splitDormerTriangle = (triangle, direction) => { + const halfWidth = triangle.width / 2 + + let leftPoints = [] + let rightPoints = [] + + if (direction === 'down') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - halfWidth, y: triangle.top + triangle.height }, + { x: triangle.left, y: triangle.top + triangle.height }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left, y: triangle.top + triangle.height }, + { x: triangle.left + halfWidth, y: triangle.top + triangle.height }, + ] + } else if (direction === 'up') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - halfWidth, y: triangle.top - triangle.height }, + { x: triangle.left, y: triangle.top - triangle.height }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left, y: triangle.top - triangle.height }, + { x: triangle.left + halfWidth, y: triangle.top - triangle.height }, + ] + } else if (direction === 'left') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - triangle.height, y: triangle.top - halfWidth }, + { x: triangle.left - triangle.height, y: triangle.top }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left - triangle.height, y: triangle.top }, + { x: triangle.left - triangle.height, y: triangle.top + halfWidth }, + ] + } else if (direction === 'right') { + leftPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top + triangle.height }, + ] + + rightPoints = [ + { x: triangle.left, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top }, + { x: triangle.left + triangle.height, y: triangle.top - triangle.height }, + ] + } + + return [leftPoints, rightPoints] + } + + const splitDormerPentagon = (pentagon, direction, offsetMode) => { + const points = pentagon.points + + console.log(pentagon.points) + + let leftPoints = [] + let rightPoints = [] + + if (direction === 'down') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[1].x, y: points[1].y }, + { x: points[2].x, y: points[2].y }, + { x: points[0].x, y: points[3].y }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x, y: points[2].y }, + { x: points[3].x, y: points[3].y }, + { x: points[4].x, y: points[4].y }, + ] + } else if (direction === 'up') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[1].x, y: points[0].y - (points[1].y - points[0].y) }, + { x: points[2].x, y: points[0].y - (points[2].y - points[0].y) }, + { x: points[0].x, y: points[0].y - (points[2].y - points[0].y) }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[3].x, y: points[0].y - (points[1].y - points[0].y) }, + { x: points[3].x, y: points[0].y - (points[2].y - points[0].y) }, + { x: points[0].x, y: points[0].y - (points[2].y - points[0].y) }, + ] + } else if (direction === 'left') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x - (points[1].y - points[0].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x - (points[1].y - points[0].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y }, + ] + } else if (direction === 'right') { + leftPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x + (points[1].y - points[0].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y + (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y }, + ] + + rightPoints = [ + { x: points[0].x, y: points[0].y }, + { x: points[0].x + (points[1].y - points[0].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y - (points[0].x - points[1].x) }, + { x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y }, + ] + } + + console.log(leftPoints, rightPoints) + + return [leftPoints, rightPoints] + } + return { applyOpeningAndShadow, applyDormers, + splitDormerTriangle, + splitDormerPentagon, } } diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 17c30f07..20b6ec66 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -744,67 +744,6 @@ export const polygonToTurfPolygon = (polygon) => { ) } -export const splitDormerTriangle = (triangle, direction) => { - const halfWidth = triangle.width / 2 - - let leftPoints = [] - let rightPoints = [] - let leftPointOffset = [] - let rightPointOffset = [] - - if (direction === 'down') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - halfWidth, y: triangle.top + triangle.height }, - { x: triangle.left, y: triangle.top + triangle.height }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left, y: triangle.top + triangle.height }, - { x: triangle.left + halfWidth, y: triangle.top + triangle.height }, - ] - } else if (direction === 'up') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - halfWidth, y: triangle.top - triangle.height }, - { x: triangle.left, y: triangle.top - triangle.height }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left, y: triangle.top - triangle.height }, - { x: triangle.left + halfWidth, y: triangle.top - triangle.height }, - ] - } else if (direction === 'left') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - triangle.height, y: triangle.top - halfWidth }, - { x: triangle.left - triangle.height, y: triangle.top }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left - triangle.height, y: triangle.top }, - { x: triangle.left - triangle.height, y: triangle.top + halfWidth }, - ] - } else if (direction === 'right') { - leftPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top + triangle.height }, - ] - - rightPoints = [ - { x: triangle.left, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top }, - { x: triangle.left + triangle.height, y: triangle.top - triangle.height }, - ] - } - - return [leftPoints, rightPoints] -} - export const triangleToPolygon = (triangle) => { const points = [] const halfWidth = triangle.width / 2 @@ -853,7 +792,7 @@ export function setSurfaceShapePattern(polygon) { patternSourceCanvas.width = polygon.width * ratio patternSourceCanvas.height = polygon.height * ratio const ctx = patternSourceCanvas.getContext('2d') - const offset = roofStyle === 1 ? 0 : patternSize.width / 2 + let offset = roofStyle === 1 ? 0 : patternSize.width / 2 const rows = Math.floor(patternSourceCanvas.height / patternSize.height) const cols = Math.floor(patternSourceCanvas.width / patternSize.width) @@ -861,23 +800,46 @@ export function setSurfaceShapePattern(polygon) { ctx.strokeStyle = 'green' ctx.lineWidth = 0.4 - for (let row = 0; row <= rows; row++) { - const y = row * patternSize.height - - ctx.beginPath() - ctx.moveTo(0, y) // 선 시작점 - ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점 - ctx.stroke() - + if (polygon.direction === 'east' || polygon.direction === 'west') { + offset = roofStyle === 1 ? 0 : patternSize.height / 2 for (let col = 0; col <= cols; col++) { - const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset) - const yStart = row * patternSize.height - const yEnd = yStart + patternSize.height - + const x = col * patternSize.width + const yStart = 0 + const yEnd = patternSourceCanvas.height ctx.beginPath() ctx.moveTo(x, yStart) // 선 시작점 ctx.lineTo(x, yEnd) // 선 끝점 ctx.stroke() + + for (let row = 0; row <= rows; row++) { + const y = row * patternSize.height + (col % 2 === 0 ? 0 : offset) + const xStart = col * patternSize.width + const xEnd = xStart + patternSize.width + ctx.beginPath() + ctx.moveTo(xStart, y) // 선 시작점 + ctx.lineTo(xEnd, y) // 선 끝점 + ctx.stroke() + } + } + } else { + for (let row = 0; row <= rows; row++) { + const y = row * patternSize.height + + ctx.beginPath() + ctx.moveTo(0, y) // 선 시작점 + ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점 + ctx.stroke() + + for (let col = 0; col <= cols; col++) { + const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset) + const yStart = row * patternSize.height + const yEnd = yStart + patternSize.height + + ctx.beginPath() + ctx.moveTo(x, yStart) // 선 시작점 + ctx.lineTo(x, yEnd) // 선 끝점 + ctx.stroke() + } } }