880 lines
32 KiB
JavaScript
880 lines
32 KiB
JavaScript
import { Button, Input } from '@nextui-org/react'
|
|
import { useState } from 'react'
|
|
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
|
import { modalState } from '@/store/modalAtom'
|
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
|
import { fontSizeState, roofMaterialState } from '@/store/canvasAtom'
|
|
import { degreesToRadians } from '@turf/turf'
|
|
import { getIntersectionPoint } from '@/util/canvas-util'
|
|
|
|
/**
|
|
* 면형상 배치 모달
|
|
* @returns {JSX.Element}
|
|
* @constructor
|
|
*/
|
|
export const SurfaceShapeModal = ({ canvas }) => {
|
|
const [type, setType] = useState(1)
|
|
const setOpen = useSetRecoilState(modalState)
|
|
const fontSize = useRecoilValue(fontSizeState)
|
|
//지붕재
|
|
const roofMaterial = useRecoilValue(roofMaterialState)
|
|
|
|
/**
|
|
* 최대 5개의 length
|
|
*/
|
|
const [length1, setLength1] = useState(0)
|
|
const [length2, setLength2] = useState(0)
|
|
const [length3, setLength3] = useState(0)
|
|
const [length4, setLength4] = useState(0)
|
|
const [length5, setLength5] = useState(0)
|
|
|
|
// 방향
|
|
const [direction, setDirection] = useState('south')
|
|
|
|
/**
|
|
* 최대 5개의 length
|
|
*/
|
|
const onChangeType = (e) => {
|
|
setType(Number(e.target.value))
|
|
}
|
|
|
|
const closeModal = () => {
|
|
setOpen(false)
|
|
}
|
|
|
|
const onSave = () => {
|
|
if (!checkValid()) {
|
|
alert('안됨')
|
|
return
|
|
}
|
|
let isDrawing = true
|
|
let obj = null
|
|
let points = []
|
|
canvas?.on('mouse:move', (e) => {
|
|
if (!isDrawing) {
|
|
return
|
|
}
|
|
const pointer = canvas?.getPointer(e.e)
|
|
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
|
|
switch (type) {
|
|
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 + length2 / 2 },
|
|
{ x: pointer.x - length1 / 2, y: pointer.y + length2 / 2 },
|
|
{ x: pointer.x - length1 / 2, y: pointer.y - length2 / 2 },
|
|
]
|
|
|
|
break
|
|
}
|
|
|
|
case 6: {
|
|
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 7: {
|
|
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 - length3 },
|
|
]
|
|
|
|
break
|
|
}
|
|
case 8: {
|
|
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 9: {
|
|
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 10: {
|
|
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 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 - 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 12: {
|
|
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 - length2, y: pointer.y + length4 / 2 - length4 },
|
|
{ x: pointer.x - length1 / 2 + length1 - length2, y: pointer.y + length4 / 2 - length4 - (length3 - length4) },
|
|
{ x: pointer.x - length1 / 2 + length1 - length2 - (length1 - length2), y: pointer.y + length4 / 2 - length4 - (length3 - length4) },
|
|
]
|
|
|
|
break
|
|
}
|
|
case 13: {
|
|
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 14: {
|
|
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 15: {
|
|
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 16: {
|
|
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 17: {
|
|
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 18: {
|
|
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 19: {
|
|
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 20: {
|
|
// 좌측 빗변
|
|
const rightHypotenuse = Math.sqrt(((length1 - length2) / 2) ** 2 + length3 ** 2)
|
|
const leftHypotenuse = (length4 / length3) * rightHypotenuse
|
|
|
|
const rightAngle = Math.acos((length1 - length2) / 2 / rightHypotenuse)
|
|
points = [
|
|
{
|
|
x: pointer.x + length1 / 2 - rightHypotenuse * Math.cos(rightAngle),
|
|
y: pointer.y + length3 / 2 - rightHypotenuse * Math.sin(rightAngle),
|
|
},
|
|
{ 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 + leftHypotenuse * Math.cos(rightAngle),
|
|
y: pointer.y + length3 / 2 - leftHypotenuse * Math.sin(rightAngle),
|
|
},
|
|
{
|
|
x: pointer.x - length1 / 2 + leftHypotenuse * Math.cos(rightAngle) + length2,
|
|
y: pointer.y + length3 / 2 - leftHypotenuse * Math.sin(rightAngle),
|
|
},
|
|
]
|
|
break
|
|
}
|
|
case 21: {
|
|
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 22: {
|
|
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 23: {
|
|
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 24: {
|
|
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 25: {
|
|
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 26: {
|
|
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(degreesToRadians(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 27: {
|
|
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,
|
|
y: pointer.y + length3 / 2,
|
|
},
|
|
{
|
|
x: pointer.x - length1 / 2 + length1,
|
|
y: pointer.y + length3 / 2,
|
|
},
|
|
{
|
|
x: pointer.x - length1 / 2 + length1 - length4 * Math.cos(degreesToRadians(angle)),
|
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
|
},
|
|
{
|
|
x: pointer.x - length1 / 2 + length1 - length4 * Math.cos(degreesToRadians(angle)) - length2,
|
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
|
},
|
|
{
|
|
x: pointer.x - length1 / 2 + length1 - 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 28: {
|
|
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
|
|
}
|
|
case 29: {
|
|
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 / 2 - b / 2 - length3 * Math.cos(newAngleInRadians),
|
|
y: pointer.y + length2 / 2 - length3 * Math.sin(newAngleInRadians),
|
|
},
|
|
{ x: pointer.x + length1 / 2 - b / 2, y: pointer.y + length2 / 2 },
|
|
{ x: pointer.x - (length1 + b) / 2, y: pointer.y + length2 / 2 },
|
|
{ x: pointer.x - (length1 + b) / 2 - d * Math.cos(newAngleInRadians), y: pointer.y + length2 / 2 - d * Math.sin(newAngleInRadians) },
|
|
]
|
|
break
|
|
}
|
|
}
|
|
|
|
const options = {
|
|
fill: 'transparent',
|
|
stroke: 'black',
|
|
strokeWidth: 2,
|
|
selectable: true,
|
|
fontSize: fontSize,
|
|
lockMovementX: true, // X 축 이동 잠금
|
|
lockMovementY: true, // Y 축 이동 잠금
|
|
lockRotation: true, // 회전 잠금
|
|
lockScalingX: true, // X 축 크기 조정 잠금
|
|
lockScalingY: true, // Y 축 크기 조정 잠금
|
|
name: 'guideTriangle',
|
|
flipX: type === 22 ? true : false,
|
|
}
|
|
|
|
obj = new QPolygon(points, options)
|
|
obj.setCoords() //좌표 변경 적용
|
|
|
|
canvas?.add(obj)
|
|
obj.set({ direction: direction })
|
|
setCurrentPattern(obj)
|
|
canvas?.renderAll()
|
|
})
|
|
|
|
canvas?.on('mouse:down', (e) => {
|
|
isDrawing = false
|
|
obj.set('name', 'roof')
|
|
})
|
|
setOpen(false)
|
|
}
|
|
|
|
const checkValid = () => {
|
|
let result = true
|
|
switch (type) {
|
|
case 1: {
|
|
if (length3 !== 0 && length1 > length3) {
|
|
return
|
|
}
|
|
break
|
|
}
|
|
case 3: {
|
|
if (length3 > length1) {
|
|
return
|
|
}
|
|
break
|
|
}
|
|
case 6: {
|
|
if (length3 > length1) {
|
|
return
|
|
}
|
|
break
|
|
}
|
|
case 7: {
|
|
if (length3 > length1) {
|
|
return
|
|
}
|
|
break
|
|
}
|
|
case 8: {
|
|
if (length2 > length3) {
|
|
return
|
|
}
|
|
break
|
|
}
|
|
case 9: {
|
|
if (length2 > length3) {
|
|
return
|
|
}
|
|
break
|
|
}
|
|
case 21: {
|
|
if (length1 < length2) {
|
|
alert('1번보다 작게 입력해주세요.')
|
|
return
|
|
}
|
|
|
|
if (length3 < length4) {
|
|
alert('3번보다 작게 입력해주세요.')
|
|
return
|
|
}
|
|
}
|
|
case 22: {
|
|
if (length1 < length2) {
|
|
alert('1번보다 작게 입력해주세요.')
|
|
return
|
|
}
|
|
|
|
if (length3 < length4) {
|
|
alert('3번보다 작게 입력해주세요.')
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
const setLength = (e) => {
|
|
let { name, value } = e.target
|
|
value = value.replace(/[^-0-9]/g, '')
|
|
switch (name) {
|
|
case 'length1':
|
|
setLength1(Number(value))
|
|
break
|
|
case 'length2':
|
|
setLength2(Number(value))
|
|
break
|
|
case 'length3':
|
|
setLength3(Number(value))
|
|
break
|
|
case 'length4':
|
|
setLength4(Number(value))
|
|
break
|
|
case 'length5':
|
|
setLength5(Number(value))
|
|
break
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
const setCurrentPattern = (polygon) => {
|
|
const { width, height, roofStyle } = roofMaterial
|
|
const roofRatio = window.devicePixelRatio || 1
|
|
const patternSourceCanvas = document.createElement('canvas')
|
|
|
|
if (roofStyle === 1) {
|
|
patternSourceCanvas.width = width * roofRatio
|
|
patternSourceCanvas.height = height * roofRatio
|
|
} else if (roofStyle === 2) {
|
|
patternSourceCanvas.width = width * 2
|
|
patternSourceCanvas.height = height * 2
|
|
}
|
|
|
|
const ctx = patternSourceCanvas.getContext('2d')
|
|
|
|
ctx.scale(roofRatio, roofRatio)
|
|
ctx.strokeStyle = 'green'
|
|
ctx.lineWidth = 0.4
|
|
// 벽돌 패턴 그리기
|
|
if (roofStyle === 1) {
|
|
ctx.strokeRect(0, 0, 50, 30)
|
|
} else if (roofStyle === 2) {
|
|
// 지그재그
|
|
ctx.strokeRect(0, 0, 200, 100)
|
|
ctx.strokeRect(100, 100, 200, 100)
|
|
}
|
|
|
|
// 패턴 생성
|
|
const pattern = new fabric.Pattern({
|
|
source: patternSourceCanvas,
|
|
repeat: 'repeat',
|
|
})
|
|
polygon.set('fill', null)
|
|
|
|
polygon.set('fill', pattern)
|
|
canvas?.renderAll()
|
|
}
|
|
|
|
const ButtonComp = () => {
|
|
// Generate 29 buttons
|
|
const buttons = []
|
|
for (let i = 1; i <= 29; i++) {
|
|
buttons.push(
|
|
<Button key={i} className="m-1 p-2" value={i} onClick={onChangeType}>
|
|
{i}번 추가
|
|
</Button>,
|
|
)
|
|
}
|
|
|
|
return <div>{buttons}</div>
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div>
|
|
<div>면형상배치{type}</div>
|
|
<ButtonComp></ButtonComp>
|
|
</div>
|
|
{type === 1 ? (
|
|
<div>
|
|
길이1
|
|
<Input type="text" name={'length1'} value={length1} onChange={setLength} />
|
|
{length3 === 0 && (
|
|
<>
|
|
길이2
|
|
<Input type="text" name={'length2'} value={length2} onChange={setLength} />
|
|
</>
|
|
)}
|
|
대각선 <Input type="text" name={'length3'} value={length3} onChange={setLength} />
|
|
</div>
|
|
) : [2, 4, 5].includes(type) ? (
|
|
<div>
|
|
길이1
|
|
<Input type="text" name={'length1'} value={length1} onChange={setLength} />
|
|
길이2
|
|
<Input type="text" name={'length2'} value={length2} onChange={setLength} />
|
|
</div>
|
|
) : [3, 6, 7, 8, 9, 24, 28, 29].includes(type) ? (
|
|
<>
|
|
길이1
|
|
<Input type="text" name={'length1'} value={length1} onChange={setLength} />
|
|
길이2
|
|
<Input type="text" name={'length2'} value={length2} onChange={setLength} />
|
|
길이3
|
|
<Input type="text" name={'length3'} value={length3} onChange={setLength} />
|
|
</>
|
|
) : [11, 12, 19, 20, 21, 22, 25, 26, 27].includes(type) ? (
|
|
<>
|
|
길이1
|
|
<Input type="text" name={'length1'} value={length1} onChange={setLength} />
|
|
길이2
|
|
<Input type="text" name={'length2'} value={length2} onChange={setLength} />
|
|
길이3
|
|
<Input type="text" name={'length3'} value={length3} onChange={setLength} />
|
|
길이4
|
|
<Input type="text" name={'length4'} value={length4} onChange={setLength} />
|
|
</>
|
|
) : [10, 13, 14, 15, 16, 17, 18, 23].includes(type) ? (
|
|
<>
|
|
길이1
|
|
<Input type="text" name={'length1'} value={length1} onChange={setLength} />
|
|
길이2
|
|
<Input type="text" name={'length2'} value={length2} onChange={setLength} />
|
|
길이3
|
|
<Input type="text" name={'length3'} value={length3} onChange={setLength} />
|
|
길이4
|
|
<Input type="text" name={'length4'} value={length4} onChange={setLength} />
|
|
길이5
|
|
<Input type="text" name={'length5'} value={length5} onChange={setLength} />
|
|
</>
|
|
) : (
|
|
<></>
|
|
)}
|
|
<div className="flex flex-col items-center">
|
|
<div className="flex">
|
|
<Button
|
|
className={`p-4 border rounded-lg ${direction === 'north' ? 'bg-blue-200' : ''} flex items-center justify-center`}
|
|
onClick={() => setDirection('north')}
|
|
>
|
|
북
|
|
</Button>
|
|
</div>
|
|
<div className="flex space-x-4">
|
|
<Button
|
|
className={`p-4 border rounded-lg ${direction === 'west' ? 'bg-blue-200' : ''} flex items-center justify-center`}
|
|
onClick={() => setDirection('west')}
|
|
>
|
|
서
|
|
</Button>
|
|
<Button
|
|
className={`p-4 border rounded-lg ${direction === 'east' ? 'bg-blue-200' : ''} flex items-center justify-center`}
|
|
onClick={() => setDirection('east')}
|
|
>
|
|
동
|
|
</Button>
|
|
</div>
|
|
<div className="mt-4">
|
|
<Button
|
|
className={`p-4 border rounded-lg ${direction === 'south' ? 'bg-blue-200' : ''} flex items-center justify-center`}
|
|
onClick={() => setDirection('south')}
|
|
>
|
|
남
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<Button className="m-1 p-2" color={'primary'} onClick={closeModal}>
|
|
닫기
|
|
</Button>
|
|
<Button className="m-1 p-2" color={'primary'} onClick={onSave}>
|
|
저장
|
|
</Button>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|