From 71494d03693134e57e54ca0aad96e446dd14c436 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Wed, 31 Jul 2024 10:55:04 +0900 Subject: [PATCH] =?UTF-8?q?=EC=95=88=EC=93=B0=EB=8A=94=EA=B1=B0=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QLine2.js | 184 ------ src/components/fabric/QPolygon3.js | 941 ----------------------------- 2 files changed, 1125 deletions(-) delete mode 100644 src/components/fabric/QLine2.js delete mode 100644 src/components/fabric/QPolygon3.js diff --git a/src/components/fabric/QLine2.js b/src/components/fabric/QLine2.js deleted file mode 100644 index d75cff2c..00000000 --- a/src/components/fabric/QLine2.js +++ /dev/null @@ -1,184 +0,0 @@ -/** - * 문제 없는경우 제거 - */ -import { fabric } from 'fabric' -import { getDirection, getDirectionByPoint } from '@/util/canvas-util' - -export class QLine2 extends fabric.Group { - line - text - fontSize - length = 0 - x1 - y1 - x2 - y2 - direction - idx - type = 'QLine2' - parent - isAlreadyInterSection = false - - interSectionPoints = [] - lengthTxt = 0 - - initPoints - initOption - initLengthTxt - - constructor(points, option = { isActiveLengthText: true }, lengthTxt) { - // 소수점 전부 제거 - points.forEach((point) => { - point = Math.round(point) - }) - - const [x1, y1, x2, y2] = points - - if (!option.fontSize) { - throw new Error('Font size is required.') - } - - const line = new fabric.Line(points, { ...option, strokeWidth: 1 }) - - // 길이가 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 - - if (lengthTxt > 0) { - this.lengthTxt = Number(lengthTxt) - } - - option.isActiveLengthText ?? this.init() - this.addControl() - } - } - - init() { - this.addLengthText(true) - } - - addControl() { - this.on('moving', () => { - this.addLengthText(false) - }) - - this.on('modified', (e) => { - this.addLengthText(false) - }) - - this.on('selected', () => { - console.log(this) - Object.keys(this.controls).forEach((controlKey) => { - if (controlKey !== 'ml' && controlKey !== 'mr') { - this.setControlVisible(controlKey, false) - } - }) - }) - } - - static fromObject(object, callback) { - const { points, initOption, initLengthTxt } = object - const instance = new QLine(points, initOption, initLengthTxt) - callback && callback(instance) - return instance - } - - addLengthText(isFirst) { - if (this.text) { - this.removeWithUpdate(this.text) - this.text = null - } - - if (isFirst && this.lengthTxt > 0) { - const text = new fabric.Textbox(this.lengthTxt.toFixed(0).toString(), { - left: (this.x1 + this.x2) / 2, - top: (this.y1 + this.y2) / 2, - fontSize: this.fontSize, - }) - this.length = this.lengthTxt - this.text = text - this.addWithUpdate(text) - return - } - - const scaleX = this.scaleX - const scaleY = this.scaleY - const x1 = this.left - const y1 = this.top - const x2 = this.left + this.width * scaleX - const y2 = this.top + this.height * scaleY - const dx = x2 - x1 - const dy = y2 - y1 - this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) - - const text = new fabric.Textbox(this.length.toFixed(0).toString(), { - left: (x1 + x2) / 2, - top: (y1 + y2) / 2, - fontSize: this.fontSize, - }) - this.text = text - this.addWithUpdate(text) - } - - setFontSize(fontSize) { - this.fontSize = fontSize - this.text.set({ fontSize }) - this.addWithUpdate() - } - - fromObject(object, callback) { - console.log('fromObject', object, callback) - } - - async = true - - toObject(propertiesToInclude) { - return fabric.util.object.extend(this.callSuper('toObject'), { - length: this.length, - line: this.line, - text: this.text, - fontSize: this.fontSize, - x1: this.x1, - y1: this.y1, - x2: this.x2, - y2: this.y2, - direction: this.direction, - idx: this.idx, - type: this.type, - parent: this.parent, - isAlreadyInterSection: this.isAlreadyInterSection, - interSectionPoints: this.interSectionPoints, - lengthTxt: this.lengthTxt, - setFontSize: this.setFontSize, - addLengthText: this.addLengthText, - init: this.init, - addControl: this.addControl, - initPoints: this.initPoints, - initOption: this.initOption, - initLengthTxt: this.initLengthTxt, - points: this.points, - }) - } - - _set(key, value) { - this.callSuper('_set', key, value) - } -} diff --git a/src/components/fabric/QPolygon3.js b/src/components/fabric/QPolygon3.js deleted file mode 100644 index b3770831..00000000 --- a/src/components/fabric/QPolygon3.js +++ /dev/null @@ -1,941 +0,0 @@ -/** - * 문제 없는경우 제거 - */ - -import { fabric } from 'fabric' -import { - calculateIntersection, - calculateIntersection2, - distanceBetweenPoints, - findClosestLineToPoint, - findTopTwoIndexesByDistance, - getDegreeByChon, - getDirectionByPoint, - getRoofHeight, - getRoofHypotenuse, - sortedPoints, -} from '@/util/canvas-util' -import { QLine } from '@/components/fabric/QLine' -import { drawHelpLineInHexagon } from '@/util/qpolygon-utils' - -export default class QPolygon3 extends fabric.Group { - type = 'QPolygon3' - polygon - points - texts = [] - lines = [] - canvas - fontSize - qCells = [] - name - shape = 0 // 점 6개일때의 shape 모양 - helpPoints = [] - helpLines = [] - - wall - - initPoints - initOption - - constructor(points, options, canvas) { - /*if (points.length !== 4 && points.length !== 6) { - throw new Error('Points must be 4 or 6.') - }*/ - if (!options.fontSize) { - throw new Error('Font size is required.') - } - - // 소수점 전부 제거 - points.forEach((point) => { - point.x = Math.round(point.x) - point.y = Math.round(point.y) - }) - - const sortPoints = sortedPoints(points) - const polygon = new fabric.Polygon(sortPoints, options) - - super([polygon], {}) - - this.fontSize = options.fontSize - this.points = sortPoints - this.polygon = polygon - this.name = options.name - - this.initPoints = points - this.initOption = options - - this.init() - this.addEvent() - this.initLines() - this.setShape() - } - - initLines() { - this.points.forEach((point, i) => { - const nextPoint = this.points[(i + 1) % this.points.length] - const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], { - stroke: this.stroke, - strokeWidth: this.strokeWidth, - fontSize: this.fontSize, - idx: i, - direction: getDirectionByPoint(point, nextPoint), - }) - - this.lines.push(line) - }) - } - - init() { - this.addLengthText() - } - - addEvent() { - this.on('scaling', (e) => { - this.updateLengthText() - }) - - this.on('selected', function () { - // 모든 컨트롤 떼기 - - Object.keys(this.controls).forEach((controlKey) => { - if (controlKey !== 'mtr') { - this.setControlVisible(controlKey, false) - } - }) - }) - } - - setWall(wall) { - this.wall = wall - } - - setFontSize(fontSize) { - this.fontSize = fontSize - this.texts.forEach((text) => { - text.set({ fontSize }) - }) - - this.getObjects().forEach((obj) => { - if (obj.type[0] === 'Q') { - obj.setFontSize(fontSize) - } - }) - - this.canvas.add() - } - - addLengthText() { - if (this.texts.length > 0) { - this.texts.forEach((text) => { - this.canvas.remove(text) - }) - this.texts = [] - } - const points = this.points - - points.forEach((start, i) => { - const end = points[(i + 1) % points.length] - const dx = end.x - start.x - const dy = end.y - start.y - const length = Math.sqrt(dx * dx + dy * dy) - - const midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2) - - // Create new text object if it doesn't exist - const text = new fabric.Text(length.toFixed(0), { - left: midPoint.x, - top: midPoint.y, - fontSize: this.fontSize, - selectable: false, - }) - - this.texts.push(text) - this.canvas.add(text) - }) - - this.canvas.renderAll() - } - - updateLengthText() { - const points = this.getCurrentPoints() - - points.forEach((start, i) => { - const end = points[(i + 1) % points.length] - const dx = end.x - start.x - const dy = end.y - start.y - const length = Math.sqrt(dx * dx + dy * dy) - - // Update the text object with the new length - this.texts[i].set({ text: length.toFixed(0) }) - }) - - this.canvas.renderAll() - } - - fillCell(cell = { width: 50, height: 100, padding: 10 }) { - const points = this.getCurrentPoints() - let bounds - - try { - bounds = fabric.util.makeBoundingBoxFromPoints(points) - } catch (error) { - alert('다각형의 꼭지점이 4개 이상이어야 합니다.') - return - } - - for (let x = bounds.left; x < bounds.left + bounds.width; x += cell.width + cell.padding) { - for (let y = bounds.top; y < bounds.top + bounds.height; y += cell.height + cell.padding) { - const rect = new fabric.Rect({ - left: x, - top: y, - width: cell.width, - height: cell.height, - fill: 'transparent', - stroke: 'black', - selectable: false, - }) - - const rectPoints = [ - new fabric.Point(rect.left, rect.top), - new fabric.Point(rect.left + rect.width, rect.top), - new fabric.Point(rect.left, rect.top + rect.height), - new fabric.Point(rect.left + rect.width, rect.top + rect.height), - ] - - const isInside = rectPoints.every((rectPoint) => this.inPolygon(rectPoint) && this.distanceFromEdge(rectPoint) >= cell.padding) - - if (isInside) { - this.canvas.add(rect) - } - } - } - - this.canvas.renderAll() - } - - /** - * this.lines의 direction이 top 인 line의 모든 합이 bottom 인 line의 모든 합과 같은지 확인 - * this.lines의 direction이 left 인 line의 모든 합이 right 인 line의 모든 합과 같은지 확인 - * return {boolean} - */ - isValid() { - const leftLinesLengthSum = this.lines.filter((line) => line.direction === 'left').reduce((sum, line) => sum + line.length, 0) - const rightLinesLengthSum = this.lines.filter((line) => line.direction === 'right').reduce((sum, line) => sum + line.length, 0) - - const topLinesLengthSum = this.lines.filter((line) => line.direction === 'top').reduce((sum, line) => sum + line.length, 0) - const bottomLinesLengthSum = this.lines.filter((line) => line.direction === 'bottom').reduce((sum, line) => sum + line.length, 0) - - return leftLinesLengthSum === rightLinesLengthSum && topLinesLengthSum === bottomLinesLengthSum - } - - inPolygon(point) { - const vertices = this.getCurrentPoints() - let intersects = 0 - - for (let i = 0; i < vertices.length; i++) { - let vertex1 = vertices[i] - let vertex2 = vertices[(i + 1) % vertices.length] - - if (vertex1.y > vertex2.y) { - let tmp = vertex1 - vertex1 = vertex2 - vertex2 = tmp - } - - if (point.y === vertex1.y || point.y === vertex2.y) { - point.y += 0.01 - } - - if (point.y <= vertex1.y || point.y > vertex2.y) { - continue - } - - let xInt = ((point.y - vertex1.y) * (vertex2.x - vertex1.x)) / (vertex2.y - vertex1.y) + vertex1.x - if (xInt < point.x) { - intersects++ - } - } - - return intersects % 2 === 1 - } - - distanceFromEdge(point) { - const vertices = this.getCurrentPoints() - let minDistance = Infinity - - for (let i = 0; i < vertices.length; i++) { - let vertex1 = vertices[i] - let vertex2 = vertices[(i + 1) % vertices.length] - - const dx = vertex2.x - vertex1.x - const dy = vertex2.y - vertex1.y - - const t = ((point.x - vertex1.x) * dx + (point.y - vertex1.y) * dy) / (dx * dx + dy * dy) - - let closestPoint - if (t < 0) { - closestPoint = vertex1 - } else if (t > 1) { - closestPoint = vertex2 - } else { - closestPoint = new fabric.Point(vertex1.x + t * dx, vertex1.y + t * dy) - } - - const distance = distanceBetweenPoints(point, closestPoint) - if (distance < minDistance) { - minDistance = distance - } - } - - return minDistance - } - - setViewLengthText(boolean) { - this.texts.forEach((text) => { - text.visible = boolean - }) - - this.canvas.renderAll() - } - - getCurrentPoints() { - const scaleX = this.scaleX - const scaleY = this.scaleY - - const left = this.left - const top = this.top - - // 시작점 - const point = this.points[0] - - const movingX = left - point.x * scaleX - const movingY = top - point.y * scaleY - - return this.points.map((point) => { - return { - x: point.x * scaleX + movingX, - y: point.y * scaleY + movingY, - } - }) - } - - fillBackground(pattern) { - this.polygon.set({ fill: pattern }) - this.canvas.requestRenderAll() - } - - // 보조선 그리기 - drawHelpLine(chon = 4) { - drawHelpLineInHexagon(this, chon) - /*if (!this.isValid()) { - return - }*/ - - /*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) { - // TODO : 8각형 - this.drawHelpLineInOctagon(chon) - }*!/*/ - } - - /** - * 현재 점 6개만 가능 - */ - setShape() { - let shape = 0 - if (this.lines.length !== 6) { - return - } - //외각선 기준 - const topIndex = findTopTwoIndexesByDistance(this.lines).sort((a, b) => a - b) //배열중에 큰 2값을 가져옴 TODO: 나중에는 인자로 받아서 다각으로 수정 해야됨 - - //일단 배열 6개 짜리 기준의 선 번호 - if (topIndex[0] === 4) { - if (topIndex[1] === 5) { - //1번 - shape = 1 - } - } else if (topIndex[0] === 1) { - //4번 - if (topIndex[1] === 2) { - shape = 4 - } - } else if (topIndex[0] === 0) { - if (topIndex[1] === 1) { - //2번 - shape = 2 - } else if (topIndex[1] === 5) { - //3번 - shape = 3 - } - } - - this.shape = shape - } - - /** - * 현재 점 6개만 가능 - * @returns {number} - */ - getShape() { - return this.shape - } - - drawHelpLineInRect(chon) { - let type = 1 - let smallestLength = Infinity - let maxLength = 0 - - this.lines.forEach((line) => { - if (line.length < smallestLength) { - smallestLength = line.length - } - if (line.length > maxLength) { - maxLength = line.length - } - }) - - // QPolygon 객체의 모든 선들을 가져옵니다. - const lines = [...this.lines] - - // 이 선들을 길이에 따라 정렬합니다. - lines.sort((a, b) => a.length - b.length) - - // 정렬된 배열에서 가장 작은 두 선을 선택합니다. - let smallestLines - - if (smallestLength === maxLength) { - // 정사각형인 경우 0, 2번째 라인이 가장 짧은 라인 - - smallestLines = [lines[0], lines[2]] - } else { - smallestLines = lines.slice(0, 2) - } - - let needPlusLine - let needMinusLine - - const direction = smallestLines[0].direction - - if (direction === 'top' || direction === 'bottom') { - needPlusLine = smallestLines[0].x1 < smallestLines[1].x1 ? smallestLines[0] : smallestLines[1] - needMinusLine = needPlusLine === smallestLines[0] ? smallestLines[1] : smallestLines[0] - - type = 1 // 가로가 긴 사각형 - } - - if (direction === 'left' || direction === 'right') { - needPlusLine = smallestLines[0].y1 < smallestLines[1].y1 ? smallestLines[0] : smallestLines[1] - needMinusLine = needPlusLine === smallestLines[0] ? smallestLines[1] : smallestLines[0] - - type = 2 // 세로가 긴 사각형 - } - - let point1 - let point2 - - if (type === 1) { - point1 = { - x: needPlusLine.x1 + smallestLength / 2, - y: needPlusLine.y1 > needPlusLine.y2 ? needPlusLine.y1 - smallestLength / 2 : needPlusLine.y2 - smallestLength / 2, - } - - point2 = { - x: needMinusLine.x1 - smallestLength / 2, - y: needMinusLine.y1 > needMinusLine.y2 ? needMinusLine.y1 - smallestLength / 2 : needMinusLine.y2 - smallestLength / 2, - } - } else if (type === 2) { - point1 = { - x: needPlusLine.x1 > needPlusLine.x2 ? needPlusLine.x1 - smallestLength / 2 : needPlusLine.x2 - smallestLength / 2, - y: needPlusLine.y1 + smallestLength / 2, - } - - point2 = { - x: needMinusLine.x1 > needMinusLine.x2 ? needMinusLine.x1 - smallestLength / 2 : needMinusLine.x2 - smallestLength / 2, - y: needMinusLine.y1 - smallestLength / 2, - } - } - - // 빗변1 - const realLine1 = new QLine( - [needPlusLine.x1, needPlusLine.y1, point1.x, point1.y], - { fontSize: this.fontSize, stroke: 'black', strokeWidth: 1 }, - getRoofHypotenuse(smallestLength / 2), - ) - - // 빗변2 - const realLine2 = new QLine( - [needPlusLine.x2, needPlusLine.y2, point1.x, point1.y], - { fontSize: this.fontSize, stroke: 'black', strokeWidth: 1 }, - getRoofHypotenuse(smallestLength / 2), - ) - - // 빗변3 - const realLine3 = new QLine( - [needMinusLine.x1, needMinusLine.y1, point2.x, point2.y], - { fontSize: this.fontSize, stroke: 'black', strokeWidth: 1 }, - getRoofHypotenuse(smallestLength / 2), - ) - - // 빗변4 - const realLine4 = new QLine( - [needMinusLine.x2, needMinusLine.y2, point2.x, point2.y], - { fontSize: this.fontSize, stroke: 'black', strokeWidth: 1 }, - getRoofHypotenuse(smallestLength / 2), - ) - - let centerPoint1 - let centerPoint2 - - if (type === 1) { - centerPoint1 = { x: point1.x - smallestLength / 2, y: point1.y } - centerPoint2 = { x: point2.x + smallestLength / 2, y: point2.y } - } else if (type === 2) { - centerPoint1 = { x: point1.x, y: point1.y - smallestLength / 2 } - centerPoint2 = { x: point2.x, y: point2.y + smallestLength / 2 } - } - - // 옆으로 누워있는 지붕의 높이 - const realLine5 = new QLine( - [point1.x, point1.y, centerPoint1.x, centerPoint1.y], - { - fontSize: this.fontSize, - stroke: 'black', - strokeWidth: 1, - strokeDashArray: [5, 5], - }, - getRoofHeight(smallestLength / 2, getDegreeByChon(chon)), - ) - - // 옆으로 누워있는 지붕의 높이 - const realLine6 = new QLine( - [point2.x, point2.y, centerPoint2.x, centerPoint2.y], - { - fontSize: this.fontSize, - stroke: 'black', - strokeWidth: 1, - strokeDashArray: [5, 5], - }, - getRoofHeight(smallestLength / 2, getDegreeByChon(chon)), - ) - - // 용마루 - const ridge = new QLine([point1.x, point1.y, point2.x, point2.y], { - fontSize: this.fontSize, - stroke: 'black', - strokeWidth: 1, - }) - - this.canvas.add(realLine1) - this.canvas.add(realLine2) - this.canvas.add(realLine3) - this.canvas.add(realLine4) - this.canvas.add(realLine5) - this.canvas.add(realLine6) - if (smallestLength !== maxLength) { - // 정사각형이 아닌경우에만 용마루를 추가한다. - this.canvas.add(ridge) - } - } - drawHelpLineInHexagon2(chon) { - const oneSideLines = [...this.lines].map((line) => { - let newX1, newY1, newX2, newY2 - if (line.direction === 'top') { - newX1 = line.x2 - newY1 = line.y2 - newX2 = line.x1 - newY2 = line.y1 - - line.x1 = newX1 - line.y1 = newY1 - line.x2 = newX2 - line.y2 = newY2 - line.direction = 'bottom' - } else if (line.direction === 'left') { - newX1 = line.x2 - newY1 = line.y2 - newX2 = line.x1 - newY2 = line.y1 - - line.x1 = newX1 - line.y1 = newY1 - line.x2 = newX2 - line.y2 = newY2 - line.direction = 'right' - } - return line - }) - - const centerLines = [] - const helpLines = [] - const ridgeStartPoints = [] - - const horizontalLines = oneSideLines.filter((line) => line.direction === 'right') - const verticalLines = oneSideLines.filter((line) => line.direction === 'bottom') - - const horizontalMaxLength = horizontalLines.reduce((max, obj) => Math.max(max, obj.length), 0) - const verticalMaxLength = verticalLines.reduce((max, obj) => Math.max(max, obj.length), 0) - // 모든 가로선의 중심선을 긋는다. - horizontalLines.forEach((line, index) => { - const nextLine = horizontalLines[(index + 1) % horizontalLines.length] - - const startCenterX = Math.max(line.x1, nextLine.x1) - const startCenterY = (line.y1 + nextLine.y1) / 2 - - let endCenterX = line.length >= nextLine.length ? startCenterX + line.length : startCenterX + nextLine.length - const endCenterY = startCenterY - - if (endCenterX > Math.max(line.x2, nextLine.x2)) { - endCenterX = Math.max(line.x2, nextLine.x2) - } - - const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], { - fontSize: this.fontSize, - stroke: 'red', - strokeWidth: 1, - direction: 'horizontal', - }) - - // this.addWithUpdate(centerLine) - - 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 - - if (endCenterY > Math.max(line.y2, nextLine.y2)) { - endCenterY = Math.max(line.y2, nextLine.y2) - } - - const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], { - fontSize: this.fontSize, - stroke: 'blue', - strokeWidth: 1, - direction: 'vertical', - }) - // this.addWithUpdate(centerLine) - - centerLines.push(centerLine) - }) - - const maxLength = horizontalMaxLength < verticalMaxLength ? horizontalMaxLength : verticalMaxLength - - this.points.forEach((point, index) => { - const wallPoint = this.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) - - newX2 = Math.floor(x1 + (maxLength / 2 + 50) * Math.cos(angle)) - newY2 = Math.floor(y1 + (maxLength / 2 + 50) * Math.sin(angle)) - - const line = new QLine([x1, y1, newX2, newY2], { - fontSize: this.fontSize, - stroke: 'green', - idx: index, - }) - this.addWithUpdate(line) - helpLines.push(line) - this.canvas.renderAll() - }) - - helpLines.forEach((line, index) => { - if (line.isAlreadyInterSection) { - return - } - const nextLine = helpLines[(index + 1 + helpLines.length) % helpLines.length] - this.canvas.renderAll() - - let intersectionPoint = calculateIntersection(line, nextLine) - if (!intersectionPoint) { - return - } - - line.set({ isAlreadyInterSection: true }) - nextLine.set({ isAlreadyInterSection: true }) - - const helpLine1 = new QLine([nextLine.x1, nextLine.y1, intersectionPoint.x, intersectionPoint.y], { - fontSize: this.fontSize, - stroke: 'skyblue', - }) - - const helpLine2 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], { - fontSize: this.fontSize, - stroke: 'skyblue', - }) - - ridgeStartPoints.push(intersectionPoint) - this.addWithUpdate(helpLine1) - this.addWithUpdate(helpLine2) - this.removeWithUpdate(nextLine) - this.removeWithUpdate(line) - this.canvas.renderAll() - }) - - // 안만나는 선들 - const notInterSectionLines = helpLines.filter((line) => !line.isAlreadyInterSection) - const ridgeEndPoints = [] - const interSectionPoints = [] - - notInterSectionLines.forEach((line, index) => { - line.line.set({ strokeWidth: (index + 1) * 5 }) - - centerLines.forEach((centerLine) => { - const interSectionPoint = calculateIntersection2(line, centerLine) - - if (!this.inPolygon(interSectionPoint) || !interSectionPoint) { - return - } - line.interSectionPoints.push(interSectionPoint) - interSectionPoints.push(interSectionPoint) - }) - }) - - ridgeStartPoints.forEach((point, index) => { - let arrivalPoint - let distance = Infinity - let startPoint - interSectionPoints.forEach((interSectionPoint) => { - if (Math.abs(point.x - interSectionPoint.x) < 3 || Math.abs(point.y - interSectionPoint.y) < 3) { - 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: this.fontSize, - }) - - const helpLine = new QLine([line.x1, line.y1, arrivalPoint.x, arrivalPoint.y], { - stroke: 'red', - fontSize: this.fontSize, - }) - - ridgeEndPoints.push(arrivalPoint) - this.addWithUpdate(ridge) - this.addWithUpdate(helpLine) - this.removeWithUpdate(line) - this.canvas.renderAll() - } - }) - - ridgeEndPoints.forEach((point, index) => { - const currentRidgeEndPoint = ridgeEndPoints[index] - const nextRidgeEndPoint = ridgeEndPoints[(index + 1) % ridgeEndPoints.length] - const ridgeConnectLine = new QLine([currentRidgeEndPoint.x, currentRidgeEndPoint.y, nextRidgeEndPoint.x, nextRidgeEndPoint.y], { - fontSize: this.fontSize, - stroke: 'green', - }) - - this.addWithUpdate(ridgeConnectLine) - this.canvas.renderAll() - }) - } - drawHelpLineInHexagon(chon) { - const historyLines = [] - const helpPoints = [] - const notInterSectionLines = [] - const ridge = [] - const maxLength = this.lines.reduce((max, obj) => Math.max(max, obj.length), 0) - this.points.forEach((point, index) => { - const wallPoint = this.wall.points[index] - // 두 점의 좌표 - const x1 = point.x - const y1 = point.y - const x2 = wallPoint.x - const y2 = wallPoint.y - const historyLines = [] - const helpPoints = [] - const notInterSectionLines = [] - const ridge = [] - const maxLength = this.lines.reduce((max, obj) => Math.max(max, obj.length), 0) - this.points.forEach((point, index) => { - const wallPoint = this.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) - - newX2 = x1 + (maxLength / 2) * Math.cos(angle) - newY2 = y1 + (maxLength / 2) * Math.sin(angle) - - const line = new QLine([x1, y1, newX2, newY2], { - fontSize: this.fontSize, - stroke: 'blue', - idx: index, - }) - historyLines.push(line) - this.canvas.add(line) - - this.canvas.renderAll() - }) - - /** - * 삼각 지붕 - */ - historyLines.forEach((line, index) => { - const prevLine = historyLines[(index - 1 + historyLines.length) % historyLines.length] - - let intersectionPoint = calculateIntersection(line, prevLine) - - if (!intersectionPoint) { - notInterSectionLines.push(line) - return - } - - const helpLine1 = new QLine([prevLine.x1, prevLine.y1, intersectionPoint.x, intersectionPoint.y], { - fontSize: this.fontSize, - stroke: 'red', - }) - - const helpLine2 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], { - fontSize: this.fontSize, - stroke: 'red', - }) - notInterSectionLines.pop() - helpPoints.push(intersectionPoint) - - this.canvas.add(helpLine1) - this.canvas.add(helpLine2) - this.canvas.remove(prevLine) - this.canvas.remove(line) - this.canvas.renderAll() - }) - // 용마루 - - const ridgePoint = [] - - helpPoints.forEach((helpPoint, index) => { - const closestLine = findClosestLineToPoint(helpPoint, notInterSectionLines) - - // 가까운 선의 중심점 - const centerClosestLinePoint = { - x: (closestLine.x1 + closestLine.x2) / 2, - y: (closestLine.y1 + closestLine.y2) / 2, - } - - const direction = getDirectionByPoint(helpPoint, centerClosestLinePoint) - - let newX, newY - - switch (direction) { - case 'left': { - newX = ((closestLine.x2 - closestLine.x1) * (helpPoint.y - closestLine.y1)) / (closestLine.y2 - closestLine.y1) + closestLine.x1 - newY = helpPoint.y - break - } - case 'right': { - newX = ((closestLine.x2 - closestLine.x1) * (helpPoint.y - closestLine.y1)) / (closestLine.y2 - closestLine.y1) + closestLine.x1 - newY = helpPoint.y - break - } - case 'top': { - newX = helpPoint.x - newY = ((closestLine.y2 - closestLine.y1) * (helpPoint.x - closestLine.x1)) / (closestLine.x2 - closestLine.x1) + closestLine.y1 - break - } - case 'bottom': { - newX = helpPoint.x - newY = ((closestLine.y2 - closestLine.y1) * (helpPoint.x - closestLine.x1)) / (closestLine.x2 - closestLine.x1) + closestLine.y1 - break - } - } - - const ridgeHelpLine = new QLine([closestLine.x1, closestLine.y1, newX, newY], { - fontSize: this.fontSize, - stroke: 'purple', - strokeWidth: 5, - }) - - ridgePoint.push({ x: newX, y: newY }) - - const ridge = new QLine([helpPoint.x, helpPoint.y, newX, newY], { - fontSize: this.fontSize, - stroke: 'skyblue', - strokeWidth: 5, - }) - - this.canvas.add(ridge) - this.canvas.renderAll() - - this.canvas.add(ridgeHelpLine) - this.canvas.remove(closestLine) - this.canvas.renderAll() - }) - - // 용마루 끼리 연결 - for (let i = 0; i < ridgePoint.length; i = i + 2) { - const currentRidgeEndPoint = ridgePoint[i] - const nextRidgeEndPoint = ridgePoint[(i + 1) % ridgePoint.length] - const ridgeConnectLine = new QLine([currentRidgeEndPoint.x, currentRidgeEndPoint.y, nextRidgeEndPoint.x, nextRidgeEndPoint.y], { - fontSize: this.fontSize, - stroke: 'green', - strokeWidth: 5, - }) - this.canvas.add(ridgeConnectLine) - this.canvas.renderAll() - } - - this.canvas.renderAll() - }) - } - - drawHelpLineInOctagon(chon) {} - - getObject() { - return this - } - sou - - toObject(propertiesToInclude) { - return fabric.util.object.extend(this.callSuper('toObject'), { - points: this.points, - fontSize: this.fontSize, - name: this.name, - shape: this.shape, - texts: this.texts, - lines: this.lines, - wall: this.wall, - initPoints: this.initPoints, - initOption: this.initOption, - objects: this.getObjects().map((obj) => obj.toObject(propertiesToInclude)), - pattern: this.pattern, - }) - } - - _set(key, value) { - this.callSuper('_set', key, value) - } -}