diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx
index ed2e837f..d7130911 100644
--- a/src/components/Roof2.jsx
+++ b/src/components/Roof2.jsx
@@ -1,7 +1,7 @@
'use client'
import { useCanvas } from '@/hooks/useCanvas'
-import { useEffect, useRef, useState } from 'react'
+import { useCallback, useEffect, useRef, useState } from 'react'
import { v4 as uuidv4 } from 'uuid'
import { useMode } from '@/hooks/useMode'
import { Mode } from '@/common/common'
@@ -21,7 +21,7 @@ import {
} from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { getCanvasState, insertCanvasState } from '@/lib/canvas'
-import { calculateIntersection } from '@/util/canvas-util'
+import { calculateIntersection, distanceBetweenPoints } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon'
import ThumbnailList from './ui/ThumbnailLIst'
import QContextMenu from './common/context-menu/QContextMenu'
@@ -31,6 +31,7 @@ import { useAxios } from '@/hooks/useAxios'
import QPolygonContextMenu from '@/components/common/context-menu/QPolygonContextMenu'
import QLineContextMenu from '@/components/common/context-menu/QLineContextMenu'
import QEmptyContextMenu from '@/components/common/context-menu/QEmptyContextMenu'
+import { radiansToDegrees } from '@turf/turf'
export default function Roof2(props) {
const { name, userId, email, isLoggedIn } = props
@@ -571,6 +572,1001 @@ export default function Roof2(props) {
canvas?.renderAll()
}
+ const createTemplate1 = () => {
+ const length1 = prompt('1번')
+ const length2 = prompt('2번')
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { x: pointer.x, y: pointer.y - parseInt(length2) / 2 },
+ { x: pointer.x - parseInt(length1) / 2, y: pointer.y + parseInt(length1) / 2 },
+ { x: pointer.x + parseInt(length1) / 2, y: pointer.y + parseInt(length1) / 2 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+
+ const createPentagon2 = () => {
+ const a = 400 //Number(prompt('a'))
+ const b = 200 //Number(prompt('b'))
+ const c = 250 //Number(prompt('c'))
+ const d = 150 //Number(prompt('d'))
+
+ const t = (c * (a - b)) / (200 + c)
+
+ const t2 = Math.sqrt(c * c + t * t)
+
+ const t3 = Math.sqrt((c - d) * (c - d) + (a - b - t) * (a - b - t))
+
+ const angle = Math.atan(t2 / t)
+ const angle2 = Math.atan(t3 / (a - b - t))
+
+ console.log(angle, angle2)
+
+ let isDrawing = true
+ let pentagon
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+
+ pentagon = new QPolygon(
+ [
+ { x: pointer.x - a / 2, y: pointer.y + a / 2 - d },
+ { x: pointer.x + a / 2, y: pointer.y + a / 2 - d },
+ { x: pointer.x + a / 2, y: pointer.y + a / 2 - d - d },
+ { x: pointer.x + a / 2 - b, y: pointer.y + a / 2 - d - d },
+ {
+ x: pointer.x + a / 2 - b - t3 * Math.cos(angle),
+ y: pointer.y + a / 2 - d - d - t3 * Math.sin(angle),
+ },
+ /*{
+ x: pointer.x - a / 2 + t2 * Math.cos(angle),
+ y: pointer.y + a / 2 - d - t2 * Math.sin(angle),
+ },*/
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'gray',
+ strokeWidth: 1,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(pentagon)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ pentagon.set('name', 'roof')
+ pentagon.set('stroke', 2)
+ canvas?.renderAll()
+ })
+ }
+
+ const createTemplate2 = () => {
+ const length1 = prompt('1번')
+ const length2 = prompt('2번')
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+
+ const createTemplate3 = () => {
+ const length1 = Number(prompt('1번'))
+ const length2 = Number(prompt('2번'))
+ const length3 = Number(prompt('3번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+
+ const createTemplate4 = () => {
+ const length1 = Number(prompt('1번'))
+ const length2 = Number(prompt('2번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+
+ const createTemplate5 = () => {
+ const length1 = Number(prompt('1번'))
+ const length2 = Number(prompt('2번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+
+ const createTemplate6 = () => {
+ const length1 = Number(prompt('1번'))
+ const length2 = Number(prompt('2번'))
+ const length3 = Number(prompt('3번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate7 = () => {
+ const length1 = Number(prompt('1번'))
+ const length2 = Number(prompt('2번'))
+ const length3 = Number(prompt('3번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate8 = () => {
+ const length1 = Number(prompt('1번')) // 밑변
+ const length2 = Number(prompt('2번')) // 높이
+ const length3 = Number(prompt('3번')) // 빗변
+
+ const angleInRadians = Math.asin(length2 / length3)
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate9 = () => {
+ const length1 = Number(prompt('1번')) // 밑변
+ const length2 = Number(prompt('2번')) // 높이
+ const length3 = Number(prompt('3번')) // 빗변
+
+ const angleInRadians = Math.asin(length2 / length3)
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate10 = () => {
+ const length1 = Number(prompt('1번'))
+ const length2 = Number(prompt('2번'))
+ const length3 = Number(prompt('3번'))
+ const length4 = Number(prompt('4번'))
+ const length5 = Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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),
+ },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate11 = () => {
+ const length1 = 200 //Number(prompt('1번'))
+ const length2 = 100 //Number(prompt('2번'))
+ const length3 = 400 //Number(prompt('3번'))
+ const length4 = 300 //Number(prompt('4번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate12 = () => {
+ const length1 = 200 //Number(prompt('1번'))
+ const length2 = 100 //Number(prompt('2번'))
+ const length3 = 400 //Number(prompt('3번'))
+ const length4 = 300 //Number(prompt('4번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate13 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 150 //Number(prompt('2번'))
+ const length3 = 100 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('4번'))
+ const length5 = 200 //Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate14 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 150 //Number(prompt('2번'))
+ const length3 = 100 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('4번'))
+ const length5 = 200 //Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate15 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 150 //Number(prompt('2번'))
+ const length3 = 100 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('4번'))
+ const length5 = 200 //Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate16 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 150 //Number(prompt('2번'))
+ const length3 = 100 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('4번'))
+ const length5 = 200 //Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate17 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 150 //Number(prompt('2번'))
+ const length3 = 250 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('4번'))
+ const length5 = 200 //Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate18 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 150 //Number(prompt('2번'))
+ const length3 = 250 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('4번'))
+ const length5 = 200 //Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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) },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ /**
+ * 19~22번은 못함
+ */
+ const createTemplate23 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 100 //Number(prompt('2번'))
+ const length3 = 150 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('4번'))
+ const length5 = 300 //Number(prompt('5번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+
+ const createTemplate24 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 400 //Number(prompt('2번'))
+ const length3 = 300 //Number(prompt('3번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ { 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 },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate25 = () => {
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 200 //Number(prompt('2번'))
+ const length3 = 300 //Number(prompt('3번'))
+ const length4 = 200 //Number(prompt('3번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon(
+ [
+ {
+ 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,
+ },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate26 = () => {
+ //todo
+ const length1 = 300 //Number(prompt('1번'))
+ const length2 = 200 //Number(prompt('2번'))
+ const length3 = 300 //Number(prompt('3번'))
+ const length4 = 400 //Number(prompt('3번'))
+
+ let isDrawing = true
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const triangle = new QPolygon([], {
+ fill: 'transparent',
+ stroke: 'black',
+ strokeWidth: 2,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ })
+
+ canvas?.add(triangle)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ })
+ }
+ const createTemplate28 = () => {
+ const length1 = Number(prompt('밑변'))
+ const length2 = Number(prompt('높이'))
+ const length3 = Number(prompt('빗변'))
+
+ 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)
+
+ if (isNaN(a)) {
+ alert('값이 잘못되었습니다.')
+ return
+ }
+ if (b < 0) {
+ alert('값이 잘못되었습니다.')
+ return
+ }
+ if (angleInDegrees === 0 || angleInRadians === 0) {
+ alert('값이 잘못되었습니다.')
+ return
+ }
+
+ let isDrawing = true
+ let pentagon
+ canvas?.on('mouse:move', (e) => {
+ if (!isDrawing) {
+ return
+ }
+ canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
+ const pointer = canvas?.getPointer(e.e)
+ const newAngleInRadians = (90 - angleInDegrees) * (Math.PI / 180)
+
+ pentagon = new QPolygon(
+ [
+ { 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),
+ },
+ ],
+ {
+ fill: 'transparent',
+ stroke: 'gray',
+ strokeWidth: 1,
+ selectable: true,
+ fontSize: fontSize,
+ name: 'guideTriangle',
+ },
+ )
+
+ canvas?.add(pentagon)
+ })
+
+ canvas?.on('mouse:down', (e) => {
+ isDrawing = false
+ pentagon.set('name', 'roof')
+ pentagon.set('stroke', 2)
+ canvas?.renderAll()
+ })
+ }
+
return (
<>
{canvas && (
@@ -717,6 +1713,78 @@ export default function Roof2(props) {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/fabric/HelpLine.js b/src/components/fabric/HelpLine.js
deleted file mode 100644
index 68112099..00000000
--- a/src/components/fabric/HelpLine.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import { fabric } from 'fabric'
-
-export class QLine extends fabric.Group {
- line
- text
- fontSize
- length = 0
- x1
- y1
- x2
- y2
- direction
- type = 'HelpLine'
- parent
- #lengthTxt = 0
-
- constructor(points, option, lengthTxt) {
- const [x1, y1, x2, y2] = points
-
- if (!option.fontSize) {
- throw new Error('Font size is required.')
- }
-
- const line = new fabric.Line(points, { ...option, strokeWidth: 1 })
- super([line], {})
-
- this.x1 = x1
- this.y1 = y1
- this.x2 = x2
- this.y2 = y2
- this.line = line
- this.fontSize = option.fontSize
- this.direction = option.direction
- this.parent = option.parent
-
- if (lengthTxt > 0) {
- this.#lengthTxt = Number(lengthTxt)
- }
-
- this.#init()
- this.#addControl()
- }
-
- #init() {
- this.#addLengthText(true)
- }
-
- #addControl() {
- this.on('moving', () => {
- this.#addLengthText(false)
- })
-
- this.on('modified', (e) => {
- this.#addLengthText(false)
- })
-
- this.on('selected', () => {
- Object.keys(this.controls).forEach((controlKey) => {
- if (controlKey !== 'ml' && controlKey !== 'mr') {
- this.setControlVisible(controlKey, false)
- }
- })
- })
- }
-
- #addLengthText(isFirst) {
- if (this.text) {
- this.removeWithUpdate(this.text)
- this.text = null
- }
-
- if (isFirst && this.#lengthTxt > 0) {
- const text = new fabric.Textbox(this.#lengthTxt.toFixed(0).toString(), {
- left: (this.x1 + this.x2) / 2,
- top: (this.y1 + this.y2) / 2,
- fontSize: this.fontSize,
- })
- this.length = this.#lengthTxt
- this.text = text
- this.addWithUpdate(text)
- return
- }
-
- const scaleX = this.scaleX
- const scaleY = this.scaleY
- const x1 = this.left
- const y1 = this.top
- const x2 = this.left + this.width * scaleX
- const y2 = this.top + this.height * scaleY
- const dx = x2 - x1
- const dy = y2 - y1
- this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0))
-
- const text = new fabric.Textbox(this.length.toFixed(0).toString(), {
- left: (x1 + x2) / 2,
- top: (y1 + y2) / 2,
- fontSize: this.fontSize,
- })
- this.text = text
- this.addWithUpdate(text)
- }
-
- setFontSize(fontSize) {
- this.fontSize = fontSize
- this.text.set({ fontSize })
- this.addWithUpdate()
- }
-}
diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js
index c5093f91..c6da782f 100644
--- a/src/components/fabric/QPolygon.js
+++ b/src/components/fabric/QPolygon.js
@@ -18,6 +18,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
parentId: null,
innerLines: [],
children: [],
+ initOptions: null,
initialize: function (points, options, canvas) {
// 소수점 전부 제거
points.forEach((point) => {
@@ -58,6 +59,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.canvas = canvas
}
+ this.initOptions = options
+
this.init()
this.initLines()
this.setShape()
@@ -177,7 +180,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
const degree = (Math.atan2(dy, dx) * 180) / Math.PI
// Create new text object if it doesn't exist
- const text = new fabric.Text(length.toFixed(0), {
+ const text = new fabric.IText(length.toFixed(0), {
left: midPoint.x,
top: midPoint.y,
fontSize: this.fontSize,
@@ -189,7 +192,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
parentDirection: getDirectionByPoint(start, end),
parentDegree: degree,
dirty: true,
- editable: false,
+ editable: true,
selectable: true,
lockRotation: true,
lockScalingX: true,
diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js
index ee2f2fdd..e5582733 100644
--- a/src/hooks/useCanvasEvent.js
+++ b/src/hooks/useCanvasEvent.js
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
import { fabric } from 'fabric'
import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasSizeState, currentObjectState, modeState } from '@/store/canvasAtom'
+import { QPolygon } from '@/components/fabric/QPolygon'
// 캔버스에 필요한 이벤트
export function useCanvasEvent() {
@@ -77,11 +78,55 @@ export function useCanvasEvent() {
if (target.name === 'lengthText') {
const x = target.left
const y = target.top
+ // Add a property to store the previous value
+ const previousValue = target.text
target.on('selected', (e) => {
Object.keys(target.controls).forEach((controlKey) => {
target.setControlVisible(controlKey, false)
})
})
+ target.on('editing:exited', () => {
+ if (isNaN(target.text.trim())) {
+ target.set({ text: previousValue })
+ canvas?.renderAll()
+ return
+ }
+ const updatedValue = parseFloat(target.text.trim())
+ const targetParent = target.parent
+ const points = targetParent.getCurrentPoints()
+ const i = target.idx // Assuming target.index gives the index of the point
+
+ const startPoint = points[i]
+ const endPoint = points[(i + 1) % points.length]
+
+ const dx = endPoint.x - startPoint.x
+ const dy = endPoint.y - startPoint.y
+
+ const currentLength = Math.sqrt(dx * dx + dy * dy)
+ const scaleFactor = updatedValue / currentLength
+
+ const newEndPoint = {
+ x: startPoint.x + dx * scaleFactor,
+ y: startPoint.y + dy * scaleFactor,
+ }
+
+ const newPoints = [...points]
+ newPoints[(i + 1) % points.length] = newEndPoint
+
+ for (let idx = i + 1; idx < points.length; idx++) {
+ if (newPoints[idx].x === endPoint.x) {
+ newPoints[idx].x = newEndPoint.x
+ } else if (newPoints[idx].y === endPoint.y) {
+ newPoints[idx].y = newEndPoint.y
+ }
+ }
+
+ const newPolygon = new QPolygon(newPoints, targetParent.initOptions)
+ canvas?.add(newPolygon)
+ canvas?.remove(targetParent)
+ canvas?.renderAll()
+ })
+
target.on('moving', (e) => {
if (target.parentDirection === 'left' || target.parentDirection === 'right') {
const minX = target.minX
@@ -116,7 +161,6 @@ export function useCanvasEvent() {
if (whiteList.includes(e.target.name)) {
return
}
- console.log('removed', e)
},
}
diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js
index 4d6dc238..b6c4680d 100644
--- a/src/hooks/useMode.js
+++ b/src/hooks/useMode.js
@@ -101,6 +101,8 @@ export function useMode() {
}, [endPoint])
useEffect(() => {
+ canvas?.off('mouse:out', removeMouseLines)
+ canvas?.on('mouse:out', removeMouseLines)
changeMode(canvas, mode)
canvas?.off('mouse:move')
canvas?.on('mouse:move', drawMouseLines)
@@ -160,6 +162,53 @@ export function useMode() {
if (mode === Mode.EDIT || mode === Mode.ADSORPTION_POINT) {
let adsorptionPoint = adsorptionPointList.length > 0 ? findClosestPoint(pointer, adsorptionPointList) : null
if ((horiGuideLines.length > 0 || vertGuideLines.length > 0) && guideDotMode) {
+ const closestHorizontalLine = getClosestHorizontalLine(pointer, horiGuideLines)
+ const closetVerticalLine = getClosestVerticalLine(pointer, vertGuideLines)
+ let intersection = null
+ let intersectionDistance = Infinity
+
+ if (closestHorizontalLine && closetVerticalLine) {
+ intersection = calculateIntersection(closestHorizontalLine, closetVerticalLine)
+ if (intersection) {
+ intersectionDistance = distanceBetweenPoints(pointer, intersection)
+ }
+ }
+
+ let xDiff, yDiff
+
+ if (closetVerticalLine) {
+ xDiff = Math.abs(pointer.x - closetVerticalLine.x1)
+ }
+ if (closestHorizontalLine) {
+ yDiff = Math.abs(pointer.y - closestHorizontalLine.y1)
+ }
+
+ const x = pointer.x - guideLineLengthHori * Math.floor(pointer.x / guideLineLengthHori)
+ const y = pointer.y - guideLineLengthVert * Math.floor(pointer.y / guideLineLengthVert)
+
+ const xRate = x / guideLineLengthHori
+ const yRate = y / guideLineLengthVert
+ const isAttachX = xRate >= 0.4 && xRate <= 0.7
+ const isAttachY = yRate >= 0.4 && yRate <= 0.7
+ if (isAttachX && isAttachY) {
+ newX = Math.floor(pointer.x / guideLineLengthHori) * guideLineLengthHori + guideLineLengthHori / 2
+ newY = Math.floor(pointer.y / guideLineLengthVert) * guideLineLengthVert + guideLineLengthVert / 2
+ } else {
+ if (intersection && intersectionDistance < 20) {
+ newX = intersection.x
+ newY = intersection.y
+ } else {
+ if (Math.min(xDiff, yDiff) <= 20) {
+ if (xDiff < yDiff) {
+ newX = closetVerticalLine.x1
+ newY = pointer.y
+ } else {
+ newX = pointer.x
+ newY = closestHorizontalLine.y1
+ }
+ }
+ }
+ }
} else if (guideDotMode) {
const x = pointer.x - guideLineLengthHori * Math.floor(pointer.x / guideLineLengthHori)
const y = pointer.y - guideLineLengthVert * Math.floor(pointer.y / guideLineLengthVert)