삼각형, 오각형 도머 작업 지붕 패턴 가로 세로 작업

This commit is contained in:
yjnoh 2024-10-18 13:56:24 +09:00
parent ddf9847288
commit 8152b83b06
5 changed files with 383 additions and 108 deletions

View File

@ -46,6 +46,7 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
heightRef: useRef(null),
pitchRef: useRef(null),
offsetRef: useRef(null),
offsetWidthRef: useRef(null),
directionRef: useRef(null),
}

View File

@ -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 (
<>
<div className="discrimination-box mb10">
@ -18,7 +27,7 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={2000} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.heightRef} defaultValue={2000} />
</div>
<span className="thin">mm</span>
</div>
@ -29,7 +38,7 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={1000} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetRef} />
</div>
<span className="thin">mm</span>
</div>
@ -40,18 +49,18 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={4000} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.widthRef} defaultValue={2000} />
</div>
<span className="thin">mm</span>
</div>
</div>
</div>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('modal.object.setting.offset.depth')}</div>
<div className="eaves-keraba-th">{getMessage('modal.object.setting.offset.width')}</div>
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={500} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetWidthRef} />
</div>
<span className="thin">mm</span>
</div>
@ -62,7 +71,7 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={4} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.pitchRef} defaultValue={4} />
</div>
<span className="thin"></span>
</div>
@ -80,13 +89,15 @@ export default function PentagonDormer() {
<span className="right">{getMessage('commons.east')}</span>
<span className="bottom">{getMessage('commons.south')}</span>
<span className="left">{getMessage('commons.west')}</span>
<button className="plane-btn up"></button>
<button className="plane-btn right"></button>
<button className="plane-btn down act"></button>
<button className="plane-btn left"></button>
<button className={`plane-btn up ${direction === 'up' ? ' act' : ''}`} value="up" onClick={getDirection}></button>
<button className={`plane-btn right ${direction === 'right' ? ' act' : ''}`} value="right" onClick={getDirection}></button>
<button className={`plane-btn down ${direction === 'down' ? ' act' : ''}`} value="down" onClick={getDirection}></button>
<button className={`plane-btn left ${direction === 'left' ? ' act' : ''}`} value="left" onClick={getDirection}></button>
</div>
</div>
</div>
</>
)
}
})
export default PentagonDormer

View File

@ -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) => {

View File

@ -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,
}
}

View File

@ -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()
}
}
}