From 6ecfab24729434d8bd9cb42c8b0b05620c6421f4 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 26 Jul 2024 13:42:13 +0900 Subject: [PATCH 1/7] =?UTF-8?q?import=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 8 ++++---- src/components/fabric/QLine.js | 2 +- src/util/qpolygon-utils.js | 36 +++++++++++++++++++++------------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 370a1e2e..f8546298 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -6,10 +6,10 @@ import QRect from '@/components/fabric/QRect' import QPolygon from '@/components/fabric/QPolygon' import RangeSlider from './ui/RangeSlider' -import { useRecoilState, useRecoilValue } from 'recoil' -import { canvasAtom, canvasListState, canvasSizeState, fontSizeState, sortedPolygonArray } from '@/store/canvasAtom' +import { useRecoilState } from 'recoil' +import { canvasSizeState, fontSizeState, sortedPolygonArray } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' -import { getTests, getCanvasState, insertCanvasState } from '@/lib/canvas' +import { getCanvasState, insertCanvasState } from '@/lib/canvas' import { calculateIntersection2 } from '@/util/canvas-util' export default function Roof2() { @@ -208,7 +208,7 @@ export default function Roof2() { ] if (canvas) { - const polygon = new QPolygon(type1, { + const polygon = new QPolygon(eightPoint, { fill: 'transparent', stroke: 'black', strokeWidth: 1, diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 9c8c2133..3924558c 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -1,5 +1,5 @@ import { fabric } from 'fabric' -import { getDirection, getDirectionByPoint } from '@/util/canvas-util' +import { getDirectionByPoint } from '@/util/canvas-util' export class QLine extends fabric.Group { line diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index bd5676bd..8ac0e078 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1,19 +1,7 @@ import { fabric } from 'fabric' import QPolygon from '@/components/fabric/QPolygon' import { QLine } from '@/components/fabric/QLine' -import { - calculateDistance, - calculateIntersection, - calculateIntersection2, - distanceBetweenPoints, - findClosestLineToPoint, - findClosestPoint, - findClosestPointWithDifferentXY, - findIntersection1, - getRoofHypotenuse, - removeDuplicatePoints, -} from '@/util/canvas-util' -import { help } from 'mathjs' +import { calculateIntersection2, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' export const defineQPloygon = () => { fabric.QPolygon = fabric.util.createClass(fabric.Group, {}) @@ -58,7 +46,9 @@ export const drawHelpLineInHexagon = (polygon, chon) => { const angle1 = Math.atan2(wallLine.y1 - line.y1, wallLine.x1 - line.x1) const angle2 = Math.atan2(wallLine.y2 - line.y2, wallLine.x2 - line.x2) - const helpLineLength = Math.min(line.length) + // line을 이등변 삼각형의 밑변으로 보고 높이를 구한다. + + const helpLineLength = Math.sqrt(Math.pow(line.length, 2) - Math.pow(line.length / 2, 2)) - 50 const firstX2 = Math.floor(line.x1 + helpLineLength * Math.cos(angle1)) const firstY2 = Math.floor(line.y1 + helpLineLength * Math.sin(angle1)) @@ -142,6 +132,7 @@ export const drawHelpLineInHexagon = (polygon, chon) => { helpLines = helpLines.filter((line) => line.relatedPoints?.length > 0) ridgeStartPoints.forEach((point) => { + point.alreadyIntersected = false // x 혹은 y가 같으면서 가장 가까운 점을 찾는다. let arrivalPoint let hipLine @@ -183,6 +174,8 @@ export const drawHelpLineInHexagon = (polygon, chon) => { polygon.canvas.renderAll() ridgeEndPoints.push(arrivalPoint) + + point.alreadyIntersected = true } }) @@ -241,6 +234,21 @@ export const drawHelpLineInHexagon = (polygon, chon) => { polygon.canvas.add(line) polygon.canvas.renderAll() } + + const notIntersectedRidgeStartPoints = ridgeStartPoints.filter((point) => !point.alreadyIntersected) + // 만나지 않은 마루 시작점 + while (notIntersectedRidgeStartPoints.length > 0) { + const point = notIntersectedRidgeStartPoints.shift() + const closestPoint = findClosestPoint(point, notIntersectedRidgeStartPoints) + if (!closestPoint) continue + const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], { + stroke: 'purple', + fontSize: polygon.fontSize, + }) + + polygon.canvas.add(line) + polygon.canvas.renderAll() + } } export const drawCenterLines = (polygon) => { From 58820d2bf20aa83a62c0e36f039036d70e09c6a2 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 26 Jul 2024 13:53:17 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=ED=8C=94=EA=B0=81=ED=98=95=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=8B=9C=EC=9E=91?= =?UTF-8?q?=EC=A0=90=20=ED=81=B0=20=EB=B9=A8=EA=B0=84=20=EC=9B=90=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 24 +++++++++++++++++++++++- src/hooks/useCanvas.js | 19 ++++--------------- src/hooks/useMode.js | 8 ++++---- src/util/qpolygon-utils.js | 2 +- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index f8546298..27aef946 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -207,8 +207,30 @@ export default function Roof2() { { x: 897, y: 215 }, ] + const eightPoint3 = [ + { x: 190, y: 147 }, + { x: 190, y: 747 }, + { x: 490, y: 747 }, + { x: 490, y: 497 }, + { x: 640, y: 497 }, + { x: 640, y: 747 }, + { x: 1090, y: 747 }, + { x: 1090, y: 147 }, + ] + + const eightPoint4 = [ + { x: 228, y: 92 }, + { x: 228, y: 592 }, + { x: 478, y: 592 }, + { x: 478, y: 342 }, + { x: 728, y: 342 }, + { x: 728, y: 592 }, + { x: 1078, y: 592 }, + { x: 1078, y: 92 }, + ] + if (canvas) { - const polygon = new QPolygon(eightPoint, { + const polygon = new QPolygon(eightPoint4, { fill: 'transparent', stroke: 'black', strokeWidth: 1, diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 44ed17ce..fb4bd571 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -7,6 +7,8 @@ import { canvasSizeState, fontSizeState } from '@/store/canvasAtom' import QPolygon from '@/components/fabric/QPolygon' import { QLine } from '@/components/fabric/QLine' import QRect from '@/components/fabric/QRect' +import { defineQPloygon } from '@/util/qpolygon-utils' +import { defineQLine } from '@/util/qline-utils' export function useCanvas(id) { const [canvas, setCanvas] = useState() @@ -118,21 +120,8 @@ export function useCanvas(id) { fabric.QLine = fabric.util.createClass(fabric.Group, {}) fabric.QPolygon = fabric.util.createClass(fabric.Group, {}) - // fromObject 메서드를 QLine 클래스에 직접 추가 - fabric.QLine.fromObject = function (object, callback) { - const { initOption, initPoints, initLengthTxt } = object - fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) { - return callback(new QLine(initPoints, initOption, initLengthTxt)) - }) - } - - // fromObject 메서드를 QLine 클래스에 직접 추가 - fabric.QPolygon.fromObject = function (object, callback) { - const { initOption, initPoints, initLengthTxt } = object - fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) { - return callback(new QPolygon(initPoints, initOption, initLengthTxt)) - }) - } + defineQPloygon() + defineQLine() } /** diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 18a7a574..3b36974f 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -329,11 +329,11 @@ export function useMode() { canvas?.on('mouse:down', function (options) { const pointer = canvas?.getPointer(options.e) const circle = new fabric.Circle({ - radius: 1, + radius: 5, fill: 'transparent', // 원 안을 비웁니다. - stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다. - left: pointer.x, - top: pointer.y, + stroke: 'red', // 원 테두리 색상을 검은색으로 설정합니다. + left: pointer.x - 5, + top: pointer.y - 5, originX: 'center', originY: 'center', selectable: false, diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 8ac0e078..982fa111 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -48,7 +48,7 @@ export const drawHelpLineInHexagon = (polygon, chon) => { // line을 이등변 삼각형의 밑변으로 보고 높이를 구한다. - const helpLineLength = Math.sqrt(Math.pow(line.length, 2) - Math.pow(line.length / 2, 2)) - 50 + const helpLineLength = Math.sqrt(Math.pow(line.length, 2) - Math.pow(line.length / 2, 2)) - 10 const firstX2 = Math.floor(line.x1 + helpLineLength * Math.cos(angle1)) const firstY2 = Math.floor(line.y1 + helpLineLength * Math.sin(angle1)) From 11fec70ac2d64273c83242d654abe5dd6c05e386 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 26 Jul 2024 15:40:55 +0900 Subject: [PATCH 3/7] =?UTF-8?q?guideLine=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 114 ++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 3b36974f..249984c7 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -25,6 +25,7 @@ export function useMode() { const points = useRef([]) const historyPoints = useRef([]) const historyLines = useRef([]) + const startPoint = useRef() const [canvas, setCanvas] = useState(null) const [zoom, setZoom] = useState(100) const [fontSize] = useRecoilState(fontSizeState) @@ -35,6 +36,8 @@ export function useMode() { const [endPoint, setEndPoint] = useState(null) + const pointCount = useRef(0) + const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState) const [canvasSize] = useRecoilState(canvasSizeState) @@ -102,6 +105,62 @@ export function useMode() { canvas?.renderAll() } + useEffect(() => { + if (pointCount.current <= 2) { + removeGuideLines() + return + } + drawGuideLines() + }, [pointCount.current]) + + const removeGuideLines = () => { + const guideLines = canvas?._objects.filter((obj) => obj.name === 'guideLine') + guideLines?.forEach((item) => canvas?.remove(item)) + } + + const drawGuideLines = () => { + // 이름이 guideLine인 가이드라인을 제거합니다. + removeGuideLines() + + const arrivalX = startPoint.current?.left + const arrivalY = startPoint.current?.top + + const lastX = endPoint?.left + const lastY = endPoint?.top + + if (lastX === arrivalX || lastY === arrivalY) { + // 둘중 하나라도 같으면 guideLine은 한개만 생성 + const guideLine = new QLine([lastX, lastY, arrivalX, arrivalY], { + fontSize: fontSize, + stroke: 'black', + strokeWidth: 1, + strokeDashArray: [1, 1, 1], + }) + guideLine.name = 'guideLine' + canvas?.add(guideLine) + } else { + const guideLine1 = new QLine([lastX, lastY, lastX, arrivalY], { + fontSize: fontSize, + stroke: 'black', + strokeWidth: 1, + strokeDashArray: [1, 1, 1], + }) + + const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, arrivalX, arrivalY], { + fontSize: fontSize, + stroke: 'black', + strokeWidth: 1, + strokeDashArray: [1, 1, 1], + }) + + guideLine1.name = 'guideLine' + guideLine2.name = 'guideLine' + + canvas?.add(guideLine1) + canvas?.add(guideLine2) + } + } + /** * 마우스 포인터의 가이드라인을 제거합니다. */ @@ -125,12 +184,10 @@ export function useMode() { const pointer = canvas?.getPointer(e.e) // 마우스 포인터 위치랑 endPoint를 연결하는 line 생성 - const line = new QLine([endPoint.left, endPoint.top, pointer.x, pointer.y], { + const line = new fabric.Line([endPoint.left, endPoint.top, pointer.x, pointer.y], { stroke: 'black', - strokeWidth: 2, + strokeWidth: 1, selectable: false, - viewLengthText: true, - fontSize: fontSize, }) line.set({ name: 'connectLine' }) @@ -235,8 +292,6 @@ export function useMode() { selectable: false, }) - setEndPoint(endPointCircle) - canvas?.add(endPointCircle) historyPoints.current.push(endPointCircle) @@ -244,6 +299,10 @@ export function useMode() { points.current.forEach((point) => { canvas?.remove(point) }) + + setEndPoint(endPointCircle) + pointCount.current = pointCount.current + 1 + points.current = [endPointCircle] canvas.renderAll() @@ -317,6 +376,8 @@ export function useMode() { const changeMode = (canvas, mode) => { setEndPoint(null) + pointCount.current = 0 + setMode(mode) // mode변경 시 이전 이벤트 제거 setCanvas(canvas) @@ -338,6 +399,10 @@ export function useMode() { originY: 'center', selectable: false, }) + if (!startPoint.current) { + startPoint.current = circle + pointCount.current = pointCount.current + 1 + } setEndPoint(circle) @@ -347,6 +412,7 @@ export function useMode() { if (points.current.length === 2) { const length = Number(prompt('길이를 입력하세요:')) + // length 값이 숫자가 아닌 경우 if (isNaN(length) || length === 0) { //마지막 추가 된 points 제거합니다. @@ -382,40 +448,10 @@ export function useMode() { } } - const line = new QLine( - [points.current[0].left, points.current[0].top, points.current[0].left + scaledVector.x, points.current[0].top + scaledVector.y], - { - stroke: 'black', - strokeWidth: 2, - selectable: false, - viewLengthText: true, - direction: getDirection(points.current[0], points.current[1]), - fontSize: fontSize, - }, - ) + const verticalLength = scaledVector.y + const horizontalLength = scaledVector.x - pushHistoryLine(line) - - // 라인의 끝에 점을 추가합니다. - const endPointCircle = new fabric.Circle({ - radius: 1, - fill: 'transparent', // 원 안을 비웁니다. - stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다. - left: points.current[0].left + scaledVector.x, - top: points.current[0].top + scaledVector.y, - originX: 'center', - originY: 'center', - selectable: false, - }) - setEndPoint(endPointCircle) - canvas?.add(endPointCircle) - - historyPoints.current.push(endPointCircle) - - points.current.forEach((point) => { - canvas?.remove(point) - }) - points.current = [endPointCircle] + drawCircleAndLine(verticalLength, horizontalLength) } } From aaeccdb6dd27bef817599b77991e4ee4c39eb83d Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 26 Jul 2024 17:11:01 +0900 Subject: [PATCH 4/7] =?UTF-8?q?clear=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 249984c7..8261fa31 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -703,6 +703,8 @@ export function useMode() { */ const handleClear = () => { canvas?.clear() + startPoint.current = null + setEndPoint(null) points.current = [] historyPoints.current = [] historyLines.current = [] From 94f1b9b28a008aa2c37680c2033de62babc04aa9 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 26 Jul 2024 18:29:21 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=EC=A7=80=EB=B6=95=20=EC=84=A0=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EA=B8=B0=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Roof2.jsx | 2 +- src/util/qpolygon-utils.js | 80 ++++++++++++++++++++++++++++---------- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 27aef946..ecd83b02 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -230,7 +230,7 @@ export default function Roof2() { ] if (canvas) { - const polygon = new QPolygon(eightPoint4, { + const polygon = new QPolygon(type1, { fill: 'transparent', stroke: 'black', strokeWidth: 1, diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 982fa111..b50cd4b9 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -48,7 +48,7 @@ export const drawHelpLineInHexagon = (polygon, chon) => { // line을 이등변 삼각형의 밑변으로 보고 높이를 구한다. - const helpLineLength = Math.sqrt(Math.pow(line.length, 2) - Math.pow(line.length / 2, 2)) - 10 + const helpLineLength = Math.sqrt(2 * Math.pow(line.length / 2, 2)) const firstX2 = Math.floor(line.x1 + helpLineLength * Math.cos(angle1)) const firstY2 = Math.floor(line.y1 + helpLineLength * Math.sin(angle1)) @@ -182,18 +182,61 @@ export const drawHelpLineInHexagon = (polygon, chon) => { /** * 안쓰는 점 제거 */ - centerInterSectionPoints.forEach((point) => { - ridgeEndPoints.forEach((endPoint) => { - if (!(Math.abs(point.x - endPoint.x) < 2 && Math.abs(point.y - endPoint.y) < 2)) { - centerInterSectionPoints.splice(centerInterSectionPoints.indexOf(point), 1) + + const ridgeEndRemainingPoints = [...ridgeEndPoints] + + const uniqueInterSectionPoints = Array.from(new Set(centerInterSectionPoints.map((point) => `${point.x},${point.y}`))).map((key) => { + const [x, y] = key.split(',').map(Number) + return { x, y } + }) + + while (ridgeEndRemainingPoints.length > 0) { + const point = ridgeEndRemainingPoints.shift() + let isExist = false + uniqueInterSectionPoints.forEach((uniquePoint) => { + const degree = calculateAngle(point, uniquePoint) + + if (Math.abs(45 - Math.abs(degree)) <= 5 || Math.abs(135 - Math.abs(degree)) <= 5) { + const line = new QLine([point.x, point.y, uniquePoint.x, uniquePoint.y], { + stroke: 'purple', + fontSize: polygon.fontSize, + }) + + ridgeEndPoints.push(uniquePoint) + + ridgeEndPoints.splice(ridgeEndPoints.indexOf(point), 1) + + isExist = true + + polygon.canvas.add(line) + polygon.canvas.renderAll() + } + + if (isExist) { + return } }) - }) + } + + const ridgeEndRemainingPoints2 = [...ridgeEndPoints] + + while (ridgeEndRemainingPoints2.length > 0) { + // 남아있는 점끼리 연결한다. + const point = ridgeEndRemainingPoints2.shift() + const closestPoint = findClosestPoint(point, ridgeEndRemainingPoints2) + if (!closestPoint) continue + const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], { + stroke: 'purple', + fontSize: polygon.fontSize, + }) + + polygon.canvas.add(line) + polygon.canvas.renderAll() + } // ridgeEndPoints와 가까운 centerInterSectionPoints를 찾아서 연결한다. const remainingPoints = centerInterSectionPoints - const ridgeEndRemainingPoints = ridgeEndPoints - + /* helpLines.forEach((line) => { remainingPoints.forEach((point) => { if (line.relatedPoints.includes(point)) { @@ -208,18 +251,7 @@ export const drawHelpLineInHexagon = (polygon, chon) => { }) }) - while (ridgeEndRemainingPoints.length > 0) { - const point = ridgeEndRemainingPoints.shift() - const closestPoint = findClosestPoint(point, remainingPoints) - if (!closestPoint) continue - const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], { - stroke: 'green', - fontSize: polygon.fontSize, - }) - polygon.canvas.add(line) - polygon.canvas.renderAll() - } // centerInterSectionPoints에 남아있는 점들을 가까운 점끼리 연결한다. while (remainingPoints.length > 0) { @@ -248,9 +280,11 @@ export const drawHelpLineInHexagon = (polygon, chon) => { polygon.canvas.add(line) polygon.canvas.renderAll() - } + }*/ } +export const drawHelpLineInHexagon2 = (polygon, chon) => {} + export const drawCenterLines = (polygon) => { const centerLines = [] @@ -342,3 +376,9 @@ const getOneSideLines = (polygon) => { return line }) } +const calculateAngle = (point1, point2) => { + const deltaX = point2.x - point1.x + const deltaY = point2.y - point1.y + const angleInRadians = Math.atan2(deltaY, deltaX) + return angleInRadians * (180 / Math.PI) +} From d88fb8f38934c2c05ddb463fec7c47e3c9ceacba Mon Sep 17 00:00:00 2001 From: yjnoh Date: Fri, 26 Jul 2024 18:29:33 +0900 Subject: [PATCH 6/7] =?UTF-8?q?8=EA=B0=81=20=EA=B0=80=EB=A1=9C=20=EC=9E=91?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 443 +++++++++++++++++++++++++++++++++---------- 1 file changed, 348 insertions(+), 95 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 249984c7..e691ef71 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -2015,16 +2015,15 @@ export function useMode() { } } - roofPatternPolygonArray.push(bigRoofPolygon) - roofPatternPolygonArray.push(middleRoofPolygon) - roofPatternPolygonArray.push(smallRoofPolygon) - - setRoofPolygonPattern({ roofPatternPolygonArray, lines }) + roofPatternPolygonArray.push(bigRoofPolygon) //지붕폴리곤 + roofPatternPolygonArray.push(middleRoofPolygon) //중간라인 폴리곤 + roofPatternPolygonArray.push(smallRoofPolygon) //작은지붕폴리곤 + setRoofPolygonPattern({ roofPatternPolygonArray, lines }) //모든 행을 저장 canvas.renderAll() } - const handleOuterLineTemplateA8Points = (polygon, offsetInputX = 50, offsetInputY = 20) => { + const handleOuterLineTemplateA8Points = (polygon, offsetInputX = 20, offsetInputY = 50) => { let offsetPoints = [] const originalMax = 71 @@ -2038,15 +2037,15 @@ export function useMode() { const dashedCenterLineOpt = { stroke: 'black', - strokeWidth: 4, + strokeWidth: 1, property: 'centerLine', - strokeDashArray: [5, 5], + strokeDashArray: [8, 4], fontSize: 14, } const centerLineOpt = { stroke: 'blue', - strokeWidth: 5, + strokeWidth: 2, property: 'bigHoriCenter', fontSize: 14, } @@ -2056,10 +2055,8 @@ export function useMode() { const start = polygon.points[i] const end = polygon.points[(i + 1) % polygon.points.length] // 다음 점, 마지막 점의 경우 첫 점으로 - const color = i % 2 === 0 ? '#A0D468' : 'skyblue' - const line = new QLine([start.x, start.y, end.x, end.y], { - stroke: color, + stroke: '#A0D468', strokeWidth: 2, property: 'normal', fontSize: 14, @@ -2074,12 +2071,6 @@ export function useMode() { const sortedIndex = getStartIndex(polygon.lines) let tmpArraySorted = rearrangeArray(polygon.lines, sortedIndex) - - if (tmpArraySorted[0].direction === 'right') { - //시계방향 - tmpArraySorted = tmpArraySorted.reverse() //그럼 배열을 거꾸로 만들어서 무조건 반시계방향으로 배열 보정 - } - setSortedArray(tmpArraySorted) //recoil에 넣음 const points = tmpArraySorted.map((line) => ({ @@ -2090,9 +2081,10 @@ export function useMode() { //좌표 재정렬 function reSortQlineArray(array) { let tmpArray = [] + let minX, minY, maxX, maxY + let tmp array.forEach((arr, index) => { - let minX, minY, maxX, maxY - let tmp = arr + tmp = arr if (arr.x2 < arr.x1 || arr.y2 < arr.y1) { minX = arr.x2 minY = arr.y2 @@ -2149,56 +2141,46 @@ export function useMode() { index: concavePointIndices[0], line: lines[concavePointIndices[0]], } - for (var i = 0; i < points.length; i++) { - var prev = points[(i - 1 + points.length) % points.length] - var current = points[i] - var next = points[(i + 1) % points.length] + + for (let i = 0; i < points.length; i++) { + let prev = points[(i - 1 + points.length) % points.length] + let current = points[i] + let next = points[(i + 1) % points.length] // 두 벡터 계산 (prev -> current, current -> next) - var vector1 = { x: current.x - prev.x, y: current.y - prev.y } - var vector2 = { x: next.x - current.x, y: next.y - current.y } + let vector1 = { x: current.x - prev.x, y: current.y - prev.y } + let vector2 = { x: next.x - current.x, y: next.y - current.y } // 벡터의 길이 계산 - var length1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y) - var length2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y) + let length1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y) + let length2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y) // 벡터를 단위 벡터로 정규화 - var unitVector1 = { x: vector1.x / length1, y: vector1.y / length1 } - var unitVector2 = { x: vector2.x / length2, y: vector2.y / length2 } + let unitVector1 = { x: vector1.x / length1, y: vector1.y / length1 } + let unitVector2 = { x: vector2.x / length2, y: vector2.y / length2 } // 법선 벡터 계산 (왼쪽 방향) - var normal1 = { x: -unitVector1.y, y: unitVector1.x } - var normal2 = { x: -unitVector2.y, y: unitVector2.x } + let normal1 = { x: -unitVector1.y, y: unitVector1.x } + let normal2 = { x: -unitVector2.y, y: unitVector2.x } // 법선 벡터 평균 계산 - var averageNormal = { + let averageNormal = { x: (normal1.x + normal2.x) / 2, y: (normal1.y + normal2.y) / 2, } // 평균 법선 벡터를 단위 벡터로 정규화 - var lengthNormal = Math.sqrt(averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y) - var unitNormal = { + let lengthNormal = Math.sqrt(averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y) + let unitNormal = { x: averageNormal.x / lengthNormal, y: averageNormal.y / lengthNormal, } - if (concavePointIndices[0] === i || concavePointIndices[1] === i) { - //인덱스가 배열이랑 같으면 - if ((concavePointIndices[0] === 4 && concavePointIndices[1] === 5) || (concavePointIndices[0] === 2 && concavePointIndices[1] === 3)) { - offsetX = 1 - offsetY = (offsetInputY / transformedMax) * originalMax * 2 - } else { - offsetX = (offsetInputX / transformedMax) * originalMax * 2 - offsetY = 1 - } - } else { - offsetX = (offsetInputX / transformedMax) * originalMax * 2 - offsetY = (offsetInputY / transformedMax) * originalMax * 2 - } + offsetX = (offsetInputX / transformedMax) * originalMax * 2 + offsetY = (offsetInputY / transformedMax) * originalMax * 2 // 오프셋 적용 - var offsetPoint = { + let offsetPoint = { x1: current.x + unitNormal.x * offsetX, y1: current.y + unitNormal.y * offsetY, } @@ -2207,6 +2189,7 @@ export function useMode() { } const outlinePolygon = makePolygon(offsetPoints) + outlinePolygon.setViewLengthText(false) // 아웃라인 폴리곤의 각 변을 선으로 생성 for (let i = 0; i < outlinePolygon.points.length; i++) { @@ -2218,6 +2201,7 @@ export function useMode() { strokeWidth: 2, property: 'normal', fontSize: 14, + idx: i, }) // 선을 배열에 추가 @@ -2227,13 +2211,8 @@ export function useMode() { canvas?.remove(outlinePolygon) //임시 폴리곤을 삭제 - //라인들을 좌측에서 -> 우측으로 그리는거처럼 데이터 보정 - outLines = reSortQlineArray(outLines) - let parallelLinesIdx = concavePointIndices[0] + 4 //들어간선에 무조건 평행하는 선 찾기 - let parallelLines = outLines[parallelLinesIdx] if (parallelLinesIdx >= outLines.length) { - parallelLines = outLines[parallelLinesIdx - outLines.length] parallelLinesIdx = parallelLinesIdx - outLines.length } @@ -2242,10 +2221,207 @@ export function useMode() { let horiCenterLine = [] let shorVertCenterLine = [] + let edgeIndexArray = [] + if (concavePointIndices[0] % 2 === 0) { - // 오목한 부분이 세로선일때 ㄷ, 역ㄷ + //케라바 색을 바꾼다 + lines.forEach((line, index) => { + if (index % 2 === 0) { + line.line.set('stroke', 'skyblue') + if (concavePointIndices[0] !== index) { + edgeIndexArray.push(index) + } + } + }) + + console.log('edgeIndexArray', edgeIndexArray) + + outLines = reSortQlineArray(outLines) + edgeIndexArray.forEach((idx, index) => { + //가로라인이 케라바 라인임 + if (concavePointIndices[0] !== idx) { + //오목이가 아니면 반으로 갈라서 계산 + + //카라바 선의 2분할 치수를 그림 + let halfLength = outLines[idx].length / 2 + let centerLine1 = new QLine([outLines[idx].x1, outLines[idx].y1, outLines[idx].x1, outLines[idx].y1 + halfLength], centerLineOpt) + canvas.add(centerLine1) + + let centerLine2 = new QLine([outLines[idx].x1, centerLine1.y2, outLines[idx].x2, centerLine1.y2 + halfLength], centerLineOpt) + canvas.add(centerLine2) + canvas.remove(outLines[idx]) //기존 라인 삭제 + + halfHoriCenterLinePoint.push({ index: idx, x1: centerLine1.x1, y1: centerLine1.y1, x2: centerLine1.x2, y2: centerLine1.y2 }) //각 카라바 라인의 1번이 마지막점을 잡아서 센터선으로 설정 + } + }) + + console.log('halfHoriCenterLinePoint', halfHoriCenterLinePoint) + + // //각 센터 라인을 그림 + halfHoriCenterLinePoint.forEach((centerPoint) => { + let tmpX2 = parallelLinesIdx !== centerPoint.index ? concaveLine.line.x2 : outLines[concavePointIndices[0]].x1 //평행선에서 내려오는 선은 아웃라인에 닿아야한다 + + let line = new QLine([centerPoint.x2, centerPoint.y2, tmpX2, centerPoint.y2], centerLineOpt) + canvas.add(line) + + line['arrayIndex'] = centerPoint.index //커스텀으로 기존 index를 넣어줌 + vertCenterLine.push(line) + }) + + vertCenterLine = reSortQlineArray(vertCenterLine) + lines = reSortQlineArray(lines) + + console.log('parallelLinesIdx', parallelLinesIdx) + + //해당라인에서 만나는점을 계산 + vertCenterLine.forEach((vertLine) => { + if (parallelLinesIdx !== vertLine.arrayIndex) { + //평행선을 제외한 애들만 네모를 연결 + let nearLine + let nearOutline + if (vertLine.arrayIndex > concaveLine.index) { + //센터에 인덱스가 오목점 보다 크면 다음 작으면 앞에꺼 + nearLine = lines[concaveLine.index + 1] + nearOutline = outLines[concaveLine.index + 1] + } else { + nearLine = lines[concaveLine.index - 1] + nearOutline = outLines[concaveLine.index - 1] + } + + let nearLineY = nearLine.y1 + if (parallelLinesIdx < concaveLine.index) { + //오목점 위치가 평행선보다 크면 위쪽으로 오목 + nearLineY = nearLine.y2 + } + + //기존에 있는 라인에서 연장해서 새로 그림 + let centerExtendHoriLine = new QLine([vertLine.x1, nearOutline.line.y1, vertLine.x2, nearOutline.line.y2], centerLineOpt) + canvas.add(centerExtendHoriLine) + canvas.remove(nearOutline) + outLines.splice(nearOutline.idx, 1, centerExtendHoriLine) //아웃라인에 데이터를 다시 넣는다 + + let centerExtendLine = new QLine([vertLine.line.x2, vertLine.line.y2, centerExtendHoriLine.x2, centerExtendHoriLine.y2], centerLineOpt) + canvas.add(centerExtendLine) //새로그리고 + + let betweenCenterLine = (vertLine.line.x1 + vertLine.line.x2) / 2 + let centerDashLine = new QLine([vertLine.line.y1, betweenCenterLine, nearOutline.y1, betweenCenterLine], dashedCenterLineOpt) + + canvas.add(centerDashLine) + horiCenterLine.push(centerDashLine) + shorVertCenterLine.push(vertLine) //마지막에 가운데 선을 긋기 위해 담음 + } else { + let longDashLine = halfHoriCenterLinePoint.find((obj) => obj.index === parallelLinesIdx) + + let dashCenterExtendLineLength = longDashLine.x2 - longDashLine.x1 + let betweenCenterLine = (vertLine.line.y1 + vertLine.line.y2) / 2 + let totalLength = ((longDashLine.x2 - longDashLine.x1) * 2) / dashCenterExtendLineLength + + //반 쪼개서 그린다 + for (let i = 0; i < totalLength; i++) { + let startX = i === 0 ? longDashLine.x1 : longDashLine.x1 + dashCenterExtendLineLength + let centerDashLine = new QLine([startX, betweenCenterLine, startX + dashCenterExtendLineLength, betweenCenterLine], dashedCenterLineOpt) + canvas.add(centerDashLine) + horiCenterLine.push(centerDashLine) + } + } + }) + + // //마지막에 오목한 외곽선을 연장한다 + // const tmpLastOutLine = outLines[concavePointIndices[0]] + // const lastOutLine = new QLine([shorVertCenterLine[0].x1, tmpLastOutLine.y1, shorVertCenterLine[1].x1, tmpLastOutLine.y2], centerLineOpt) + // canvas.add(lastOutLine) + // canvas.remove(tmpLastOutLine) + + // let tmpVertCenterLine = outLines.filter((x, index) => index % 2 === 0) //세로만 찾음 + // tmpVertCenterLine = tmpVertCenterLine.concat(vertCenterLine) + // tmpVertCenterLine.sort((a, b) => a.x1 - b.x1) + // tmpVertCenterLine.push(lastOutLine) + + // let roofPatternPolygonArray = [] + // let tmpArray = [] + // let tmpBigArray = [] + + // const lastCenterLine = tmpVertCenterLine[tmpVertCenterLine.length - 1] //마지막 센터라인을 정의 + + // for (let i = 0; i < tmpVertCenterLine.length - 1; i++) { + // //-1인건 마지막은 오목한 선이라 돌 필요 없음 + // //라인 하나에 두점씩 나온다 + // let firstPointObj = {} + // let secondPointObj = {} + + // let x1 = tmpVertCenterLine[i].x1 + // let y1 = tmpVertCenterLine[i].y1 + // let x2 = tmpVertCenterLine[i].x2 + // let y2 = tmpVertCenterLine[i].y2 + + // if (i === 2 || i === 4) { + // tmpArray = [] + // const prevLine = tmpVertCenterLine[i - 1] //뒤에서 앞라인을 찾는다 + // const nextLine = tmpVertCenterLine[i + 1] + + // //내 앞뒤 라인 + // const tmpX1 = i === 2 ? prevLine.x1 : nextLine.x1 + // const tmpY1 = i === 2 ? prevLine.y1 : nextLine.y1 + // const tmpX2 = i === 2 ? prevLine.x2 : nextLine.x2 + // const tmpY2 = i === 2 ? prevLine.y2 : nextLine.y2 + + // firstPointObj = { x: tmpX1, y: tmpY1 } + // secondPointObj = { x: tmpX2, y: tmpY2 } + // tmpArray.push(firstPointObj) + // tmpArray.push(secondPointObj) + + // //현재 내 선 + // firstPointObj = { x: x1, y: y1 } + // secondPointObj = { x: x2, y: y2 } + // tmpArray.push(firstPointObj) + // tmpArray.push(secondPointObj) + // roofPatternPolygonArray.push(tmpArray) + // } else { + // if (i === 1 || i === 5) { + // // 큰 폴리곤은 가운데 선으로 되야됨 + // if (outLines.length / 2 < concavePointIndices[0]) { + // //오목이가 배열 전체보다 크면 위쪽 방향 + // x2 = i === 1 ? lastCenterLine.x2 : lastCenterLine.x1 + // y2 = i === 1 ? lastCenterLine.y2 : lastCenterLine.y1 + // } else { + // x1 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2 + // y1 = i === 1 ? lastCenterLine.y1 : lastCenterLine.y2 + // } + // } + + // if (i === 5) { + // //5번일때는 앞에 3번에 선이 필요하다 + // let prevX1 = tmpVertCenterLine[i - 2].x1 + // let prevY1 = tmpVertCenterLine[i - 2].y1 + // let prevX2 = tmpVertCenterLine[i - 2].x2 + // let prevY2 = tmpVertCenterLine[i - 2].y2 + // firstPointObj = { x: prevX1, y: prevY1 } + // secondPointObj = { x: prevX2, y: prevY2 } + // tmpBigArray.push(firstPointObj) + // tmpBigArray.push(secondPointObj) + // } + + // firstPointObj = { x: x1, y: y1 } + // secondPointObj = { x: x2, y: y2 } + // tmpBigArray.push(firstPointObj) + // tmpBigArray.push(secondPointObj) + + // if (i === 3 || i === 6) { + // roofPatternPolygonArray.push(tmpBigArray) + // tmpBigArray = [] + // } + // } + // } } else { - // 오목한 부분이 세로선일때 ㄷ, 역ㄷ + // 오목한 부분이 세로선일때 아래ㄷ, 위ㄷ + //라인들을 좌측에서 -> 우측으로 그리는거처럼 데이터 보정 + + lines.forEach((line, index) => { + if (!(index % 2 === 0)) { + line.line.set('stroke', 'skyblue') + } + }) + outLines = reSortQlineArray(outLines) outLines.forEach((outline, index) => { if (!(index % 2 === 0)) { //세로라인이 케라바 라인임 @@ -2255,20 +2431,10 @@ export function useMode() { //카라바 선의 2분할 치수를 그림 let halfLength = outline.length / 2 - let centerLine1 = new QLine([outline.x1, outline.y1, outline.x1 + halfLength, outline.y1], { - stroke: 'red', - strokeWidth: 2, - property: 'normal', - fontSize: 14, - }) + let centerLine1 = new QLine([outline.x1, outline.y1, outline.x1 + halfLength, outline.y1], centerLineOpt) canvas.add(centerLine1) - let centerLine2 = new QLine([centerLine1.x2, outline.y1, centerLine1.x2 + halfLength, outline.y1], { - stroke: 'red', - strokeWidth: 2, - property: 'normal', - fontSize: 14, - }) + let centerLine2 = new QLine([centerLine1.x2, outline.y1, centerLine1.x2 + halfLength, outline.y1], centerLineOpt) canvas.add(centerLine2) canvas.remove(outline) //기존 라인 삭제 @@ -2279,7 +2445,9 @@ export function useMode() { //각 센터 라인을 그림 halfHoriCenterLinePoint.forEach((centerPoint) => { - let line = new QLine([centerPoint.x2, centerPoint.y1, centerPoint.x2, concaveLine.line.y1], centerLineOpt) + let tmpY2 = parallelLinesIdx !== centerPoint.index ? concaveLine.line.y1 : outLines[concavePointIndices[0]].y2 //평행선에서 내려오는 선은 아웃라인에 닿아야한다 + + let line = new QLine([centerPoint.x2, centerPoint.y1, centerPoint.x2, tmpY2], centerLineOpt) canvas.add(line) line['arrayIndex'] = centerPoint.index //커스텀으로 기존 index를 넣어줌 @@ -2287,18 +2455,21 @@ export function useMode() { }) vertCenterLine = reSortQlineArray(vertCenterLine) + lines = reSortQlineArray(lines) //해당라인에서 만나는점을 계산 vertCenterLine.forEach((vertLine) => { if (parallelLinesIdx !== vertLine.arrayIndex) { //평행선을 제외한 애들만 네모를 연결 let nearLine - + let nearOutline if (vertLine.arrayIndex > concaveLine.index) { //센터에 인덱스가 오목점 보다 크면 다음 작으면 앞에꺼 - nearLine = outLines[concaveLine.index + 1] + nearLine = lines[concaveLine.index + 1] + nearOutline = outLines[concaveLine.index + 1] } else { - nearLine = outLines[concaveLine.index - 1] + nearLine = lines[concaveLine.index - 1] + nearOutline = outLines[concaveLine.index - 1] } let nearLineY = nearLine.y1 @@ -2307,11 +2478,17 @@ export function useMode() { nearLineY = nearLine.y2 } - let centerExtendLine = new QLine([vertLine.line.x1, nearLineY, nearLine.x1, nearLineY], centerLineOpt) - canvas.add(centerExtendLine) + let centerExtendLine = new QLine([vertLine.line.x1, nearLineY, nearOutline.x1, nearLineY], centerLineOpt) + canvas.add(centerExtendLine) //새로그리고 + + //기존에 있는 라인에서 연장해서 새로 그림 + let centerExtendHoriLine = new QLine([nearOutline.line.x1, vertLine.y1, nearOutline.line.x2, vertLine.line.y2], centerLineOpt) + canvas.add(centerExtendHoriLine) + canvas.remove(nearOutline) + outLines.splice(nearOutline.idx, 1, centerExtendHoriLine) //아웃라인에 데이터를 다시 넣는다 let betweenCenterLine = (vertLine.line.y1 + vertLine.line.y2) / 2 - let centerDashLine = new QLine([vertLine.line.x1, betweenCenterLine, nearLine.x1, betweenCenterLine], dashedCenterLineOpt) + let centerDashLine = new QLine([vertLine.line.x1, betweenCenterLine, nearOutline.x1, betweenCenterLine], dashedCenterLineOpt) canvas.add(centerDashLine) horiCenterLine.push(centerDashLine) @@ -2319,30 +2496,108 @@ export function useMode() { } else { let longDashLine = halfHoriCenterLinePoint.find((obj) => obj.index === parallelLinesIdx) - let dashCenterExtendLineLength = (longDashLine.x2 - longDashLine.x1) * 2 + let dashCenterExtendLineLength = longDashLine.x2 - longDashLine.x1 let betweenCenterLine = (vertLine.line.y1 + vertLine.line.y2) / 2 + let totalLength = ((longDashLine.x2 - longDashLine.x1) * 2) / dashCenterExtendLineLength - let centerDashLine = new QLine( - [longDashLine.x1, betweenCenterLine, longDashLine.x1 + dashCenterExtendLineLength, betweenCenterLine], - dashedCenterLineOpt, - ) - canvas.add(centerDashLine) - horiCenterLine.push(centerDashLine) + //반 쪼개서 그린다 + for (let i = 0; i < totalLength; i++) { + let startX = i === 0 ? longDashLine.x1 : longDashLine.x1 + dashCenterExtendLineLength + let centerDashLine = new QLine([startX, betweenCenterLine, startX + dashCenterExtendLineLength, betweenCenterLine], dashedCenterLineOpt) + canvas.add(centerDashLine) + horiCenterLine.push(centerDashLine) + } } }) - if (parallelLinesIdx < concaveLine.index) { - offsetY = offsetY * -1 // 위로올린다 + //마지막에 오목한 외곽선을 연장한다 + const tmpLastOutLine = outLines[concavePointIndices[0]] + const lastOutLine = new QLine([shorVertCenterLine[0].x1, tmpLastOutLine.y1, shorVertCenterLine[1].x1, tmpLastOutLine.y2], centerLineOpt) + canvas.add(lastOutLine) + canvas.remove(tmpLastOutLine) + + let tmpVertCenterLine = outLines.filter((x, index) => index % 2 === 0) //세로만 찾음 + tmpVertCenterLine = tmpVertCenterLine.concat(vertCenterLine) + tmpVertCenterLine.sort((a, b) => a.x1 - b.x1) + tmpVertCenterLine.push(lastOutLine) + + let roofPatternPolygonArray = [] + let tmpArray = [] + let tmpBigArray = [] + + const lastCenterLine = tmpVertCenterLine[tmpVertCenterLine.length - 1] //마지막 센터라인을 정의 + + for (let i = 0; i < tmpVertCenterLine.length - 1; i++) { + //-1인건 마지막은 오목한 선이라 돌 필요 없음 + //라인 하나에 두점씩 나온다 + let firstPointObj = {} + let secondPointObj = {} + + let x1 = tmpVertCenterLine[i].x1 + let y1 = tmpVertCenterLine[i].y1 + let x2 = tmpVertCenterLine[i].x2 + let y2 = tmpVertCenterLine[i].y2 + + if (i === 2 || i === 4) { + tmpArray = [] + const prevLine = tmpVertCenterLine[i - 1] //뒤에서 앞라인을 찾는다 + const nextLine = tmpVertCenterLine[i + 1] + + //내 앞뒤 라인 + const tmpX1 = i === 2 ? prevLine.x1 : nextLine.x1 + const tmpY1 = i === 2 ? prevLine.y1 : nextLine.y1 + const tmpX2 = i === 2 ? prevLine.x2 : nextLine.x2 + const tmpY2 = i === 2 ? prevLine.y2 : nextLine.y2 + + firstPointObj = { x: tmpX1, y: tmpY1 } + secondPointObj = { x: tmpX2, y: tmpY2 } + tmpArray.push(firstPointObj) + tmpArray.push(secondPointObj) + + //현재 내 선 + firstPointObj = { x: x1, y: y1 } + secondPointObj = { x: x2, y: y2 } + tmpArray.push(firstPointObj) + tmpArray.push(secondPointObj) + roofPatternPolygonArray.push(tmpArray) + } else { + if (i === 1 || i === 5) { + // 큰 폴리곤은 가운데 선으로 되야됨 + if (outLines.length / 2 < concavePointIndices[0]) { + //오목이가 배열 전체보다 크면 위쪽 방향 + x2 = i === 1 ? lastCenterLine.x2 : lastCenterLine.x1 + y2 = i === 1 ? lastCenterLine.y2 : lastCenterLine.y1 + } else { + x1 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2 + y1 = i === 1 ? lastCenterLine.y1 : lastCenterLine.y2 + } + } + + if (i === 5) { + //5번일때는 앞에 3번에 선이 필요하다 + let prevX1 = tmpVertCenterLine[i - 2].x1 + let prevY1 = tmpVertCenterLine[i - 2].y1 + let prevX2 = tmpVertCenterLine[i - 2].x2 + let prevY2 = tmpVertCenterLine[i - 2].y2 + firstPointObj = { x: prevX1, y: prevY1 } + secondPointObj = { x: prevX2, y: prevY2 } + tmpBigArray.push(firstPointObj) + tmpBigArray.push(secondPointObj) + } + + firstPointObj = { x: x1, y: y1 } + secondPointObj = { x: x2, y: y2 } + tmpBigArray.push(firstPointObj) + tmpBigArray.push(secondPointObj) + + if (i === 3 || i === 6) { + roofPatternPolygonArray.push(tmpBigArray) + tmpBigArray = [] + } + } } - - const lastInLine = new QLine( - [shorVertCenterLine[0].x1, lines[concavePointIndices[0]].y1 + offsetY, shorVertCenterLine[1].x1, lines[concavePointIndices[0]].y2 + offsetY], - centerLineOpt, - ) - canvas.add(lastInLine) - canvas.remove(outLines[concavePointIndices[0]]) + setRoofPolygonPattern({ roofPatternPolygonArray, lines }) } - canvas.renderAll() } @@ -2871,8 +3126,6 @@ export function useMode() { } const makeRoofPatternPolygon = (roofStyle) => { - console.log('roofPolygonPattern', roofPolygonPattern) - if (Object.keys(roofPolygonPattern).length === 0 && roofPolygonPattern.constructor === Object) { alert('객체가 비어있습니다.') return @@ -2918,7 +3171,7 @@ export function useMode() { const commonOption = { fill: pattern, - selectable: false, + selectable: true, fontSize: 15, // fontSize는 필요에 따라 조정 } From 96b1e5822ffd4e85a16187a9a5f8e2f590cac749 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 29 Jul 2024 11:32:30 +0900 Subject: [PATCH 7/7] =?UTF-8?q?8=EA=B0=81=20=E3=84=B7=EC=9E=90=20=ED=8C=A8?= =?UTF-8?q?=ED=84=B4=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useMode.js | 189 +++++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 88 deletions(-) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index 033b0a7f..1ee98028 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -2226,6 +2226,7 @@ export function useMode() { let edgeIndexArray = [] if (concavePointIndices[0] % 2 === 0) { + //concave가 짝수면 좌우로 그려진 ㄷ자 //케라바 색을 바꾼다 lines.forEach((line, index) => { if (index % 2 === 0) { @@ -2236,8 +2237,6 @@ export function useMode() { } }) - console.log('edgeIndexArray', edgeIndexArray) - outLines = reSortQlineArray(outLines) edgeIndexArray.forEach((idx, index) => { //가로라인이 케라바 라인임 @@ -2257,8 +2256,6 @@ export function useMode() { } }) - console.log('halfHoriCenterLinePoint', halfHoriCenterLinePoint) - // //각 센터 라인을 그림 halfHoriCenterLinePoint.forEach((centerPoint) => { let tmpX2 = parallelLinesIdx !== centerPoint.index ? concaveLine.line.x2 : outLines[concavePointIndices[0]].x1 //평행선에서 내려오는 선은 아웃라인에 닿아야한다 @@ -2273,8 +2270,6 @@ export function useMode() { vertCenterLine = reSortQlineArray(vertCenterLine) lines = reSortQlineArray(lines) - console.log('parallelLinesIdx', parallelLinesIdx) - //해당라인에서 만나는점을 계산 vertCenterLine.forEach((vertLine) => { if (parallelLinesIdx !== vertLine.arrayIndex) { @@ -2302,118 +2297,136 @@ export function useMode() { canvas.remove(nearOutline) outLines.splice(nearOutline.idx, 1, centerExtendHoriLine) //아웃라인에 데이터를 다시 넣는다 - let centerExtendLine = new QLine([vertLine.line.x2, vertLine.line.y2, centerExtendHoriLine.x2, centerExtendHoriLine.y2], centerLineOpt) + //가로형에선 기본으로 ㄷ자 형태로 한다 + let centerExtendLine = new QLine([vertLine.line.x1, vertLine.line.y1, centerExtendHoriLine.x1, centerExtendHoriLine.y1], centerLineOpt) + + //오목이가 배열에 반보다 작으면 역 ㄷ자 여서 변경 + if (concavePointIndices[0] < outLines.length / 2) { + centerExtendLine = new QLine([vertLine.line.x2, vertLine.line.y2, centerExtendHoriLine.x2, centerExtendHoriLine.y2], centerLineOpt) + } + canvas.add(centerExtendLine) //새로그리고 let betweenCenterLine = (vertLine.line.x1 + vertLine.line.x2) / 2 - let centerDashLine = new QLine([vertLine.line.y1, betweenCenterLine, nearOutline.y1, betweenCenterLine], dashedCenterLineOpt) + let centerDashLine = new QLine([betweenCenterLine, centerExtendLine.y1, betweenCenterLine, centerExtendLine.y2], dashedCenterLineOpt) canvas.add(centerDashLine) horiCenterLine.push(centerDashLine) shorVertCenterLine.push(vertLine) //마지막에 가운데 선을 긋기 위해 담음 } else { - let longDashLine = halfHoriCenterLinePoint.find((obj) => obj.index === parallelLinesIdx) + let longDashLine = halfHoriCenterLinePoint.find((obj) => obj.index === parallelLinesIdx) //평행선 - let dashCenterExtendLineLength = longDashLine.x2 - longDashLine.x1 - let betweenCenterLine = (vertLine.line.y1 + vertLine.line.y2) / 2 - let totalLength = ((longDashLine.x2 - longDashLine.x1) * 2) / dashCenterExtendLineLength + let dashCenterExtendLineLength = longDashLine.y2 - longDashLine.y1 //y반개 길이 + let betweenCenterLine = (vertLine.line.x1 + vertLine.line.x2) / 2 //y의 길이 + let totalLength = ((longDashLine.y2 - longDashLine.y1) * 2) / dashCenterExtendLineLength //2개로 나눔 //반 쪼개서 그린다 for (let i = 0; i < totalLength; i++) { - let startX = i === 0 ? longDashLine.x1 : longDashLine.x1 + dashCenterExtendLineLength - let centerDashLine = new QLine([startX, betweenCenterLine, startX + dashCenterExtendLineLength, betweenCenterLine], dashedCenterLineOpt) + //2번에 나눠서 + let startY = i === 0 ? longDashLine.y1 : longDashLine.y1 + dashCenterExtendLineLength //시작 하는 y의 좌표 + //x값은 고정이임 //TODO: 지붕 각도 계산법에 의해 재계산해야함 + let centerDashLine = new QLine([betweenCenterLine, startY, betweenCenterLine, startY + dashCenterExtendLineLength], dashedCenterLineOpt) canvas.add(centerDashLine) horiCenterLine.push(centerDashLine) } } }) - // //마지막에 오목한 외곽선을 연장한다 - // const tmpLastOutLine = outLines[concavePointIndices[0]] - // const lastOutLine = new QLine([shorVertCenterLine[0].x1, tmpLastOutLine.y1, shorVertCenterLine[1].x1, tmpLastOutLine.y2], centerLineOpt) - // canvas.add(lastOutLine) - // canvas.remove(tmpLastOutLine) + //마지막에 오목한 외곽선을 연장한다 + const tmpLastOutLine = outLines[concavePointIndices[0]] + const lastOutLine = new QLine([tmpLastOutLine.x1, shorVertCenterLine[0].y1, tmpLastOutLine.x1, shorVertCenterLine[1].y1], centerLineOpt) + canvas.add(lastOutLine) + canvas.remove(tmpLastOutLine) - // let tmpVertCenterLine = outLines.filter((x, index) => index % 2 === 0) //세로만 찾음 - // tmpVertCenterLine = tmpVertCenterLine.concat(vertCenterLine) - // tmpVertCenterLine.sort((a, b) => a.x1 - b.x1) - // tmpVertCenterLine.push(lastOutLine) + //폴리곤 패턴을 그리기 위해 작성 + let tmpVertCenterLine = outLines.filter((x, index) => index % 2 !== 0) //세로만 찾음 + tmpVertCenterLine = tmpVertCenterLine.concat(vertCenterLine) + tmpVertCenterLine.sort((a, b) => a.y1 - b.y1) + tmpVertCenterLine.push(lastOutLine) - // let roofPatternPolygonArray = [] - // let tmpArray = [] - // let tmpBigArray = [] + let roofPatternPolygonArray = [] + let tmpArray = [] + let tmpBigArray = [] - // const lastCenterLine = tmpVertCenterLine[tmpVertCenterLine.length - 1] //마지막 센터라인을 정의 + console.log('tmpVertCenterLine', tmpVertCenterLine) - // for (let i = 0; i < tmpVertCenterLine.length - 1; i++) { - // //-1인건 마지막은 오목한 선이라 돌 필요 없음 - // //라인 하나에 두점씩 나온다 - // let firstPointObj = {} - // let secondPointObj = {} + const lastCenterLine = tmpVertCenterLine[tmpVertCenterLine.length - 1] //마지막 센터라인을 정의 - // let x1 = tmpVertCenterLine[i].x1 - // let y1 = tmpVertCenterLine[i].y1 - // let x2 = tmpVertCenterLine[i].x2 - // let y2 = tmpVertCenterLine[i].y2 + for (let i = 0; i < tmpVertCenterLine.length - 1; i++) { + //-1인건 마지막은 오목한 선이라 돌 필요 없음 + //라인 하나에 두점씩 나온다 + let firstPointObj = {} + let secondPointObj = {} - // if (i === 2 || i === 4) { - // tmpArray = [] - // const prevLine = tmpVertCenterLine[i - 1] //뒤에서 앞라인을 찾는다 - // const nextLine = tmpVertCenterLine[i + 1] + let x1 = tmpVertCenterLine[i].x1 + let y1 = tmpVertCenterLine[i].y1 + let x2 = tmpVertCenterLine[i].x2 + let y2 = tmpVertCenterLine[i].y2 - // //내 앞뒤 라인 - // const tmpX1 = i === 2 ? prevLine.x1 : nextLine.x1 - // const tmpY1 = i === 2 ? prevLine.y1 : nextLine.y1 - // const tmpX2 = i === 2 ? prevLine.x2 : nextLine.x2 - // const tmpY2 = i === 2 ? prevLine.y2 : nextLine.y2 + if (i === 2 || i === 4) { + //작은 네모들 + tmpArray = [] + const prevLine = tmpVertCenterLine[i - 1] //뒤에서 앞라인을 찾는다 + const nextLine = tmpVertCenterLine[i + 1] - // firstPointObj = { x: tmpX1, y: tmpY1 } - // secondPointObj = { x: tmpX2, y: tmpY2 } - // tmpArray.push(firstPointObj) - // tmpArray.push(secondPointObj) + //내 앞뒤 라인 + const tmpX1 = i === 2 ? prevLine.x1 : nextLine.x1 + const tmpY1 = i === 2 ? prevLine.y1 : nextLine.y1 + const tmpX2 = i === 2 ? prevLine.x2 : nextLine.x2 + const tmpY2 = i === 2 ? prevLine.y2 : nextLine.y2 - // //현재 내 선 - // firstPointObj = { x: x1, y: y1 } - // secondPointObj = { x: x2, y: y2 } - // tmpArray.push(firstPointObj) - // tmpArray.push(secondPointObj) - // roofPatternPolygonArray.push(tmpArray) - // } else { - // if (i === 1 || i === 5) { - // // 큰 폴리곤은 가운데 선으로 되야됨 - // if (outLines.length / 2 < concavePointIndices[0]) { - // //오목이가 배열 전체보다 크면 위쪽 방향 - // x2 = i === 1 ? lastCenterLine.x2 : lastCenterLine.x1 - // y2 = i === 1 ? lastCenterLine.y2 : lastCenterLine.y1 - // } else { - // x1 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2 - // y1 = i === 1 ? lastCenterLine.y1 : lastCenterLine.y2 - // } - // } + firstPointObj = { x: tmpX1, y: tmpY1 } + secondPointObj = { x: tmpX2, y: tmpY2 } + tmpArray.push(firstPointObj) + tmpArray.push(secondPointObj) - // if (i === 5) { - // //5번일때는 앞에 3번에 선이 필요하다 - // let prevX1 = tmpVertCenterLine[i - 2].x1 - // let prevY1 = tmpVertCenterLine[i - 2].y1 - // let prevX2 = tmpVertCenterLine[i - 2].x2 - // let prevY2 = tmpVertCenterLine[i - 2].y2 - // firstPointObj = { x: prevX1, y: prevY1 } - // secondPointObj = { x: prevX2, y: prevY2 } - // tmpBigArray.push(firstPointObj) - // tmpBigArray.push(secondPointObj) - // } + //현재 내 선 + firstPointObj = { x: x1, y: y1 } + secondPointObj = { x: x2, y: y2 } + tmpArray.push(firstPointObj) + tmpArray.push(secondPointObj) + roofPatternPolygonArray.push(tmpArray) + } else { + //큰 육각 + if (i === 1 || i === 5) { + // 큰 폴리곤은 가운데 선으로 되야됨 + if (outLines.length / 2 > concavePointIndices[0]) { + x2 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2 + y2 = i === 1 ? lastCenterLine.y1 : lastCenterLine.y2 + } else { + //오목이가 배열 전체보다 크면 오른쪽 오목이 + x1 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2 + y1 = i === 1 ? lastCenterLine.y2 : lastCenterLine.y1 + } + } - // firstPointObj = { x: x1, y: y1 } - // secondPointObj = { x: x2, y: y2 } - // tmpBigArray.push(firstPointObj) - // tmpBigArray.push(secondPointObj) + if (i === 5) { + //5번일때는 앞에 3번에 선이 필요하다 + let prevX1 = tmpVertCenterLine[i - 2].x1 + let prevY1 = tmpVertCenterLine[i - 2].y1 + let prevX2 = tmpVertCenterLine[i - 2].x2 + let prevY2 = tmpVertCenterLine[i - 2].y2 + firstPointObj = { x: prevX1, y: prevY1 } + secondPointObj = { x: prevX2, y: prevY2 } + tmpBigArray.push(firstPointObj) + tmpBigArray.push(secondPointObj) + } - // if (i === 3 || i === 6) { - // roofPatternPolygonArray.push(tmpBigArray) - // tmpBigArray = [] - // } - // } - // } + firstPointObj = { x: x1, y: y1 } + secondPointObj = { x: x2, y: y2 } + tmpBigArray.push(firstPointObj) + tmpBigArray.push(secondPointObj) + + if (i === 3 || i === 6) { + roofPatternPolygonArray.push(tmpBigArray) + tmpBigArray = [] + } + } + } + + console.log('roofPatternPolygonArray', roofPatternPolygonArray) + + setRoofPolygonPattern({ roofPatternPolygonArray, lines }) } else { // 오목한 부분이 세로선일때 아래ㄷ, 위ㄷ //라인들을 좌측에서 -> 우측으로 그리는거처럼 데이터 보정