polygon 나누는 함수 수정
This commit is contained in:
parent
69568966ba
commit
46ecb8fdee
@ -2,7 +2,7 @@ import { fabric } from 'fabric'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
|
||||
import { calculateAngle, dividePolygon, drawHelpLineInHexagon } from '@/util/qpolygon-utils'
|
||||
import { calculateAngle, dividePolygon, drawHelpLineInHexagon, splitPolygonWithLines } from '@/util/qpolygon-utils'
|
||||
|
||||
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
type: 'QPolygon',
|
||||
@ -450,6 +450,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
})
|
||||
},
|
||||
divideLine() {
|
||||
dividePolygon(this)
|
||||
splitPolygonWithLines(this)
|
||||
},
|
||||
})
|
||||
|
||||
@ -2,6 +2,7 @@ import { fabric } from 'fabric'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { calculateIntersection, distanceBetweenPoints, findClosestPoint, getDirectionByPoint } from '@/util/canvas-util'
|
||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||
import polygonSplitter from 'polygon-splitter'
|
||||
|
||||
const TWO_PI = Math.PI * 2
|
||||
|
||||
@ -954,3 +955,127 @@ export default function offsetPolygon(vertices, offset) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const splitPolygonWithLines = (polygon) => {
|
||||
//todo: polygon의 모든 line들 모음 hip, ridge, connectRidge
|
||||
const allLines = [...polygon.hips, ...polygon.ridges, ...polygon.connectRidges]
|
||||
|
||||
polygon.points.forEach((point, index) => {
|
||||
allLines.forEach((line) => {
|
||||
if (line.endPoint.x === point.x && line.endPoint.y === point.y) {
|
||||
const temp = line.startPoint
|
||||
line.startPoint = line.endPoint
|
||||
line.endPoint = temp
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
polygon.points.forEach((point, index) => {
|
||||
const routes = []
|
||||
|
||||
const polygonPoints = [...polygon.points].map((point, index) => {
|
||||
return { ...point, index }
|
||||
})
|
||||
|
||||
// 시작점은 시작 hip라인의 출발점
|
||||
const startPoint = point
|
||||
// 도착점은 마지막 hip라인의 끝나는 점
|
||||
const endPoint = polygon.points[(index + 1) % polygon.points.length]
|
||||
|
||||
const startLine = allLines.find((line) => line.startPoint.x === startPoint.x && line.startPoint.y === startPoint.y)
|
||||
const endLine = allLines.find((line) => line.startPoint.x === endPoint.x && line.startPoint.y === endPoint.y)
|
||||
|
||||
const arrivalPoint = endLine.endPoint
|
||||
routes.push(startLine.startPoint)
|
||||
routes.push(startLine.endPoint)
|
||||
//hip끼리 만나는 경우는 아무것도 안해도됨
|
||||
if (!isSamePoint(startLine.endPoint, arrivalPoint)) {
|
||||
// polygon line까지 추가
|
||||
const allLinesCopy = [...allLines, ...polygon.lines]
|
||||
// hip이 만나지 않는 경우 갈 수 있는 길을 다 돌아야함
|
||||
let currentPoint = startLine.endPoint
|
||||
let currentLine = startLine
|
||||
|
||||
while (!isSamePoint(currentPoint, arrivalPoint)) {
|
||||
// startHip에서 만나는 출발선 두개. 두개의 선을 출발하여 arrivalPoint에 도착할 때 까지 count를 세고, 더 낮은 count를 가진 길을 선택한다.
|
||||
let connectedLines = allLinesCopy.filter(
|
||||
(line) => isSamePoint(line.startPoint, currentPoint) || (isSamePoint(line.endPoint, currentPoint) && line !== currentLine),
|
||||
)
|
||||
|
||||
if (connectedLines.length === 0) {
|
||||
throw new Error('connectedLines is empty')
|
||||
}
|
||||
|
||||
let tempPoints = []
|
||||
|
||||
for (let i = 0; i < connectedLines.length; i++) {
|
||||
if (isSamePoint(connectedLines[i].startPoint, currentPoint)) {
|
||||
tempPoints.push({ point: connectedLines[i].endPoint, index: i, line: connectedLines[i] })
|
||||
} else {
|
||||
tempPoints.push({ point: connectedLines[i].startPoint, index: i, line: connectedLines[i] })
|
||||
}
|
||||
}
|
||||
|
||||
//tempPoints에서 arrivalPoint와 가장 가까운 점을 찾는다.
|
||||
let minDistance = Number.MAX_SAFE_INTEGER
|
||||
let minIndex = 0
|
||||
tempPoints.forEach((tempPoint, index) => {
|
||||
const distance = Math.sqrt(Math.pow(tempPoint.point.x - arrivalPoint.x, 2) + Math.pow(tempPoint.point.y - arrivalPoint.y, 2))
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance
|
||||
minIndex = tempPoint.index
|
||||
}
|
||||
})
|
||||
|
||||
currentPoint = tempPoints[minIndex].point
|
||||
currentLine = tempPoints[minIndex].line
|
||||
routes.push(currentPoint)
|
||||
}
|
||||
}
|
||||
|
||||
routes.push(endLine.startPoint)
|
||||
const roof = new QPolygon(routes, {
|
||||
fontSize: polygon.fontSize,
|
||||
stroke: 'black',
|
||||
fill: 'transparent',
|
||||
strokeWidth: 3,
|
||||
name: 'roof',
|
||||
})
|
||||
|
||||
polygon.canvas.add(roof)
|
||||
polygon.canvas.renderAll()
|
||||
})
|
||||
}
|
||||
|
||||
const isSamePoint = (a, b) => {
|
||||
return a.x === b.x && a.y === b.y
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the angle between two lines.
|
||||
* @param {Object} line1 - The first line defined by two points {x1, y1} and {x2, y2}.
|
||||
* @param {Object} line2 - The second line defined by two points {x1, y1} and {x2, y2}.
|
||||
* @returns {number} - The angle between the two lines in degrees.
|
||||
*/
|
||||
function calculateAngleBetweenLines(line1, line2) {
|
||||
const { x1: x1_1, y1: y1_1, x2: x2_1, y2: y2_1 } = line1
|
||||
const { x1: x1_2, y1: y1_2, x2: x2_2, y2: y2_2 } = line2
|
||||
|
||||
// Calculate direction vectors
|
||||
const vector1 = { x: x2_1 - x1_1, y: y2_1 - y1_1 }
|
||||
const vector2 = { x: x2_2 - x1_2, y: y2_2 - y1_2 }
|
||||
|
||||
// Calculate dot product and magnitudes
|
||||
const dotProduct = vector1.x * vector2.x + vector1.y * vector2.y
|
||||
const magnitude1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y)
|
||||
const magnitude2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y)
|
||||
|
||||
// Calculate the cosine of the angle
|
||||
const cosTheta = dotProduct / (magnitude1 * magnitude2)
|
||||
|
||||
// Calculate the angle in radians and then convert to degrees
|
||||
const angleInRadians = Math.acos(cosTheta)
|
||||
const angleInDegrees = (angleInRadians * 180) / Math.PI
|
||||
|
||||
return angleInDegrees
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user