면형상배치 작업 진행중

This commit is contained in:
yjnoh 2024-10-11 15:04:22 +09:00
parent e149b462d2
commit a82dafaa06
5 changed files with 779 additions and 85 deletions

View File

@ -1,9 +1,14 @@
import Image from 'next/image'
import { useMessage } from '@/hooks/useMessage'
import { forwardRef, useState } from 'react'
export default function PlacementSurface(props) {
const PlacementSurface = forwardRef((props, refs) => {
const { getMessage } = useMessage()
const { id, lines, info, rotate, xInversion, yInversion } = props
let { length1, length2, length3, length4, length5, lengthetc, azimuth } = refs
const [azimuthDirection, setAzimuthDirection] = useState(azimuth.current)
const num = ['①', '②', '③', '④', '⑤']
const getImageUrl = () => {
if (xInversion && !yInversion) {
@ -24,6 +29,12 @@ export default function PlacementSurface(props) {
return `/static/images/canvas/shape/${rotate !== 0 ? Math.abs(rotate * 90) + 'deg' : 'normal'}/plane_tab${id < 10 ? '0' + id : id}.svg`
}
const azimuthButton = (direction, e) => {
setAzimuthDirection(direction)
azimuth.current = direction
}
return (
<>
<div className="plane-shape-wrapper">
@ -36,14 +47,31 @@ export default function PlacementSurface(props) {
<div className="shape-data">
<div className="eaves-keraba-table">
{lines?.map((line, index) => (
<div className="eaves-keraba-item" id={index}>
<div className="eaves-keraba-item" id={index} key={index}>
<div className="eaves-keraba-th">
{line.isDiagonal ? getMessage('modal.placement.surface.setting.diagonal.length') : num[index]}
</div>
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '57px' }}>
<input type="text" className="input-origin plane block" defaultValue={line.value} />
<input
type="text"
className="input-origin plane block"
defaultValue={line.value}
ref={
line.isDiagonal
? lengthetc
: index === 0
? length1
: index === 1
? length2
: index === 2
? length3
: index === 3
? length4
: length5
}
/>
</div>
<span className="thin">mm</span>
</div>
@ -62,10 +90,10 @@ export default function PlacementSurface(props) {
<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 ${azimuthDirection === 'up' ? ' act' : ''}`} onClick={() => azimuthButton('up')}></button>
<button className={`plane-btn right ${azimuthDirection === 'right' ? ' act' : ''}`} onClick={() => azimuthButton('right')}></button>
<button className={`plane-btn down ${azimuthDirection === 'down' ? ' act' : ''}`} onClick={() => azimuthButton('down')}></button>
<button className={`plane-btn left ${azimuthDirection === 'left' ? ' act' : ''}`} onClick={() => azimuthButton('left')}></button>
</div>
</div>
</div>
@ -73,4 +101,6 @@ export default function PlacementSurface(props) {
{info && <div className="plane-tab-guide">{info}</div>}
</>
)
}
})
export default PlacementSurface

View File

@ -1,15 +1,30 @@
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useEffect, useState } from 'react'
import { useEffect, useState, useRef } from 'react'
import Image from 'next/image'
import PlacementSurface from '@/components/floor-plan/modal/placementSurface/PlacementSurface'
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSettingModal }) {
const { getMessage } = useMessage()
const [selectedType, setSelectedType] = useState()
const [rotate, setRotate] = useState(0)
const [xInversion, setXInversion] = useState(false)
const [yInversion, setYInversion] = useState(false)
const { applySurfaceShape } = useSurfaceShapeBatch()
const surfaceRefs = {
length1: useRef(null),
length2: useRef(null),
length3: useRef(null),
length4: useRef(null),
length5: useRef(null),
lengthetc: useRef(null),
azimuth: useRef('down'),
}
/* type
* a: line 2
* b: line 2 + diagonal 1
@ -21,11 +36,11 @@ export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSetting
{
id: 1,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{
isDiagonal: true,
value: 3500,
value: 0,
},
],
info: getMessage('modal.placement.surface.setting.info'),
@ -33,151 +48,151 @@ export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSetting
{
id: 2,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 3,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 4,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 5,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 6,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
lineAmount: 3,
},
{
id: 7,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 8,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 9,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 10,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 11,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 12,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 13,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 14,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 15,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 16,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 17,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
{
id: 18,
lines: [
{ isDiagonal: false, value: 4500 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 2600 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
{ isDiagonal: false, value: 0 },
],
},
]
@ -200,11 +215,11 @@ export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSetting
return `rotate(${90 * rotate}deg)`
}
const onClick = () => {
if (xInversion !== yInversion) {
} else {
setRotate((rotate + 1) % 4)
}
const applySurfaces = () => {
surfaceRefs.xInversion = xInversion //
surfaceRefs.yInversion = yInversion //
surfaceRefs.rotate = rotate * 90 //
applySurfaceShape(surfaceRefs, selectedType, setShowPlacementSurfaceSettingModal)
}
useEffect(() => {
@ -245,9 +260,11 @@ export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSetting
<button className="library-btn ico02" onClick={() => setYInversion(!yInversion)}></button>
<button className="library-btn ico03" onClick={() => setXInversion(!xInversion)}></button>
</div>
<PlacementSurface {...placementSurfaceProps} />
<PlacementSurface {...placementSurfaceProps} ref={surfaceRefs} />
<div className="grid-btn-wrap">
<button className="btn-frame modal act">作成</button>
<button className="btn-frame modal act" onClick={applySurfaces}>
{getMessage('write')}
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,633 @@
'use client'
import { useEffect, useRef, useState } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { MENU } from '@/common/common'
import { getIntersectionPoint } from '@/util/canvas-util'
import { degreesToRadians } from '@turf/turf'
import { QPolygon } from '@/components/fabric/QPolygon'
import { fabric } from 'fabric'
import { useSwal } from '@/hooks/useSwal'
import { useMessage } from '@/hooks/useMessage'
export function useSurfaceShapeBatch() {
const { getMessage } = useMessage()
const canvas = useRecoilValue(canvasState)
const { swalFire } = useSwal()
const applySurfaceShape = (surfaceRefs, selectedType, setShowPlacementSurfaceSettingModal) => {
let length1, length2, length3, length4, length5
const surfaceId = selectedType?.id
const azimuth = surfaceRefs.azimuth.current
if (surfaceId === 1) {
length1 = surfaceRefs.length1.current.value
length2 = surfaceRefs.length2.current.value
length3 = surfaceRefs.lengthetc.current.value //대각선
} else if ([2, 4].includes(surfaceId)) {
length1 = surfaceRefs.length1.current.value
length2 = surfaceRefs.length2.current.value
} else if ([3, 5, 6, 15, 18].includes(surfaceId)) {
length1 = surfaceRefs.length1.current.value
length2 = surfaceRefs.length2.current.value
length3 = surfaceRefs.length3.current.value
} else if ([8, 12, 13, 16, 17].includes(surfaceId)) {
length1 = surfaceRefs.length1.current.value
length2 = surfaceRefs.length2.current.value
length3 = surfaceRefs.length3.current.value
length4 = surfaceRefs.length4.current.value
} else if ([7, 9, 10, 11, 14].includes(surfaceId)) {
length1 = surfaceRefs.length1.current.value
length2 = surfaceRefs.length2.current.value
length3 = surfaceRefs.length3.current.value
length4 = surfaceRefs.length4.current.value
length5 = surfaceRefs.length5.current.value
}
length1 = parseInt(length1 === undefined ? 0 : length1 / 10)
length2 = parseInt(length2 === undefined ? 0 : length2 / 10)
length3 = parseInt(length3 === undefined ? 0 : length3 / 10)
length4 = parseInt(length4 === undefined ? 0 : length4 / 10)
length5 = parseInt(length5 === undefined ? 0 : length5 / 10)
let isDrawing = true
let obj = null
let points = []
if (checkSurfaceShape(surfaceId, { length1, length2, length3, length4, length5 })) {
setShowPlacementSurfaceSettingModal(false)
canvas?.on('mouse:move', (e) => {
console.log('asdfasdfasdfasdfasdfsdfasdfsdf')
if (!isDrawing) {
return
}
const pointer = canvas?.getPointer(e.e)
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP))
points = getSurfaceShape(surfaceId, pointer, { length1, length2, length3, length4, length5 })
const options = {
fill: 'transparent',
stroke: 'black',
strokeWidth: 1,
strokeDasharray: [10, 4],
fontSize: 12,
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금
name: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP,
flipX: surfaceRefs.yInversion,
flipY: surfaceRefs.xInversion,
angle: surfaceRefs.rotate,
originX: 'center',
originY: 'center',
}
obj = new QPolygon(points, options)
obj.setCoords() //좌표 변경 적용
canvas?.add(obj)
//각도 추가
let originAngle = 0 //기본 남쪽
let direction = 'south'
if (azimuth === 'left') {
//서
originAngle = 90
direction = 'west'
} else if (azimuth === 'right') {
//동
originAngle = 270
direction = 'east'
} else if (azimuth === 'up') {
//북
originAngle = 180
direction = 'north'
}
obj.set({ direction: direction })
obj.set({ originAngle: originAngle })
// setCurrentPattern(obj)
canvas?.renderAll()
})
canvas?.on('mouse:down', (e) => {
isDrawing = false
obj.set('name', MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH)
canvas?.off('mouse:down')
canvas.off('mouse:move')
setSurfaceShapePattern(obj)
setShowPlacementSurfaceSettingModal(true)
})
}
}
//면형상 입력 validate
const checkSurfaceShape = (surfaceId, lengths) => {
const { length1, length2, length3, length4, length5 } = lengths
let check = true
if (surfaceId === 1) {
if (length1 === 0) {
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
check = false
}
if (length2 === 0) {
if (length3 === 0) {
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
check = false
}
}
} else if ([2, 4].includes(surfaceId)) {
if (length1 === 0 || length2 === 0) {
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
check = false
}
} else if ([3, 5, 6, 15, 18].includes(surfaceId)) {
if (length1 === 0 || length2 === 0 || length3 === 0) {
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
check = false
}
if (surfaceId === 3 && length3 > length1) {
swalFire({ text: getMessage('surface.shape.validate.size.1to3'), icon: 'error' })
check = false
}
if (surfaceId === 5 || surfaceId === 15) {
if (length3 >= length2) {
swalFire({ text: getMessage('surface.shape.validate.size.2to3'), icon: 'error' })
check = false
}
}
if (surfaceId === 18) {
if (length1 >= length2) {
swalFire({ text: getMessage('surface.shape.validate.size.1to2'), icon: 'error' })
check = false
}
if (length4 >= length3) {
swalFire({ text: getMessage('surface.shape.validate.size.3to4'), icon: 'error' })
check = false
}
}
} else if ([8, 12, 13, 16, 17].includes(surfaceId)) {
if (length1 === 0 || length2 === 0 || length3 === 0 || length4 === 0) {
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
check = false
}
if (surfaceId === 8) {
if (length2 >= length1) {
swalFire({ text: getMessage('surface.shape.validate.size.1to2'), icon: 'error' })
check = false
}
if (length4 >= length3) {
swalFire({ text: getMessage('surface.shape.validate.size.3to4'), icon: 'error' })
check = false
}
}
if (surfaceId === 12 || surfaceId === 13 || surfaceId === 16 || surfaceId === 17) {
if (length2 >= length1) {
swalFire({ text: getMessage('surface.shape.validate.size.1to2'), icon: 'error' })
check = false
}
if (length4 >= length3) {
swalFire({ text: getMessage('surface.shape.validate.size.1to2'), icon: 'error' })
check = false
}
}
} else if ([7, 9, 10, 11, 14].includes(surfaceId)) {
if (length1 === 0 || length2 === 0 || length3 === 0 || length4 === 0 || length5 === 0) {
swalFire({ text: getMessage('surface.shape.validate.size'), icon: 'error' })
check = false
}
if (surfaceId === 9 || surfaceId === 10 || surfaceId === 11) {
if (length2 + length3 >= length1) {
swalFire({ text: getMessage('surface.shape.validate.size.1to23'), icon: 'error' })
check = false
}
if (length5 >= length4) {
swalFire({ text: getMessage('surface.shape.validate.size.4to5'), icon: 'error' })
check = false
}
}
if (surfaceId === 14) {
if (length2 + length3 >= length1) {
swalFire({ text: getMessage('surface.shape.validate.size.1to23'), icon: 'error' })
check = false
}
if (length5 >= length4) {
swalFire({ text: getMessage('surface.shape.validate.size.4to5'), icon: 'error' })
check = false
}
}
}
return check
}
//면형상 가져오기
const getSurfaceShape = (surfaceId, pointer, lengths) => {
let points = []
const { length1, length2, length3, length4, length5 } = lengths
switch (surfaceId) {
case 1: {
let newLength2 = length2
if (length3 !== 0) {
newLength2 = Math.sqrt(length3 ** 2 - (length1 / 2) ** 2)
}
points = [
{ x: pointer.x, y: pointer.y - parseInt(newLength2) / 2 },
{ x: pointer.x - parseInt(length1) / 2, y: pointer.y + parseInt(newLength2) / 2 },
{ x: pointer.x + parseInt(length1) / 2, y: pointer.y + parseInt(newLength2) / 2 },
]
break
}
case 2: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y - length2 / 2 },
{ x: pointer.x - length1 / 2, y: pointer.y - length2 / 2 },
]
break
}
case 3: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x + length3 / 2, y: pointer.y - length2 / 2 },
{ x: pointer.x - length3 / 2, y: pointer.y - length2 / 2 },
]
break
}
case 4: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y - length2 / 2 },
]
break
}
case 5: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y - length3 / 2 },
{ x: pointer.x - length1 / 2, y: pointer.y + length3 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y + length3 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y + length3 / 2 - length2 },
]
break
}
case 6: {
const angleInRadians = Math.asin(length2 / length3)
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x - length1 / 2 + length3 * Math.cos(angleInRadians), y: pointer.y + length2 / 2 - length3 * Math.sin(angleInRadians) },
{ x: pointer.x + length1 / 2 + length3 * Math.cos(angleInRadians), y: pointer.y + length2 / 2 - length3 * Math.sin(angleInRadians) },
{ x: pointer.x + length1 / 2, y: pointer.y + length2 / 2 },
]
break
}
case 7: {
points = [
{ x: pointer.x - (length1 + length2 + length3) / 2, y: pointer.y - (length4 + length5) / 2 },
{ x: pointer.x - (length1 + length2 + length3) / 2, y: pointer.y + (length4 + length5) / 2 },
{ x: pointer.x - (length1 + length2 + length3) / 2 + length1, y: pointer.y + (length4 + length5) / 2 },
{ x: pointer.x - (length1 + length2 + length3) / 2 + length1, y: pointer.y + (length4 + length5) / 2 - length5 },
{ x: pointer.x - (length1 + length2 + length3) / 2 + length1 + length2, y: pointer.y + (length4 + length5) / 2 - length5 },
{ x: pointer.x - (length1 + length2 + length3) / 2 + length1 + length2, y: pointer.y + (length4 + length5) / 2 - length5 + length5 },
{
x: pointer.x - (length1 + length2 + length3) / 2 + length1 + length2 + length3,
y: pointer.y + (length4 + length5) / 2 - length5 + length5,
},
{
x: pointer.x - (length1 + length2 + length3) / 2 + length1 + length2 + length3,
y: pointer.y + (length4 + length5) / 2 - length5 + length5 - (length4 + length5),
},
]
break
}
case 8: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length3 },
{ x: pointer.x - length1 / 2 + length1 - (length1 - length2), y: pointer.y + length4 / 2 - length3 },
{ x: pointer.x - length1 / 2 + length1 - (length1 - length2), y: pointer.y + length4 / 2 - length3 + (length3 - length4) },
{ x: pointer.x - length1 / 2 + length1 - (length1 - length2) - length2, y: pointer.y + length4 / 2 - length3 + (length3 - length4) },
]
break
}
case 9: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 },
{ x: pointer.x - length1 / 2 + length1 - length3, y: pointer.y + length4 / 2 - length4 },
{ x: pointer.x - length1 / 2 + length1 - length3, y: pointer.y + length4 / 2 - length4 + (length4 - length5) },
{ x: pointer.x - length1 / 2 + length1 - length3 - length2, y: pointer.y + length4 / 2 - length4 + (length4 - length5) },
]
break
}
case 10: {
points = [
{ x: pointer.x + length1 / 2, y: pointer.y + length4 / 2 },
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 },
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 - length5 },
{ x: pointer.x + length1 / 2 - length1 + length2, y: pointer.y + length4 / 2 - length5 },
{ x: pointer.x + length1 / 2 - length1 + length2, y: pointer.y + length4 / 2 - length5 - (length4 - length5) },
{ x: pointer.x + length1 / 2 - length1 + length2 + length3, y: pointer.y + length4 / 2 - length5 - (length4 - length5) },
]
break
}
case 11: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length5 },
{ x: pointer.x - length1 / 2 + length1 - length2, y: pointer.y + length4 / 2 - length5 },
{ x: pointer.x - length1 / 2 + length1 - length2, y: pointer.y + length4 / 2 - length5 - (length4 - length5) },
{ x: pointer.x - length1 / 2 + length1 - length2 - length3, y: pointer.y + length4 / 2 - length5 - (length4 - length5) },
]
break
}
case 12: {
const leftHypotenuse = Math.sqrt(((length1 - length2) / 2) ** 2 + length3 ** 2)
const rightHypotenuse = (length4 / length3) * leftHypotenuse
const leftAngle = Math.acos((length1 - length2) / 2 / leftHypotenuse)
points = [
{ x: pointer.x - length1 / 2 + leftHypotenuse * Math.cos(leftAngle), y: pointer.y + length3 / 2 - leftHypotenuse * Math.sin(leftAngle) },
{ x: pointer.x - length1 / 2, y: pointer.y + length3 / 2 },
{ x: pointer.x + length1 / 2, y: pointer.y + length3 / 2 },
{
x: pointer.x + length1 / 2 - rightHypotenuse * Math.cos(leftAngle),
y: pointer.y + length3 / 2 - rightHypotenuse * Math.sin(leftAngle),
},
{
x: pointer.x + length1 / 2 - rightHypotenuse * Math.cos(leftAngle) - length2,
y: pointer.y + length3 / 2 - rightHypotenuse * Math.sin(leftAngle),
},
]
break
}
case 13: {
const pointsArray = [
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
]
const tmpPolygon = new QPolygon(
[
{ x: 0, y: length3 },
{ x: length1 - length2, y: length3 },
{ x: (length1 - length2) / 2, y: length3 - length3 },
],
{
fill: 'transparent',
stroke: 'black', //black
strokeWidth: 2,
selectable: true,
fontSize: 0,
},
)
const coord = getIntersectionPoint(tmpPolygon.lines[1].startPoint, tmpPolygon.lines[2].startPoint, length3 - length4)
const scale = (length1 - length2) / coord.x
tmpPolygon.set({ scaleX: scale })
pointsArray[0].x = 0
pointsArray[0].y = length3 //바닥면부터 시작하게
pointsArray[1].x = pointsArray[0].x + length1
pointsArray[1].y = pointsArray[0].y
pointsArray[2].x = pointsArray[1].x
pointsArray[2].y = pointsArray[1].y - length4
pointsArray[3].x = pointsArray[2].x - length2
pointsArray[3].y = pointsArray[2].y
pointsArray[4].x = tmpPolygon.getCurrentPoints()[2].x
pointsArray[4].y = tmpPolygon.getCurrentPoints()[2].y
points = [
{
x: pointer.x - length1 / 2,
y: pointer.y + length4 / 2,
},
{
x: pointer.x + length1 / 2,
y: pointer.y + length4 / 2,
},
{
x: pointer.x + length1 / 2,
y: pointer.y - length4 / 2,
},
{
x: pointer.x - (length2 - length1 / 2),
y: pointer.y - length4 / 2,
},
{
x: pointer.x - length1 / 2 + pointsArray[4].x,
y: pointer.y - length3 + length4 / 2,
},
]
break
}
case 14: {
points = [
{ x: pointer.x - length1 / 2 + length2, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 - length4 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 },
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 + length4 },
{ x: pointer.x - length1 / 2 + length1 - length3, y: pointer.y + length4 / 2 - length4 + length4 },
{ x: pointer.x - length1 / 2 + length2 + (length1 - length2 - length3) / 2, y: pointer.y + length4 / 2 - length4 + length5 },
]
break
}
case 15: {
points = [
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 },
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
{ x: pointer.x, y: pointer.y + length2 - length2 / 2 - length3 - (length2 - length3) },
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 + length3 },
]
break
}
case 16: {
points = [
{
x: pointer.x - length1 / 2,
y: pointer.y + length3 / 2,
},
{
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
y: pointer.y + length3 / 2 - (length3 - length4),
},
{
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
},
{
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
},
{
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
y: pointer.y + length3 / 2 - (length3 - length4) - length4 + length4,
},
{
x: pointer.x - length1 / 2 + length1,
y: pointer.y + length3 / 2,
},
]
break
}
case 17: {
const angle = (Math.asin(length3 / length4) * 180) / Math.PI // 높이와 빗변으로 먼저 각도구하기
const topL = (length1 - length2) / 2 / Math.cos((angle * Math.PI) / 180) // 꺽이는부분 윗쪽 길이
points = [
{
x: pointer.x - length1 / 2 + length1,
y: pointer.y + length3 / 2,
},
{
x: pointer.x - length1 / 2,
y: pointer.y + length3 / 2,
},
{
x: pointer.x - length1 / 2 + length4 * Math.cos(angle),
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
},
{
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2,
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
},
{
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2 + topL * Math.cos(degreesToRadians(angle)),
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)) + topL * Math.sin(degreesToRadians(angle)),
},
]
break
}
case 18: {
const a = Math.sqrt(length3 * length3 - length2 * length2) // 입력된 밑변과 높이
const sinA = a / length3
const angleInRadians = Math.asin(sinA)
const angleInDegrees = angleInRadians * (180 / Math.PI)
const b = a - length1 / 2
const c = b / Math.tan(angleInRadians)
const d = Math.sqrt(b * b + c * c)
const newAngleInRadians = (90 - angleInDegrees) * (Math.PI / 180)
points = [
{ x: pointer.x - (length1 + b) / 2, y: pointer.y + length2 / 2 },
{ x: pointer.x + length1 / 2 - b / 2, y: pointer.y + length2 / 2 },
{
x: pointer.x + length1 / 2 - b / 2 + d * Math.cos(newAngleInRadians),
y: pointer.y + length2 / 2 - d * Math.sin(newAngleInRadians),
},
{
x: pointer.x - (length1 + b) / 2 + length3 * Math.cos(newAngleInRadians),
y: pointer.y + length2 / 2 - length3 * Math.sin(newAngleInRadians),
},
]
break
}
}
return points
}
//면형상 선택 클릭시 지붕 패턴 입히기
const setSurfaceShapePattern = (polygon) => {
const ratio = window.devicePixelRatio || 1
let width = 265 / 10
let height = 150 / 10
let roofStyle = 2
const inputPatternSize = { width: width, height: height } //임시 사이즈
const patternSize = { ...inputPatternSize } // 입력된 값을 뒤집기 위해
if (polygon.direction === 'east' || polygon.direction === 'west') {
//세로형이면 width height를 바꿈
;[patternSize.width, patternSize.height] = [inputPatternSize.height, patternSize.width]
}
// 패턴 소스를 위한 임시 캔버스 생성
const patternSourceCanvas = document.createElement('canvas')
patternSourceCanvas.width = polygon.width * ratio
patternSourceCanvas.height = polygon.height * ratio
const ctx = patternSourceCanvas.getContext('2d')
const offset = roofStyle === 1 ? 0 : patternSize.width / 2
const rows = Math.floor(patternSourceCanvas.height / patternSize.height)
const cols = Math.floor(patternSourceCanvas.width / patternSize.width)
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()
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()
}
}
// 패턴 생성
const pattern = new fabric.Pattern({
source: patternSourceCanvas,
repeat: 'repeat',
})
polygon.set('fill', null)
polygon.set('fill', pattern)
canvas?.renderAll()
}
return {
applySurfaceShape,
}
}

View File

@ -361,5 +361,12 @@
"main.content.objectList": "最近の更新物件一覧",
"main.content.notice": "お知らせ",
"main.content.download1": "操作マニュアル",
"main.content.download2": "屋根の説明書"
"main.content.download2": "屋根の説明書",
"surface.shape.validate.size": "寸法を入力してください.",
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.1to3": "①길이는 ③보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.1to23": "①길이는 ②+③보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.2to3": "②길이는 ③보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.3to4": "③길이는 ④보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.4to5": "④길이는 ⑤보다 큰 값을 넣어주세요."
}

View File

@ -367,5 +367,12 @@
"main.content.objectList": "최근 갱신 물건목록",
"main.content.notice": "공지사항",
"main.content.download1": "조작메뉴얼",
"main.content.download2": "지붕설명서"
"main.content.download2": "지붕설명서",
"surface.shape.validate.size": "사이즈를 입력해 주세요.",
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.1to3": "①길이는 ③보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.1to23": "①길이는 ②+③보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.2to3": "②길이는 ③보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.3to4": "③길이는 ④보다 큰 값을 넣어주세요.",
"surface.shape.validate.size.4to5": "④길이는 ⑤보다 큰 값을 넣어주세요."
}