From d410a8cd890aa4fce0749b09f61d5a16648d977a Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 12 Aug 2024 15:10:35 +0900 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20axios=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=ED=8C=A8=ED=84=B4=20?= =?UTF-8?q?=EA=B0=84=EB=8B=A8=ED=95=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useAxios.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/hooks/useAxios.js b/src/hooks/useAxios.js index 9e188ba7..04f1f304 100644 --- a/src/hooks/useAxios.js +++ b/src/hooks/useAxios.js @@ -1,4 +1,4 @@ -import axios from 'axios' +import axios, { Axios } from 'axios' export const AxiosType = { INTERNAL: 'Internal', @@ -6,7 +6,10 @@ export const AxiosType = { } export function useAxios() { - const getInstances = (type) => { + const getInstances = (url) => { + let type = AxiosType.INTERNAL + url.startsWith('http') ? (type = AxiosType.EXTERNAL) : '' + return axios.create({ baseURL: type === AxiosType.INTERNAL ? process.env.NEXT_PUBLIC_API_SERVER_PATH : '', headers: { @@ -28,36 +31,36 @@ export function useAxios() { // } }) - const get = async ({ type, url }) => { - return await getInstances(type) + const get = async ({ url }) => { + return await getInstances(url) .get(url) .then((res) => res.data) .catch(console.error) } - const post = async ({ type, url, data }) => { - return await getInstances(type) + const post = async ({ url, data }) => { + return await getInstances(url) .post(url, data) .then((res) => res.data) .catch(console.error) } - const put = async ({ type, url, data }) => { - return await getInstances(type) + const put = async ({ url, data }) => { + return await getInstances(url) .put(url, data) .then((res) => res.data) .catch(console.error) } - const patch = async ({ type, url, data }) => { - return await getInstances(type) + const patch = async ({ url, data }) => { + return await getInstances(url) .patch(url, data) .then((res) => res.data) .catch(console.error) } - const del = async ({ type, url }) => { - return await getInstances(type) + const del = async ({ url }) => { + return await getInstances(url) .delete(url) .then((res) => res.data) .catch(console.error) From bb0849c2d044a4cd86dba7ccd3c0aedd8f4a43b0 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 12 Aug 2024 16:07:51 +0900 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20useAxios=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/[locale]/changelog/page.jsx | 3 +-- src/components/Intro.jsx | 2 +- src/hooks/useAxios.js | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/app/[locale]/changelog/page.jsx b/src/app/[locale]/changelog/page.jsx index dd7f623a..26cfc0a9 100644 --- a/src/app/[locale]/changelog/page.jsx +++ b/src/app/[locale]/changelog/page.jsx @@ -2,7 +2,7 @@ import { Button, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from '@nextui-org/react' -import { AxiosType, useAxios } from '@/hooks/useAxios' +import { useAxios } from '@/hooks/useAxios' // import { get } from '@/lib/Axios' import QSelect from '@/components/ui/QSelect' @@ -16,7 +16,6 @@ export default function changelogPage() { const handleUsers = async () => { // const users = await get('/api/user/find-all') const params = { - type: AxiosType.INTERNAL, url: '/api/user/find-all', } const users = await get(params) diff --git a/src/components/Intro.jsx b/src/components/Intro.jsx index 35b5b872..054edc53 100644 --- a/src/components/Intro.jsx +++ b/src/components/Intro.jsx @@ -72,7 +72,7 @@ export default function Intro() { async function fetchData() { // const response = await fetch('https://www.ag-grid.com/example-assets/space-mission-data.json') // const data = await response.json() - const data = await get({ type: AxiosType.EXTERNAL, url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' }) + const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' }) setGridProps({ ...gridProps, gridData: data }) } fetchData() diff --git a/src/hooks/useAxios.js b/src/hooks/useAxios.js index 04f1f304..3fa1f4f4 100644 --- a/src/hooks/useAxios.js +++ b/src/hooks/useAxios.js @@ -1,6 +1,6 @@ import axios, { Axios } from 'axios' -export const AxiosType = { +const AxiosType = { INTERNAL: 'Internal', EXTERNAL: 'External', } From 225cf3a5661cbbfd0e735204ddb4f83a1e6ec564 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 12 Aug 2024 16:19:49 +0900 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=BC=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B0=8F=20=EA=B5=AC=EC=A1=B0=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/[locale]/playground/page.jsx | 9 ++++++++ src/components/Headers.jsx | 2 +- src/components/Intro.jsx | 4 ++-- .../page.jsx => components/Playground.jsx} | 22 ++----------------- .../playground.module.css} | 0 5 files changed, 14 insertions(+), 23 deletions(-) create mode 100644 src/app/[locale]/playground/page.jsx rename src/{app/[locale]/changelog/page.jsx => components/Playground.jsx} (68%) rename src/{app/[locale]/changelog/changelog.module.css => components/playground.module.css} (100%) diff --git a/src/app/[locale]/playground/page.jsx b/src/app/[locale]/playground/page.jsx new file mode 100644 index 00000000..b8a7f496 --- /dev/null +++ b/src/app/[locale]/playground/page.jsx @@ -0,0 +1,9 @@ +import Playground from '@/components/Playground' + +export default function PlaygroundPage() { + return ( + <> + + + ) +} diff --git a/src/components/Headers.jsx b/src/components/Headers.jsx index a5503b8c..07caed71 100644 --- a/src/components/Headers.jsx +++ b/src/components/Headers.jsx @@ -9,7 +9,7 @@ export default function Headers() {
Intro - Changelog + Playground Roof Roof2
diff --git a/src/components/Intro.jsx b/src/components/Intro.jsx index 054edc53..0129e7a4 100644 --- a/src/components/Intro.jsx +++ b/src/components/Intro.jsx @@ -1,13 +1,13 @@ 'use client' -import { useEffect, useMemo, useState } from 'react' +import { useEffect, useState } from 'react' import Link from 'next/link' import { useRecoilState } from 'recoil' import { modalContent, modalState } from '@/store/modalAtom' -import { AxiosType, useAxios } from '@/hooks/useAxios' +import { useAxios } from '@/hooks/useAxios' import { Button } from '@nextui-org/react' diff --git a/src/app/[locale]/changelog/page.jsx b/src/components/Playground.jsx similarity index 68% rename from src/app/[locale]/changelog/page.jsx rename to src/components/Playground.jsx index 26cfc0a9..2467798a 100644 --- a/src/app/[locale]/changelog/page.jsx +++ b/src/components/Playground.jsx @@ -7,9 +7,9 @@ import { useAxios } from '@/hooks/useAxios' import QSelect from '@/components/ui/QSelect' -import styles from './changelog.module.css' +import styles from './playground.module.css' -export default function changelogPage() { +export default function Playground() { const { get } = useAxios() const testVar = process.env.NEXT_PUBLIC_TEST @@ -46,24 +46,6 @@ export default function changelogPage() { <>
이 영역은 테스트입니다.
-
- - - DATE - NAME - CONTENTS - - - {data.map((item) => ( - - {item.date} - {item.author} - {item.contents} - - ))} - -
-
diff --git a/src/app/[locale]/changelog/changelog.module.css b/src/components/playground.module.css similarity index 100% rename from src/app/[locale]/changelog/changelog.module.css rename to src/components/playground.module.css From 3d266b21d7fec8318f60d5d6761ed59d9f5facba Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 12 Aug 2024 17:42:55 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=EB=B3=B4=EC=A1=B0=EC=84=A0=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=EB=AA=A8=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 36 ++- src/hooks/useCanvas.js | 5 +- src/hooks/useMode.js | 550 +++++++++++++++++-------------------- src/util/common-utils.js | 11 + src/util/qpolygon-utils.js | 3 +- 5 files changed, 297 insertions(+), 308 deletions(-) create mode 100644 src/util/common-utils.js diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 20883410..68303710 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -4,13 +4,20 @@ import { Mode, useMode } from '@/hooks/useMode' import { Button } from '@nextui-org/react' import RangeSlider from './ui/RangeSlider' import { useRecoilState, useRecoilValue } from 'recoil' -import { canvasSizeState, fontSizeState, roofMaterialState, sortedPolygonArray, templateTypeState, compassState } from '@/store/canvasAtom' +import { + canvasSizeState, + compassState, + fontSizeState, + roofMaterialState, + roofState, + sortedPolygonArray, + templateTypeState, + wallState, +} from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' import { getCanvasState, insertCanvasState } from '@/lib/canvas' import { calculateIntersection } from '@/util/canvas-util' import { QPolygon } from '@/components/fabric/QPolygon' -import * as turf from '@turf/turf' -import { toGeoJSON } from '@/util/qpolygon-utils' export default function Roof2() { const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas') @@ -38,6 +45,10 @@ export default function Roof2() { const [compass, setCompass] = useRecoilState(compassState) + const roof = useRecoilValue(roofState) + + const wall = useRecoilValue(wallState) + const { mode, setMode, @@ -55,6 +66,8 @@ export default function Roof2() { createRoofRack, drawRoofPolygon, drawCellInTrestle, + setDirectionTrestles, + cutHelpLines, } = useMode() // const [canvasState, setCanvasState] = useRecoilState(canvasAtom) @@ -553,12 +566,19 @@ export default function Roof2() { - {/* + */} + @@ -614,6 +634,9 @@ export default function Roof2() { */} + {templateType === 1 && ( <> + diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 968f3676..27c80187 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from 'react' import { fabric } from 'fabric' -import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util' +import { actionHandler, anchorWrapper, calculateIntersection, distanceBetweenPoints, polygonPositionHandler } from '@/util/canvas-util' import { useRecoilState } from 'recoil' import { canvasSizeState, fontSizeState } from '@/store/canvasAtom' @@ -9,6 +9,8 @@ import { QPolygon } from '@/components/fabric/QPolygon' import { defineQLine } from '@/util/qline-utils' import { defineQPloygon } from '@/util/qpolygon-utils' +import * as turf from '@turf/turf' + export function useCanvas(id) { const [canvas, setCanvas] = useState() const [isLocked, setIsLocked] = useState(false) @@ -65,6 +67,7 @@ export function useCanvas(id) { initialize() canvas?.on('object:added', onChange) canvas?.on('object:added', addEventOnObject) + canvas?.on('object:modified', onChange) canvas?.on('object:removed', onChange) canvas?.on('mouse:move', drawMouseLines) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 9edd121c..968c76ca 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -1,5 +1,13 @@ import { useEffect, useRef, useState } from 'react' -import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util' +import { + calculateIntersection, + distanceBetweenPoints, + findTopTwoIndexesByDistance, + getCenterPoint, + getDirection, + getStartIndex, + rearrangeArray, +} from '@/util/canvas-util' import { useRecoilState, useRecoilValue } from 'recoil' import { @@ -18,6 +26,8 @@ import { QLine } from '@/components/fabric/QLine' import { fabric } from 'fabric' import { QPolygon } from '@/components/fabric/QPolygon' import offsetPolygon from '@/util/qpolygon-utils' +import { isObjectNotEmpty } from '@/util/common-utils' +import * as turf from '@turf/turf' export const Mode = { DRAW_LINE: 'drawLine', // 기준선 긋기모드` @@ -31,6 +41,7 @@ export const Mode = { ROOF_TRESTLE: 'roofTrestle', //지붕가대 모드 FILL_CELLS: 'fillCells', //태양광셀 모드 CELL_POWERCON: 'cellPowercon', //파워콘 + DRAW_HELP_LINE: 'drawHelpLine', // 보조선 그리기 모드 지붕 존재해야함 DEFAULT: 'default', } @@ -254,6 +265,14 @@ export function useMode() { case 'cellPowercon': makeCellPowercon() break + case 'drawHelpLine': + canvas?.off('selection:created', addSelectCreatedEvent) + canvas?.off('selection:cleared', addSelectClearedEvent) + canvas?.on('selection:created', addSelectCreatedEvent) + canvas?.on('selection:cleared', addSelectClearedEvent) + drawHelpLineMode() + break + case 'default': canvas?.off('mouse:down') break @@ -340,6 +359,81 @@ export function useMode() { canvas?.renderAll() } + const addSelectCreatedEvent = (e) => { + const target = e.selected[0] + + if (target.name === 'helpPoint') { + canvas?.on('mouse:move', helpPointEvent.mouseMove) + } + } + + const helpPointEvent = { + mouseMove: (e) => { + const target = canvas?.getActiveObject() + const pointer = canvas?.getPointer(e.e) + const point = { x: target.left + target.radius, y: target.top + target.radius } + const angle = Math.atan2(pointer.y - point.y, pointer.x - point.x) + const degree = fabric.util.radiansToDegrees(angle) + + const min = [0, 45, 90, -0, -90, -45, 135, -135, 180, -180].reduce((prev, curr) => { + return Math.abs(curr - degree) < Math.abs(prev - degree) ? curr : prev + }) + + // Calculate the center point of the target object + const centerX = target.left + target.width / 2 + const centerY = target.top + target.height / 2 + + const length = distanceBetweenPoints(point, { x: pointer.x, y: pointer.y }) + + // min의 각도와 pointer의 위치를 이용하여 새로운 점을 구한다. + const newPoint = { + x: centerX + length * Math.cos(fabric.util.degreesToRadians(min)), + y: centerY + length * Math.sin(fabric.util.degreesToRadians(min)), + } + + const line = new fabric.Line([point.x, point.y, newPoint.x, newPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'beforeHelpLine', + helpPoint: target, + }) + + const helpLines = canvas?._objects.filter((obj) => obj.name === 'beforeHelpLine') + helpLines.forEach((item) => canvas?.remove(item)) + + canvas?.add(line) + }, + } + + const addSelectClearedEvent = (e) => { + const target = e.deselected[0] + + if (target.name === 'helpPoint') { + const beforeHelpLines = canvas?._objects.filter((obj) => obj.name === 'beforeHelpLine' && obj.helpPoint === target) + + const helpLines = canvas?._objects.filter((obj) => obj.name === 'helpLine' && obj.helpPoint === target) + + beforeHelpLines.forEach((item) => canvas?.remove(item)) + helpLines.forEach((item) => canvas?.remove(item)) + + const newPoint = { x: beforeHelpLines[0].x2, y: beforeHelpLines[0].y2 } + + const helpLine = new fabric.Line([target.left + target.radius, target.top + target.radius, newPoint.x, newPoint.y], { + stroke: 'red', + strokeWidth: 1, + selectable: false, + name: 'helpLine', + helpPoint: target, + }) + + canvas?.add(helpLine) + canvas?.renderAll() + + canvas?.off('mouse:move', helpPointEvent.mouseMove) + } + } + const handleKeyDown = (e) => { switch (e.key) { case 'ArrowDown': { @@ -531,7 +625,7 @@ export function useMode() { // handleOuterlines() const wall = makePolygon(null, sort) wall.set({ name: 'wall' }) - setWall(wall) + console.log('wall', wall) return wall } @@ -695,6 +789,7 @@ export function useMode() { viewLengthText: true, fontSize: fontSize, sort: sort, + selectable: false, }, canvas, ) @@ -738,296 +833,6 @@ export function useMode() { setZoom(Math.ceil(zoom - 10)) } - const handleOuterlines = () => { - const newOuterlines = [] - for (let i = 0; i < historyLines.current.length; i++) { - const next = historyLines.current[i + 1] - const prev = historyLines.current[i - 1] ?? historyLines.current[historyLines.current.length - 1] - if (next) { - if (next.direction === 'right') { - // 다름 라인이 오른쪽으로 이동 - if (historyLines.current[i].direction === 'top') { - if (prev.direction !== 'right') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - // bottom - if (prev?.direction !== 'right') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } - } else if (next.direction === 'left') { - if (historyLines.current[i].direction === 'top') { - if (prev?.direction !== 'left') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - // bottom - if (prev?.direction !== 'left') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } - } else if (next.direction === 'top') { - if (historyLines.current[i].direction === 'right') { - if (prev?.direction !== 'top') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - // left - if (prev?.direction !== 'top') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } - } else if (next.direction === 'bottom') { - if (historyLines.current[i].direction === 'right') { - if (prev?.direction !== 'bottom') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - // left - if (prev.direction !== 'bottom') { - if (historyLines.current.length === 4) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 6) { - newOuterlines.push({ - x1: historyLines.current[i].x1 + 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 - 50, - y2: historyLines.current[i].y2 - 50, - }) - } else if (historyLines.current.length === 8) { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 + 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 + 50, - }) - } - } else { - newOuterlines.push({ - x1: historyLines.current[i].x1 - 50, - y1: historyLines.current[i].y1 - 50, - x2: historyLines.current[i].x2 + 50, - y2: historyLines.current[i].y2 - 50, - }) - } - } - } - } else { - const tmp = newOuterlines[newOuterlines.length - 1] - newOuterlines.push({ - x1: tmp.x2, - y1: tmp.y2, - x2: newOuterlines[0].x1, - y2: newOuterlines[0].y1, - }) - } - } - - makePolygon(newOuterlines) - } - /** *벽 지붕 외곽선 생성 */ @@ -1115,9 +920,10 @@ export function useMode() { ) roof.setWall(polygon) setRoof(roof) + setWall(polygon) - roof.drawHelpLine() - roof.divideLine() + // roof.drawHelpLine() + // roof.divideLine() } const drawRoofPolygon = (wall, offset = 50) => { @@ -4465,6 +4271,7 @@ export function useMode() { } const createRoofRack = () => { + roof.divideLine() const trestlePolygons = canvas?.getObjects().filter((obj) => obj.name === 'trestle') // 이미 만들어진 가대가 있을 경우 return if (trestlePolygons.length !== 0) { @@ -4475,7 +4282,6 @@ export function useMode() { canvas?.off('mouse:out') document.removeEventListener('keydown', handleKeyDown) const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof') - let roofCells = [] // roof에 적재된 cell들 roofs.forEach((roof, index) => { const offsetPolygonPoint = offsetPolygon(roof.points, -20) @@ -4498,8 +4304,6 @@ export function useMode() { canvas?.add(trestlePoly) }) - - setDrewRoofCells(roofCells) } //배터리 셀 넣기 @@ -4531,19 +4335,24 @@ export function useMode() { let drawRoofCells if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') { - drawRoofCells = trestle.fillCell({ width: 50, height: 100, padding: 0 }) + drawRoofCells = trestle.fillCell({ width: 50, height: 100, padding: 10 }) trestle.direction = 'south' } else { - drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 0 }) + drawRoofCells = trestle.fillCell({ width: 100, height: 50, padding: 10 }) trestle.direction = 'east' } drawRoofCells.forEach((cell) => { - roofCells.push(cell) + drawCellsArray.push(cell) }) }) - setDrewRoofCells(roofCells) + setDrewRoofCells(drawCellsArray) + } + + // 가대 방위 설정 + const setDirectionTrestles = () => { + console.log('roof', roof) } const makeCellPowercon = () => { @@ -4610,6 +4419,143 @@ export function useMode() { return { concaveIndices: concaveIndices, concavePointIndices: concavePointIndices } } + const drawHelpLineMode = () => { + if (!isObjectNotEmpty(roof)) { + alert('지붕을 먼저 그려주세요.') + setMode(Mode.DEFAULT) + return + } + + const roofPoints = roof.points + const wallPoints = wall.points + + roofPoints.forEach((roofPoint, index) => { + const circle = new fabric.Circle({ + radius: 5, + fill: 'red', + left: roofPoint.x - 5, + top: roofPoint.y - 5, + selectable: true, // 선택 가능하게 설정 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 + name: 'helpPoint', + }) + + canvas?.add(circle) + canvas?.renderAll() + }) + } + + const cutHelpLines = () => { + // 먼저 hip을 자른다. + canvas + ?.getObjects() + .filter((obj) => obj.name === 'helpLine') + .forEach((line, index1) => { + canvas + ?.getObjects() + .filter((obj) => obj.name === 'helpLine') + .forEach((line2, index2) => { + if (line === line2) { + return + } + + const intersectionPoint = calculateIntersection(line, line2) + if (!intersectionPoint) { + return + } + + canvas?.remove(line) + canvas?.remove(line2) + + const hip1 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'hip', + }) + + const hip2 = new QLine([line2.x1, line2.y1, intersectionPoint.x, intersectionPoint.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'hip', + }) + + const interSectionCircle = new fabric.Circle({ + radius: 5, + fill: 'red', + left: intersectionPoint.x - 5, + top: intersectionPoint.y - 5, + selectable: true, // 선택 가능하게 설정 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 + name: 'helpPoint', + }) + + canvas?.add(hip1) + canvas?.add(hip2) + roof.innerLines.push(hip1) + roof.innerLines.push(hip2) + canvas?.add(interSectionCircle) + canvas?.renderAll() + }) + }) + + canvas + ?.getObjects() + .filter((obj) => obj.name === 'helpLine') + .forEach((line) => { + const helpPoints = canvas?.getObjects().filter((obj) => obj.name === 'helpPoint') + let cnt = 0 + let intersectionPoints = [] + helpPoints.forEach((point) => { + if (cnt === 2) { + return + } + if ( + turf.booleanPointOnLine( + turf.point([point.left + point.radius, point.top + point.radius]), + turf.lineString([ + [line.x1, line.y1], + [line.x2, line.y2], + ]), + ) + ) { + intersectionPoints.push(point) + cnt++ + } + }) + + if (intersectionPoints.length === 2) { + const ridge = new QLine( + [ + intersectionPoints[0].left + intersectionPoints[0].radius, + intersectionPoints[0].top + intersectionPoints[0].radius, + intersectionPoints[1].left + intersectionPoints[1].radius, + intersectionPoints[1].top + intersectionPoints[1].radius, + ], + { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'ridge', + }, + ) + roof.innerLines.push(ridge) + canvas?.add(ridge) + canvas?.remove(line) + canvas?.renderAll() + } + }) + } + return { mode, setMode, @@ -4627,5 +4573,7 @@ export function useMode() { createRoofRack, drawRoofPolygon, drawCellInTrestle, + setDirectionTrestles, + cutHelpLines, } } diff --git a/src/util/common-utils.js b/src/util/common-utils.js new file mode 100644 index 00000000..9f53fede --- /dev/null +++ b/src/util/common-utils.js @@ -0,0 +1,11 @@ +/** + * Check if an object is not empty. + * @param {Object} obj - The object to check. + * @returns {boolean} - Returns true if the object is not empty, false otherwise. + */ +export const isObjectNotEmpty = (obj) => { + if (!obj) { + return false + } + return Object.keys(obj).length > 0 +} diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 5a216524..77af0df5 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1127,7 +1127,7 @@ export const splitPolygonWithLines = (polygon) => { }) }) - roofs.forEach((roofPoint) => { + roofs.forEach((roofPoint, index) => { const roof = new QPolygon(roofPoint, { fontSize: polygon.fontSize, stroke: 'black', @@ -1135,6 +1135,7 @@ export const splitPolygonWithLines = (polygon) => { strokeWidth: 3, name: 'roof', selectable: false, + startDirection: polygon.lines[index].direction, }) polygon.canvas.add(roof) From 7578965300912259b4ccee1cd1e4f5245143598e Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 13 Aug 2024 10:56:41 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EB=B0=A9=EC=9C=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useCanvas.js | 4 ++++ src/hooks/useMode.js | 15 +++++++++++++++ src/util/qpolygon-utils.js | 20 +++++++++++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 27c80187..4f5035bc 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -113,6 +113,10 @@ export function useCanvas(id) { if (target.name === 'trestle') { target.on('mousedown', () => { + if (target.defense === 'north') { + alert('북쪽은 선택 불가합니다.') + return + } if (target.get('selected')) { target.set({ strokeWidth: 1 }) target.set({ strokeDashArray: [5, 5] }) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 968c76ca..1782dde8 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4293,6 +4293,7 @@ export function useMode() { selectable: false, fontSize: fontSize, name: 'trestle', + defense: roof.defense, lockMovementX: true, // X 축 이동 잠금 lockMovementY: true, // Y 축 이동 잠금 lockRotation: true, // 회전 잠금 @@ -4304,6 +4305,7 @@ export function useMode() { canvas?.add(trestlePoly) }) + removeHelpPointAndHelpLine() } //배터리 셀 넣기 @@ -4556,6 +4558,19 @@ export function useMode() { }) } + const removeHelpPointAndHelpLine = () => { + const helpPoints = canvas?.getObjects().filter((obj) => obj.name === 'helpPoint') + helpPoints.forEach((point) => { + canvas?.remove(point) + }) + + const helpLines = canvas?.getObjects().filter((obj) => obj.name === 'helpLine') + helpLines.forEach((line) => { + canvas?.remove(line) + }) + canvas?.renderAll() + } + return { mode, setMode, diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 77af0df5..527aee8d 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1128,6 +1128,24 @@ export const splitPolygonWithLines = (polygon) => { }) roofs.forEach((roofPoint, index) => { + let defense + const direction = getDirectionByPoint(roofPoint[0], roofPoint[roofPoint.length - 1]) + + switch (direction) { + case 'top': + defense = 'east' + break + case 'right': + defense = 'south' + break + case 'bottom': + defense = 'west' + break + case 'left': + defense = 'north' + break + } + const roof = new QPolygon(roofPoint, { fontSize: polygon.fontSize, stroke: 'black', @@ -1135,7 +1153,7 @@ export const splitPolygonWithLines = (polygon) => { strokeWidth: 3, name: 'roof', selectable: false, - startDirection: polygon.lines[index].direction, + defense: defense, }) polygon.canvas.add(roof) From 09cfbab00947a1768cf8fd61d4e184ec17428a16 Mon Sep 17 00:00:00 2001 From: nalpari Date: Tue, 13 Aug 2024 13:50:49 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=20=EC=A2=85=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/[locale]/community/archive/page.jsx | 6 ++---- src/app/[locale]/community/faq/page.jsx | 6 ++---- src/app/[locale]/community/notice/page.jsx | 6 ++---- src/app/[locale]/management/plan/page.jsx | 6 ++---- src/app/[locale]/management/stuff/page.jsx | 4 +--- src/app/[locale]/master/company/page.jsx | 6 ++---- src/app/[locale]/master/price/page.jsx | 2 -- src/app/[locale]/roof/page.jsx | 2 -- 8 files changed, 11 insertions(+), 27 deletions(-) diff --git a/src/app/[locale]/community/archive/page.jsx b/src/app/[locale]/community/archive/page.jsx index 06971385..4c0cbdb0 100644 --- a/src/app/[locale]/community/archive/page.jsx +++ b/src/app/[locale]/community/archive/page.jsx @@ -1,14 +1,12 @@ -'use client' - import Hero from '@/components/Hero' import Archive from '@/components/community/Archive' export default function CommunityArchivePage() { return ( <> - +
- +
) diff --git a/src/app/[locale]/community/faq/page.jsx b/src/app/[locale]/community/faq/page.jsx index 63992da8..3f764566 100644 --- a/src/app/[locale]/community/faq/page.jsx +++ b/src/app/[locale]/community/faq/page.jsx @@ -1,14 +1,12 @@ -'use client' - import Hero from '@/components/Hero' import Faq from '@/components/community/Faq' export default function CommunityFaqPage() { return ( <> - +
- +
) diff --git a/src/app/[locale]/community/notice/page.jsx b/src/app/[locale]/community/notice/page.jsx index 5c5d0559..5372112e 100644 --- a/src/app/[locale]/community/notice/page.jsx +++ b/src/app/[locale]/community/notice/page.jsx @@ -1,14 +1,12 @@ -'use client' - import Hero from '@/components/Hero' import Notice from '@/components/community/Notice' export default function CommunityNoticePage() { return ( <> - +
- +
) diff --git a/src/app/[locale]/management/plan/page.jsx b/src/app/[locale]/management/plan/page.jsx index 45afb7fa..61937238 100644 --- a/src/app/[locale]/management/plan/page.jsx +++ b/src/app/[locale]/management/plan/page.jsx @@ -1,14 +1,12 @@ -'use client' - import Hero from '@/components/Hero' import Plan from '@/components/management/Plan' export default function ManagementPlanPage() { return ( <> - +
- +
) diff --git a/src/app/[locale]/management/stuff/page.jsx b/src/app/[locale]/management/stuff/page.jsx index a548be92..15131ba6 100644 --- a/src/app/[locale]/management/stuff/page.jsx +++ b/src/app/[locale]/management/stuff/page.jsx @@ -1,5 +1,3 @@ -'use client' - import Hero from '@/components/Hero' import Stuff from '@/components/management/Stuff' @@ -8,7 +6,7 @@ export default function ManagementStuffPage() { <>
- +
) diff --git a/src/app/[locale]/master/company/page.jsx b/src/app/[locale]/master/company/page.jsx index 18be29e2..6ee60f0e 100644 --- a/src/app/[locale]/master/company/page.jsx +++ b/src/app/[locale]/master/company/page.jsx @@ -1,14 +1,12 @@ -'use client' - import Hero from '@/components/Hero' import Company from '@/components/master/Company' export default function MasterCompanyPage() { return ( <> - +
- +
) diff --git a/src/app/[locale]/master/price/page.jsx b/src/app/[locale]/master/price/page.jsx index e60210fb..c0e5a40d 100644 --- a/src/app/[locale]/master/price/page.jsx +++ b/src/app/[locale]/master/price/page.jsx @@ -1,5 +1,3 @@ -'use client' - import Hero from '@/components/Hero' import Price from '@/components/master/Price' diff --git a/src/app/[locale]/roof/page.jsx b/src/app/[locale]/roof/page.jsx index 756199c3..4d9703f3 100644 --- a/src/app/[locale]/roof/page.jsx +++ b/src/app/[locale]/roof/page.jsx @@ -1,5 +1,3 @@ -'use client' - import Hero from '@/components/Hero' import Roof from '@/components/Roof'