{!canvas ? null : mode === Mode.DRAW_LINE ? (
diff --git a/src/components/common/context-menu/QContextMenu.jsx b/src/components/common/context-menu/QContextMenu.jsx
index 57aaf45b..4658ef6f 100644
--- a/src/components/common/context-menu/QContextMenu.jsx
+++ b/src/components/common/context-menu/QContextMenu.jsx
@@ -1,6 +1,5 @@
'use client'
-import { useEffect, useState } from 'react'
-import { useRecoilState, useRecoilValue } from 'recoil'
+import { Children, useEffect, useState } from 'react'
export default function QContextMenu(props) {
const { contextRef, canvasProps } = props
@@ -8,6 +7,19 @@ export default function QContextMenu(props) {
// const children = useRecoilValue(modalContent)
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 })
+ const activeObject = canvasProps.getActiveObject() //액티브된 객체를 가져옴
+
+ let contextType = ''
+
+ if (activeObject) {
+ if (activeObject.initOptions) {
+ //이건 바뀔 가능성이 있음
+ if (activeObject.initOptions.name.indexOf('guide') > -1) {
+ contextType = 'surface' //면형상
+ }
+ }
+ }
+
useEffect(() => {
if (!contextRef.current) return
@@ -29,21 +41,49 @@ export default function QContextMenu(props) {
}
}
- // Prevent the default context menu from appearing on the canvas
canvasProps.upperCanvasEl.addEventListener('contextmenu', handleContextMenu)
document.addEventListener('click', handleClick)
document.addEventListener('click', handleOutsideClick)
return () => {
- // canvasProps.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu)
document.removeEventListener('click', handleClick)
document.removeEventListener('click', handleOutsideClick)
}
}, [contextRef, contextMenu])
- const handleMenuClick = (option) => {
- alert(`option ${option} clicked`)
- setContextMenu({ ...contextMenu, visible: false })
+ const handleObjectMove = () => {
+ activeObject.set({
+ lockMovementX: false, // X 축 이동 잠금
+ lockMovementY: false, // Y 축 이동 잠금
+ })
+
+ canvasProps.on('object:modified', function (e) {
+ activeObject.set({
+ lockMovementX: true, // X 축 이동 잠금
+ lockMovementY: true, // Y 축 이동 잠금
+ })
+ })
+ }
+
+ const handleObjectDelete = () => {
+ if (confirm('삭제하실거?')) {
+ canvasProps.remove(activeObject)
+ }
+ }
+
+ const handleObjectCopy = () => {
+ activeObject.clone((cloned) => {
+ cloned.set({
+ left: activeObject.left + activeObject.width + 20,
+ initOptions: { ...activeObject.initOptions },
+ lockMovementX: true, // X 축 이동 잠금
+ lockMovementY: true, // Y 축 이동 잠금
+ lockRotation: true, // 회전 잠금
+ lockScalingX: true, // X 축 크기 조정 잠금
+ lockScalingY: true, // Y 축 크기 조정 잠금
+ })
+ canvasProps?.add(cloned)
+ })
}
return (
@@ -51,15 +91,16 @@ export default function QContextMenu(props) {
{contextMenu.visible && (
- - handleMenuClick(1)}>
- Option 1
+
- handleObjectMove()}>
+ 이동
- - handleMenuClick(2)}>
- Option 2
+
- handleObjectDelete()}>
+ 삭제
- - handleMenuClick(3)}>
- Option 3
+
- handleObjectCopy()}>
+ 복사
+ {props.children}
)}
diff --git a/src/components/common/context-menu/QPolygonContextMenu.jsx b/src/components/common/context-menu/QPolygonContextMenu.jsx
index b3246165..12f8e20b 100644
--- a/src/components/common/context-menu/QPolygonContextMenu.jsx
+++ b/src/components/common/context-menu/QPolygonContextMenu.jsx
@@ -1,71 +1,20 @@
'use client'
-import { useEffect, useState } from 'react'
-import { useRecoilState, useRecoilValue } from 'recoil'
+import QContextMenu from './QContextMenu'
export default function QPolygonContextMenu(props) {
const { contextRef, canvasProps } = props
- // const children = useRecoilValue(modalContent)
- const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 })
-
- useEffect(() => {
- if (!contextRef.current) return
-
- const handleContextMenu = (e) => {
- e.preventDefault() //기존 contextmenu 막고
- setContextMenu({ visible: true, x: e.pageX, y: e.pageY })
- canvasProps.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
- }
-
- const handleClick = (e) => {
- e.preventDefault()
- setContextMenu({ ...contextMenu, visible: false })
- }
-
- const handleOutsideClick = (e) => {
- e.preventDefault()
- if (contextMenu.visible && !ref.current.contains(e.target)) {
- setContextMenu({ ...contextMenu, visible: false })
- }
- }
-
- // Prevent the default context menu from appearing on the canvas
- canvasProps.upperCanvasEl.addEventListener('contextmenu', handleContextMenu)
- document.addEventListener('click', handleClick)
- document.addEventListener('click', handleOutsideClick)
-
- return () => {
- // canvasProps.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu)
- document.removeEventListener('click', handleClick)
- document.removeEventListener('click', handleOutsideClick)
- }
- }, [contextRef, contextMenu])
-
- const handleMenuClick = (option) => {
- alert(`option ${option} clicked`)
- setContextMenu({ ...contextMenu, visible: false })
+ function handleMenuClick(index) {
+ alert('test')
}
return (
- <>
- {contextMenu.visible && (
-
-
- - handleMenuClick(1)}>
- polygon
-
- - handleMenuClick(1)}>
- Option 1
-
- - handleMenuClick(2)}>
- Option 2
-
- - handleMenuClick(3)}>
- Option 3
-
-
-
- )}
- >
+
+ <>
+ handleMenuClick(4)}>
+ 모듈 채우기
+
+ >
+
)
}
diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js
index 355fdf7f..3c8b2148 100644
--- a/src/components/fabric/QPolygon.js
+++ b/src/components/fabric/QPolygon.js
@@ -2,7 +2,15 @@ import { fabric } from 'fabric'
import { v4 as uuidv4 } from 'uuid'
import { QLine } from '@/components/fabric/QLine'
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
-import { calculateAngle, drawHippedRoof, inPolygon, splitPolygonWithLines, toGeoJSON } from '@/util/qpolygon-utils'
+import {
+ calculateAngle,
+ drawDirectionArrow,
+ drawHippedRoof,
+ drawPolygonArrow,
+ inPolygon,
+ splitPolygonWithLines,
+ toGeoJSON,
+} from '@/util/qpolygon-utils'
import * as turf from '@turf/turf'
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
@@ -19,6 +27,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
innerLines: [],
children: [],
initOptions: null,
+ direction: null,
+ arrow: null,
initialize: function (points, options, canvas) {
// 소수점 전부 제거
points.forEach((point) => {
@@ -100,6 +110,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
toObject: function (propertiesToInclude) {
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
+ id: this.id,
type: this.type,
text: this.text,
hips: this.hips,
@@ -116,9 +127,13 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.on('modified', (e) => {
this.addLengthText()
+ if (this.arrow) {
+ drawDirectionArrow(this)
+ }
})
this.on('selected', () => {
+ drawDirectionArrow(this)
Object.keys(this.controls).forEach((controlKey) => {
if (controlKey !== 'ml' && controlKey !== 'mr') {
this.setControlVisible(controlKey, false)
@@ -132,6 +147,17 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.canvas.remove(text)
})
this.texts = null
+
+ if (this.arrow) {
+ this.canvas.remove(this.arrow)
+ this.canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'directionText' && obj.parent === this.arrow)
+ .forEach((text) => {
+ this.canvas.remove(text)
+ })
+ this.arrow = null
+ }
})
// polygon.fillCell({ width: 50, height: 30, padding: 10 })
@@ -162,11 +188,13 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
},
addLengthText() {
- if (this.texts.length > 0) {
- this.texts.forEach((text) => {
+ this.canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'lengthText' && obj.parent === this)
+ .forEach((text) => {
this.canvas.remove(text)
})
- }
+
let points = this.getCurrentPoints()
points.forEach((start, i) => {
@@ -209,7 +237,12 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
},
setFontSize(fontSize) {
this.fontSize = fontSize
- this.text.set({ fontSize })
+ this.canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'lengthText' && obj.parent === this)
+ .forEach((text) => {
+ text.set({ fontSize: fontSize })
+ })
},
_render: function (ctx) {
this.callSuper('_render', ctx)
@@ -689,9 +722,20 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.wall = wall
},
setViewLengthText(isView) {
- this.texts.forEach((text) => {
- text.set({ visible: isView })
- })
+ this.canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'lengthText' && obj.parent === this)
+ .forEach((text) => {
+ text.set({ visible: isView })
+ })
+ },
+ setScaleX(scale) {
+ this.scaleX = scale
+ this.addLengthText()
+ },
+ setScaleY(scale) {
+ this.scaleY = scale
+ this.addLengthText()
},
divideLine() {
splitPolygonWithLines(this)
diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx
new file mode 100644
index 00000000..27e03cf6
--- /dev/null
+++ b/src/components/floor-plan/FloorPlan.jsx
@@ -0,0 +1,7 @@
+export default function FloorPlan() {
+ return (
+ <>
+
도면 작성 페이지
+ >
+ )
+}
diff --git a/src/components/ui/ObjectPlacement.jsx b/src/components/ui/ObjectPlacement.jsx
new file mode 100644
index 00000000..7bb10f14
--- /dev/null
+++ b/src/components/ui/ObjectPlacement.jsx
@@ -0,0 +1,155 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import { Button, Input } from '@nextui-org/react'
+import { useRecoilState, useSetRecoilState } from 'recoil'
+import { modalState } from '@/store/modalAtom'
+import { fabric } from 'fabric'
+import { QPolygon } from '@/components/fabric/QPolygon'
+import { modeState, objectPlacementModeState } from '@/store/canvasAtom'
+
+const BATCH_TYPE = {
+ OPENING: 'opening',
+ SHADOW: 'shadow',
+}
+
+const INPUT_TYPE = {
+ FREE: 'free',
+ DIMENSION: 'dimension',
+}
+
+const ObjectPlacement = ({ canvas }) => {
+ const [open, setOpen] = useRecoilState(modalState)
+ const [mode, setMode] = useRecoilState(modeState)
+ const [objectPlacementMode, setObjectPlacementModeState] = useRecoilState(objectPlacementModeState)
+ const [width, setWidth] = useState(0)
+ const [height, setHeight] = useState(0)
+ const [areaBoundary, setAreaBoundary] = useState(true)
+
+ // opening or shadow 개구 / 그림자
+ const [batchType, setBatchType] = useState(BATCH_TYPE.OPENING)
+
+ // free or dimension 프리 / 치수
+ const [inputType, setInputType] = useState(INPUT_TYPE.FREE)
+
+ const handleSave = () => {
+ setMode(batchType)
+ setOpen(false)
+ }
+
+ return (
+
+
+
+
+
+
+
개구 · 그림자 배치
+
+
+
+
+
+
+
+
+
+
+
설정
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default ObjectPlacement
diff --git a/src/components/ui/SurfaceShape.jsx b/src/components/ui/SurfaceShape.jsx
index b55db429..ac30138f 100644
--- a/src/components/ui/SurfaceShape.jsx
+++ b/src/components/ui/SurfaceShape.jsx
@@ -1,9 +1,11 @@
import { Button, Input } from '@nextui-org/react'
-import { useCallback, useEffect, useState } from 'react'
-import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
+import { useState } from 'react'
+import { useRecoilValue, useSetRecoilState } from 'recoil'
import { modalState } from '@/store/modalAtom'
import { QPolygon } from '@/components/fabric/QPolygon'
-import { fontSizeState } from '@/store/canvasAtom'
+import { fontSizeState, roofMaterialState } from '@/store/canvasAtom'
+import { degreesToRadians } from '@turf/turf'
+import { getIntersectionPoint } from '@/util/canvas-util'
/**
* 면형상 배치 모달
@@ -14,6 +16,8 @@ export const SurfaceShapeModal = ({ canvas }) => {
const [type, setType] = useState(0)
const setOpen = useSetRecoilState(modalState)
const fontSize = useRecoilValue(fontSizeState)
+ //지붕재
+ const roofMaterial = useRecoilValue(roofMaterialState)
/**
* 최대 5개의 length
@@ -24,6 +28,9 @@ export const SurfaceShapeModal = ({ canvas }) => {
const [length4, setLength4] = useState(0)
const [length5, setLength5] = useState(0)
+ // 방향
+ const [direction, setDirection] = useState('south')
+
/**
* 최대 5개의 length
*/
@@ -36,203 +43,585 @@ export const SurfaceShapeModal = ({ canvas }) => {
}
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: {
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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: {
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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: {
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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: {
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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: {
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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: {
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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: {
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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)
- canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'guideTriangle'))
- const pointer = canvas?.getPointer(e.e)
- obj = 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',
- },
- )
+ 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)
- const pointer = canvas?.getPointer(e.e)
- obj = new QPolygon(
+ 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: 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 },
+ { x: 0, y: length3 },
+ { x: length1 - length2, y: length3 },
+ { x: (length1 - length2) / 2, y: length3 - length3 },
],
{
fill: 'transparent',
- stroke: 'black',
+ stroke: 'black', //black
strokeWidth: 2,
selectable: true,
- fontSize: fontSize,
- name: 'guideTriangle',
+ 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) => {
@@ -242,138 +631,241 @@ export const SurfaceShapeModal = ({ canvas }) => {
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) => {
- const { name, value } = e.target
+ let { name, value } = e.target
+ value = value.replace(/[^-0-9]/g, '')
switch (name) {
case 'length1':
- setLength1(value)
+ setLength1(Number(value))
break
case 'length2':
- setLength2(value)
+ setLength2(Number(value))
break
case 'length3':
- setLength3(value)
+ setLength3(Number(value))
break
case 'length4':
- setLength4(value)
+ setLength4(Number(value))
break
case 'length5':
- setLength5(value)
+ 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(
+
,
+ )
+ }
+
+ return
{buttons}
+ }
+
return (
<>
면형상배치{type}
-
-
-
-
-
-
-
-
-
+
{type === 1 ? (
길이1
-
- 길이2
-
- 길이3
+
+ {length3 === 0 && (
+ <>
+ 길이2
+
+ >
+ )}
+ 대각선
- ) : type === 2 ? (
+ ) : [2, 4, 5].includes(type) ? (
길이1
-
+
길이2
-
+
- ) : type === 3 ? (
+ ) : [3, 6, 7, 8, 9, 24, 28, 29].includes(type) ? (
<>
길이1
-
+
길이2
-
+
길이3
-
+
>
- ) : type === 4 ? (
+ ) : [11, 12, 19, 20, 21, 22, 25, 26, 27].includes(type) ? (
<>
길이1
-
+
길이2
-
- >
- ) : type === 5 ? (
- <>
- 길이1
-
- 길이2
-
- >
- ) : type === 6 ? (
- <>
- 길이1
-
- 길이2
-
+
길이3
-
+
+ 길이4
+
>
- ) : type === 7 ? (
+ ) : [10, 13, 14, 15, 16, 17, 18, 23].includes(type) ? (
<>
길이1
-
+
길이2
-
+
길이3
-
- >
- ) : type === 8 ? (
- <>
- 길이1
-
- 길이2
-
- 길이3
-
- >
- ) : type === 9 ? (
- <>
- 길이1
-
- 길이2
-
- 길이3
-
+
+ 길이4
+
+ 길이5
+
>
) : (
<>>
)}
+
+
+
+
+
+
+
+
+
+
+
+