diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx index 004f03db..370a1e2e 100644 --- a/src/components/Roof2.jsx +++ b/src/components/Roof2.jsx @@ -208,7 +208,7 @@ export default function Roof2() { ] if (canvas) { - const polygon = new QPolygon(eightPoint, { + const polygon = new QPolygon(type1, { fill: 'transparent', stroke: 'black', strokeWidth: 1, diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 98948ac4..9c8c2133 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -36,28 +36,36 @@ export class QLine extends fabric.Group { } const line = new fabric.Line(points, { ...option, strokeWidth: 1 }) - super([line], {}) - this.initPoints = points - this.initOption = option - this.initLengthTxt = lengthTxt + // 길이가 1이하인 선은 생성하지 않음 + if (Math.abs(x1 - x2) <= 1 && Math.abs(y1 - y2) <= 1) { + super([], {}) + this.initPoints = points + this.initOption = option + this.initLengthTxt = lengthTxt + } else { + super([line], {}) + this.initPoints = points + this.initOption = option + this.initLengthTxt = lengthTxt - this.x1 = x1 - this.y1 = y1 - this.x2 = x2 - this.y2 = y2 - this.line = line - this.fontSize = option.fontSize - this.direction = option.direction ?? getDirectionByPoint({ x: x1, y: y1 }, { x: x2, y: y2 }) - this.parent = option.parent - this.idx = option.idx + this.x1 = x1 + this.y1 = y1 + this.x2 = x2 + this.y2 = y2 + this.line = line + this.fontSize = option.fontSize + this.direction = option.direction ?? getDirectionByPoint({ x: x1, y: y1 }, { x: x2, y: y2 }) + this.parent = option.parent + this.idx = option.idx - if (lengthTxt > 0) { - this.lengthTxt = Number(lengthTxt) + if (lengthTxt > 0) { + this.lengthTxt = Number(lengthTxt) + } + + option.isActiveLengthText ?? this.init() + this.addControl() } - - option.isActiveLengthText ?? this.init() - this.addControl() } init() { @@ -156,6 +164,7 @@ export class QLine extends fabric.Group { initPoints: this.initPoints, initOption: this.initOption, initLengthTxt: this.initLengthTxt, + points: this.points, }) } diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index f903289e..b10c8465 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -12,7 +12,7 @@ import { sortedPoints, } from '@/util/canvas-util' import { QLine } from '@/components/fabric/QLine' -import { drawHelpLineInHexagon2 } from '@/util/qpolygon-utils' +import { drawHelpLineInHexagon } from '@/util/qpolygon-utils' export default class QPolygon extends fabric.Group { type = 'QPolygon' @@ -73,6 +73,7 @@ export default class QPolygon extends fabric.Group { stroke: this.stroke, strokeWidth: this.strokeWidth, fontSize: this.fontSize, + idx: i, direction: getDirectionByPoint(point, nextPoint), }) @@ -321,19 +322,20 @@ export default class QPolygon extends fabric.Group { // 보조선 그리기 drawHelpLine(chon = 4) { - if (!this.isValid()) { + drawHelpLineInHexagon(this, chon) + /*if (!this.isValid()) { return - } + }*/ - if (this.lines.length === 4) { + /*if (this.lines.length === 4) { this.drawHelpLineInRect(chon) } else if (this.lines.length === 6 || this.lines.length === 8) { // TODO : 6각형 drawHelpLineInHexagon2(this, chon) - } /* else if (this.lines.length === 8) { + } /!* else if (this.lines.length === 8) { // TODO : 8각형 this.drawHelpLineInOctagon(chon) - }*/ + }*!/*/ } /** @@ -925,6 +927,7 @@ export default class QPolygon extends fabric.Group { initPoints: this.initPoints, initOption: this.initOption, objects: this.getObjects().map((obj) => obj.toObject(propertiesToInclude)), + pattern: this.pattern, }) } diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index dab596c2..9d3743df 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -4,8 +4,9 @@ import QPolygon from '@/components/fabric/QPolygon' import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util' import { useRecoilState } from 'recoil' -import { fontSizeState, roofPolygonPatternArrayState, roofState, sortedPolygonArray, wallState } from '@/store/canvasAtom' +import { canvasSizeState, fontSizeState, roofPolygonPatternArrayState, roofState, sortedPolygonArray, wallState } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' +import { fabric } from 'fabric' export const Mode = { DRAW_LINE: 'drawLine', // 기준선 긋기모드 @@ -32,8 +33,12 @@ export function useMode() { const [roof, setRoof] = useRecoilState(roofState) const [wall, setWall] = useRecoilState(wallState) + const [endPoint, setEndPoint] = useState(null) + const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState) + const [canvasSize] = useRecoilState(canvasSizeState) + useEffect(() => { // 이벤트 리스너 추가 if (!canvas) { @@ -47,6 +52,93 @@ export function useMode() { } }, [canvas]) // 빈 배열을 전달하여 컴포넌트가 마운트될 때만 실행되도록 함 + useEffect(() => { + if (canvas?.getObjects().find((obj) => obj.name === 'connectLine')) { + canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'connectLine')) + } + canvas?.off('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint)) + canvas?.off('mouse:move') + canvas?.on('mouse:move', drawMouseLines) + canvas?.off('mouse:out', removeMouseLines) + canvas?.on('mouse:out', removeMouseLines) + if (!endPoint) { + return + } + + canvas?.on('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint)) + }, [endPoint]) + + const drawMouseLines = (e) => { + // 현재 마우스 포인터의 위치를 가져옵니다. + const pointer = canvas?.getPointer(e.e) + + // 기존에 그려진 가이드라인을 제거합니다. + removeMouseLines() + + if (canvas?.getActiveObject()) { + return + } + + // 가로선을 그립니다. + const horizontalLine = new fabric.Line([0, pointer.y, canvasSize.horizontal, pointer.y], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'mouseLine', + }) + + // 세로선을 그립니다. + const verticalLine = new fabric.Line([pointer.x, 0, pointer.x, canvasSize.vertical], { + stroke: 'black', + strokeWidth: 1, + selectable: false, + name: 'mouseLine', + }) + + // 선들을 캔버스에 추가합니다. + canvas?.add(horizontalLine, verticalLine) + + // 캔버스를 다시 그립니다. + canvas?.renderAll() + } + + /** + * 마우스 포인터의 가이드라인을 제거합니다. + */ + const removeMouseLines = () => { + if (canvas?._objects.length > 0) { + const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine') + mouseLines.forEach((item) => canvas?.remove(item)) + } + canvas?.renderAll() + } + + const addLineEndPointToMousePoint = (e, endPoint) => { + if (canvas?.getObjects().find((obj) => obj.name === 'connectLine')) { + canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'connectLine')) + } + + if (!endPoint) { + return + } + + const pointer = canvas?.getPointer(e.e) + + // 마우스 포인터 위치랑 endPoint를 연결하는 line 생성 + const line = new QLine([endPoint.left, endPoint.top, pointer.x, pointer.y], { + stroke: 'black', + strokeWidth: 2, + selectable: false, + viewLengthText: true, + fontSize: fontSize, + }) + + line.set({ name: 'connectLine' }) + + canvas?.add(line) + canvas?.renderAll() + } + const addEvent = (mode) => { switch (mode) { case 'default': @@ -98,6 +190,7 @@ export function useMode() { originY: 'center', selectable: false, }) + historyPoints.current.push(circle) points.current.push(circle) canvas?.add(circle) @@ -142,6 +235,8 @@ export function useMode() { selectable: false, }) + setEndPoint(endPointCircle) + canvas?.add(endPointCircle) historyPoints.current.push(endPointCircle) @@ -221,10 +316,12 @@ export function useMode() { } const changeMode = (canvas, mode) => { + setEndPoint(null) setMode(mode) // mode변경 시 이전 이벤트 제거 setCanvas(canvas) canvas?.off('mouse:down') + addEvent(mode) } @@ -242,6 +339,8 @@ export function useMode() { selectable: false, }) + setEndPoint(circle) + historyPoints.current.push(circle) points.current.push(circle) canvas?.add(circle) @@ -308,7 +407,7 @@ export function useMode() { originY: 'center', selectable: false, }) - + setEndPoint(endPointCircle) canvas?.add(endPointCircle) historyPoints.current.push(endPointCircle) @@ -556,7 +655,7 @@ export function useMode() { if (!otherLines) { // polygon.fillCell() canvas.renderAll() - polygon.setViewLengthText(false) + // polygon.setViewLengthText(false) setMode(Mode.DEFAULT) } diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 072f7bab..e7bdb373 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -649,3 +649,26 @@ export function removeDuplicatePoints(points) { return uniquePoints } + +/** + * x,y가 다르면서 가장 가까운 점 + * @param targetPoint + * @param points + * @returns {null} + */ +export function findClosestPointWithDifferentXY(targetPoint, points) { + let closestPoint = null + let smallestDistance = Infinity + + points.forEach((point) => { + if (point.x !== targetPoint.x && point.y !== targetPoint.y) { + const distance = Math.sqrt(Math.pow(point.x - targetPoint.x, 2) + Math.pow(point.y - targetPoint.y, 2)) + if (distance < smallestDistance) { + smallestDistance = distance + closestPoint = point + } + } + }) + + return closestPoint +} diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index e683e4be..bd5676bd 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -1,7 +1,19 @@ import { fabric } from 'fabric' import QPolygon from '@/components/fabric/QPolygon' import { QLine } from '@/components/fabric/QLine' -import { calculateIntersection, calculateIntersection2, distanceBetweenPoints, findIntersection1, removeDuplicatePoints } from '@/util/canvas-util' +import { + calculateDistance, + calculateIntersection, + calculateIntersection2, + distanceBetweenPoints, + findClosestLineToPoint, + findClosestPoint, + findClosestPointWithDifferentXY, + findIntersection1, + getRoofHypotenuse, + removeDuplicatePoints, +} from '@/util/canvas-util' +import { help } from 'mathjs' export const defineQPloygon = () => { fabric.QPolygon = fabric.util.createClass(fabric.Group, {}) @@ -14,8 +26,287 @@ export const defineQPloygon = () => { } } -export const drawHelpLineInHexagon2 = (polygon, chon) => { - const oneSideLines = [...polygon.lines].map((line) => { +export const drawHelpLineInHexagon = (polygon, chon) => { + const centerLines = drawCenterLines(polygon) + let helpLines = [] + + const ridgeStartPoints = [] + const ridgeEndPoints = [] + + const centerInterSectionPoints = [] + + let maxLength = 0 + + polygon.lines = polygon.lines.sort((a, b) => a.length - b.length) + + polygon.wall.lines = getOneSideLines(polygon.wall) + + // 짧은 라인 순서대로 삼각 지붕을 그린다. + polygon.lines.forEach((line, index) => { + if (line.length > maxLength) { + maxLength = line.length + } + const wallLine = polygon.wall.lines.filter((wallLine) => wallLine.idx === line.idx)[0] + + const checkPoint1 = polygon.points.filter((point) => point.x === line.x1 && point.y === line.y1)[0] + const checkPoint2 = polygon.points.filter((point) => point.x === line.x2 && point.y === line.y2)[0] + + if (checkPoint1.alreadyIntersected || checkPoint2.alreadyIntersected) { + return + } + + 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) + + const firstX2 = Math.floor(line.x1 + helpLineLength * Math.cos(angle1)) + const firstY2 = Math.floor(line.y1 + helpLineLength * Math.sin(angle1)) + + const secondX2 = Math.floor(line.x2 + helpLineLength * Math.cos(angle2)) + const secondY2 = Math.floor(line.y2 + helpLineLength * Math.sin(angle2)) + + const firstHelpLine = new QLine([line.x1, line.y1, firstX2, firstY2], { + fontSize: polygon.fontSize, + }) + + const secondHelpLine = new QLine([line.x2, line.y2, secondX2, secondY2], { + fontSize: polygon.fontSize, + }) + + const interSectionPoint = calculateIntersection2(firstHelpLine, secondHelpLine) + + if (interSectionPoint) { + if (polygon.inPolygon(interSectionPoint) && polygon.wall.inPolygon(interSectionPoint)) { + checkPoint1.alreadyIntersected = true + checkPoint2.alreadyIntersected = true + + const helpLine1 = new QLine([line.x1, line.y1, interSectionPoint.x, interSectionPoint.y], { + fontSize: polygon.fontSize, + stroke: 'skyblue', + }) + + const helpLine2 = new QLine([line.x2, line.y2, interSectionPoint.x, interSectionPoint.y], { + fontSize: polygon.fontSize, + stroke: 'skyblue', + }) + + helpLines.push(helpLine1) + helpLines.push(helpLine2) + + polygon.canvas.add(helpLine1) + polygon.canvas.add(helpLine2) + + ridgeStartPoints.push(interSectionPoint) + } + } + + polygon.canvas.renderAll() + }) + // points를 순회하면서 이미 그려진 점이 아닌 경우 centerLine과 만나는 점을 찾는다. + polygon.points.forEach((point, index) => { + if (point.alreadyIntersected) { + return + } + + const wallPoint = polygon.wall.points[index] + + const angle = Math.atan2(wallPoint.y - point.y, wallPoint.x - point.x) + + const newX2 = Math.floor(point.x + (maxLength / 2 + 50) * Math.cos(angle)) + const newY2 = Math.floor(point.y + (maxLength / 2 + 50) * Math.sin(angle)) + + const helpLine = new QLine([point.x, point.y, newX2, newY2], { + fontSize: polygon.fontSize, + stroke: 'green', + }) + + const relatedPoints = [] + + centerLines.forEach((centerLine) => { + const interSectionPoint = calculateIntersection2(helpLine, centerLine) + + if (interSectionPoint) { + if (polygon.inPolygon(interSectionPoint) && polygon.wall.inPolygon(interSectionPoint)) { + relatedPoints.push(interSectionPoint) + + centerInterSectionPoints.push(interSectionPoint) + } + } + }) + + helpLine.set({ relatedPoints: relatedPoints }) + helpLines.push(helpLine) + }) + + helpLines = helpLines.filter((line) => line.relatedPoints?.length > 0) + + ridgeStartPoints.forEach((point) => { + // x 혹은 y가 같으면서 가장 가까운 점을 찾는다. + let arrivalPoint + let hipLine + let distance = Infinity + let startPoint + helpLines.forEach((line) => { + line.relatedPoints.forEach((relatedPoint) => { + if (Math.abs(point.x - relatedPoint.x) <= 2 || Math.abs(point.y - relatedPoint.y) <= 2) { + if (distanceBetweenPoints(point, relatedPoint) < distance) { + startPoint = point + distance = distanceBetweenPoints(point, relatedPoint) + hipLine = line + arrivalPoint = relatedPoint + } + } + }) + }) + + if (arrivalPoint) { + hipLine.relatedPoints.forEach((relatedPoint) => { + if (relatedPoint.x !== arrivalPoint.x && relatedPoint.y !== arrivalPoint.y) { + centerInterSectionPoints.splice(centerInterSectionPoints.indexOf(relatedPoint), 1) + } + }) + + helpLines.splice(helpLines.indexOf(hipLine), 1) + + const helpLine = new QLine([hipLine.x1, hipLine.y1, arrivalPoint.x, arrivalPoint.y], { + fontSize: polygon.fontSize, + stroke: 'red', + }) + const ridge = new QLine([startPoint.x, startPoint.y, arrivalPoint.x, arrivalPoint.y], { + stroke: 'green', + fontSize: polygon.fontSize, + }) + + polygon.canvas.add(helpLine) + polygon.canvas.add(ridge) + + polygon.canvas.renderAll() + ridgeEndPoints.push(arrivalPoint) + } + }) + + /** + * 안쓰는 점 제거 + */ + 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) + } + }) + }) + + // ridgeEndPoints와 가까운 centerInterSectionPoints를 찾아서 연결한다. + const remainingPoints = centerInterSectionPoints + const ridgeEndRemainingPoints = ridgeEndPoints + + helpLines.forEach((line) => { + remainingPoints.forEach((point) => { + if (line.relatedPoints.includes(point)) { + const hip = new QLine([line.x1, line.y1, point.x, point.y], { + stroke: 'red', + fontSize: polygon.fontSize, + }) + + polygon.canvas.add(hip) + polygon.canvas.renderAll() + } + }) + }) + + 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) { + const point = remainingPoints.shift() + const closestPoint = findClosestPoint(point, remainingPoints) + 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) => { + const centerLines = [] + + const oneSideLines = getOneSideLines(polygon) + + const horizontalLines = oneSideLines.filter((line) => line.direction === 'right') + const verticalLines = oneSideLines.filter((line) => line.direction === 'bottom') + // horizontalLines 를 y1 좌표 기준으로 정렬한다. + horizontalLines.sort((a, b) => a.y1 - b.y1) + // verticalLines 를 x1 좌표 기준으로 정렬한다. + verticalLines.sort((a, b) => a.x1 - b.x1) + + let maxHorizontalLineLength = 0 + let maxVerticalLineLength = 0 + // 모든 가로선의 중심선을 긋는다. + horizontalLines.forEach((line, index) => { + const nextLine = horizontalLines[(index + 1) % horizontalLines.length] + + line.line.set({ strokeWidth: 5 }) + nextLine.line.set({ strokeWidth: 5 }) + + polygon.canvas.renderAll() + + const startCenterX = Math.min(line.x1, nextLine.x1) + const startCenterY = (line.y1 + nextLine.y1) / 2 + + const endCenterX = line.x2 > nextLine.x2 ? line.x2 : nextLine.x2 + const endCenterY = startCenterY + + const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], { + fontSize: polygon.fontSize, + stroke: 'red', + strokeWidth: 1, + direction: 'horizontal', + }) + + centerLines.push(centerLine) + }) + + // 모든 세로선의 중심선을 긋는다. + verticalLines.forEach((line, index) => { + const nextLine = verticalLines[(index + 1) % verticalLines.length] + + const startCenterX = (line.x1 + nextLine.x1) / 2 + const startCenterY = Math.min(line.y1, nextLine.y1) + + const endCenterX = startCenterX + let endCenterY = line.y2 > nextLine.y2 ? line.y2 : nextLine.y2 + + const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], { + fontSize: polygon.fontSize, + stroke: 'blue', + strokeWidth: 1, + direction: 'vertical', + }) + + centerLines.push(centerLine) + }) + + return centerLines +} + +const getOneSideLines = (polygon) => { + return [...polygon.lines].map((line) => { let newX1, newY1, newX2, newY2 if (line.direction === 'top') { newX1 = line.x2 @@ -42,288 +333,4 @@ export const drawHelpLineInHexagon2 = (polygon, chon) => { } return line }) - - const centerLines = [] - const helpLines = [] - const ridgeStartPoints = [] - - const horizontalLines = oneSideLines.filter((line) => line.direction === 'right') - const verticalLines = oneSideLines.filter((line) => line.direction === 'bottom') - // horizontalLines 를 y1 좌표 기준으로 정렬한다. - horizontalLines.sort((a, b) => a.y1 - b.y1) - // verticalLines 를 x1 좌표 기준으로 정렬한다. - verticalLines.sort((a, b) => a.x1 - b.x1) - - const maxHorizontalLineLength = horizontalLines.reduce((prev, current) => (prev.length > current.length ? prev.length : current.length)) - const maxVerticalLineLength = verticalLines.reduce((prev, current) => (prev.length > current.length ? prev.length : current.length)) - - // 모든 가로선의 중심선을 긋는다. - horizontalLines.forEach((line, index) => { - const nextLine = horizontalLines[(index + 1) % horizontalLines.length] - - line.line.set({ strokeWidth: 5 }) - nextLine.line.set({ strokeWidth: 5 }) - - polygon.canvas.renderAll() - - const startCenterX = Math.min(line.x1, nextLine.x1) - const startCenterY = (line.y1 + nextLine.y1) / 2 - - const endCenterX = line.length >= nextLine.length ? startCenterX + line.length : startCenterX + nextLine.length - const endCenterY = startCenterY - - const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], { - fontSize: polygon.fontSize, - stroke: 'red', - strokeWidth: 1, - direction: 'horizontal', - }) - - /*polygon.canvas.add(centerLine) - polygon.canvas.renderAll()*/ - - centerLines.push(centerLine) - }) - - // 모든 세로선의 중심선을 긋는다. - verticalLines.forEach((line, index) => { - const nextLine = verticalLines[(index + 1) % verticalLines.length] - - const startCenterX = (line.x1 + nextLine.x1) / 2 - const startCenterY = Math.min(line.y1, nextLine.y1) - - const endCenterX = startCenterX - let endCenterY = line.length >= nextLine.length ? startCenterY + line.length : startCenterY + nextLine.length - - const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], { - fontSize: polygon.fontSize, - stroke: 'blue', - strokeWidth: 1, - direction: 'vertical', - }) - - /*polygon.canvas.add(centerLine) - polygon.canvas.renderAll()*/ - centerLines.push(centerLine) - }) - - polygon.points.forEach((point, index) => { - const wallPoint = polygon.wall.points[index] - // 두 점의 좌표 - const x1 = point.x - const y1 = point.y - const x2 = wallPoint.x - const y2 = wallPoint.y - - let newX2, newY2 - - // x1, y1을 기준으로 x2, y2와의 거리를 유지한 새로운 직선 생성 - const angle = Math.atan2(y2 - y1, x2 - x1) - - let previousIndex = index === 0 ? polygon.lines.length - 1 : index - 1 - const maxLength = Math.max(polygon.lines[index].length, polygon.lines[previousIndex].length) - - newX2 = Math.floor(x1 + (maxLength / 2 + polygon.points.length * 10) * Math.cos(angle)) - newY2 = Math.floor(y1 + (maxLength / 2 + polygon.points.length * 10) * Math.sin(angle)) - - const line = new QLine([x1, y1, newX2, newY2], { - fontSize: polygon.fontSize, - stroke: 'green', - idx: index, - }) - line.set({ degree: fabric.util.radiansToDegrees(angle) }) - polygon.canvas.add(line) - helpLines.push(line) - polygon.canvas.renderAll() - }) - - helpLines.forEach((line, index) => { - for (let i = index + 1; i < helpLines.length; i++) { - const nextLine = helpLines[i] - - if (line.isAlreadyInterSection || nextLine.isAlreadyInterSection) { - continue - } - - let intersectionPoint = calculateIntersection(line, nextLine) - - if (!intersectionPoint) { - continue - } - - const circle = new fabric.Circle({ - radius: 3, - fill: 'red', - left: intersectionPoint.x - 3, - top: intersectionPoint.y - 3, - }) - - polygon.canvas.add(circle) - - line.set({ isAlreadyInterSection: true }) - nextLine.set({ isAlreadyInterSection: true }) - - const helpLine1 = new QLine([nextLine.x1, nextLine.y1, intersectionPoint.x, intersectionPoint.y], { - fontSize: polygon.fontSize, - stroke: 'skyblue', - }) - - const helpLine2 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], { - fontSize: polygon.fontSize, - stroke: 'skyblue', - }) - - ridgeStartPoints.push(intersectionPoint) - polygon.canvas.add(helpLine1) - polygon.canvas.add(helpLine2) - polygon.canvas.remove(nextLine) - polygon.canvas.remove(line) - polygon.canvas.renderAll() - } - }) - - // 안만나는 선들 - const notInterSectionLines = helpLines.filter((line) => !line.isAlreadyInterSection) - const ridgeEndPoints = [] - let interSectionPoints = [] - - notInterSectionLines.forEach((line, index) => { - let subCenterLines - if (Math.abs(line.degree) < 90) { - subCenterLines = centerLines.filter((centerLine) => centerLine.direction === 'vertical') - } else { - subCenterLines = centerLines.filter((centerLine) => centerLine.direction === 'horizontal') - } - - centerLines.forEach((centerLine) => { - const interSectionPoint = calculateIntersection2(line, centerLine) - - if (!interSectionPoint) { - return - } - - ridgeStartPoints.forEach((point) => { - line.interSectionPoints.push(interSectionPoint) - interSectionPoints.push(interSectionPoint) - - const newLine = new QLine([line.x1, line.y1, interSectionPoint.x, interSectionPoint.y], { - stroke: 'black', - fontSize: polygon.fontSize, - }) - - const circle = new fabric.Circle({ - radius: 3, - fill: 'blue', - left: interSectionPoint.x - 3, - top: interSectionPoint.y - 3, - }) - polygon.canvas.add(circle) - polygon.canvas.add(newLine) - - polygon.canvas.remove(line) - - line.set({ isAlreadyInterSection: true }) - }) - }) - }) - - interSectionPoints = removeDuplicatePoints(interSectionPoints) - - const startRidgePoint = ridgeStartPoints[0] - - const endRidgePoint = ridgeStartPoints[ridgeStartPoints.length - 1] - - let step = 0 - - while (true) { - if (step % 2 === 0) { - const nextPoint = interSectionPoints.find((point) => point.x === startRidgePoint.x || point.y === startRidgePoint.y) - - if (nextPoint) { - const ridge = new QLine([startRidgePoint.x, startRidgePoint.y, nextPoint.x, nextPoint.y], { - stroke: 'green', - fontSize: polygon.fontSize, - }) - polygon.canvas.add(ridge) - polygon.canvas.renderAll() - } - - console.log('nextPoint', nextPoint) - console.log('startRidgePoint', startRidgePoint) - } else { - } - - step++ - - break - } - - /*ridgeStartPoints.forEach((point, index) => { - for (let i = index + 1; i < ridgeStartPoints.length; i++) { - const currentPoint = ridgeStartPoints[index] - const nextPoint = ridgeStartPoints[i] - - if (currentPoint.x === nextPoint.x || currentPoint.y === nextPoint.y) { - const ridge = new QLine([currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y], { - stroke: 'black', - fontSize: polygon.fontSize, - }) - polygon.canvas.add(ridge) - polygon.canvas.renderAll() - break - } - } - })*/ - - /*ridgeStartPoints.forEach((point, index) => { - let arrivalPoint - let distance = Infinity - let startPoint - interSectionPoints.forEach((interSectionPoint) => { - if (Math.abs(point.x - interSectionPoint.x) < 1 || Math.abs(point.y - interSectionPoint.y) < 1) { - if (distanceBetweenPoints(point, interSectionPoint) < distance) { - startPoint = point - distance = distanceBetweenPoints(point, interSectionPoint) - arrivalPoint = interSectionPoint - } - } - }) - - if (arrivalPoint) { - const line = notInterSectionLines.filter((line) => line.interSectionPoints.includes(arrivalPoint))[0] - - const ridge = new QLine([startPoint.x, startPoint.y, arrivalPoint.x, arrivalPoint.y], { - stroke: 'black', - fontSize: polygon.fontSize, - }) - - const helpLine = new QLine([line.x1, line.y1, arrivalPoint.x, arrivalPoint.y], { - stroke: 'red', - fontSize: polygon.fontSize, - }) - - ridgeEndPoints.push(arrivalPoint) - polygon.canvas.add(ridge) - polygon.canvas.add(helpLine) - // polygon.canvas.remove(line) - polygon.canvas.renderAll() - debugger - } - })*/ - - /*for (let i = 0; i < ridgeEndPoints.length; i = i + 2) { - const currentRidgeEndPoint = ridgeEndPoints[i] - const nextRidgeEndPoint = ridgeEndPoints[(i + 1) % ridgeEndPoints.length] - const ridgeConnectLine = new QLine([currentRidgeEndPoint.x, currentRidgeEndPoint.y, nextRidgeEndPoint.x, nextRidgeEndPoint.y], { - fontSize: polygon.fontSize, - stroke: 'green', - }) - - polygon.canvas.add(ridgeConnectLine) - polygon.canvas.renderAll() - }*/ -} - -export const drawHelpLineInHexagon = (polygon, chon) => { - // 가장 긴라인을 기준으로 centerLine을 그린다. }