Merge branch 'feature/test' into test-yj

This commit is contained in:
yjnoh 2024-07-31 09:47:40 +09:00
commit 6bf0a934c2
2 changed files with 82 additions and 137 deletions

View File

@ -126,16 +126,20 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
points.forEach((start, i) => { points.forEach((start, i) => {
const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id && obj.idx === i) const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id && obj.idx === i)
if (thisText) {
thisText.set({ left: (start.x + points[(i + 1) % points.length].x) / 2, top: (start.y + points[(i + 1) % points.length].y) / 2 })
return
}
const end = points[(i + 1) % points.length] const end = points[(i + 1) % points.length]
const dx = end.x - start.x const dx = end.x - start.x
const dy = end.y - start.y const dy = end.y - start.y
const length = Math.sqrt(dx * dx + dy * dy) const length = Math.sqrt(dx * dx + dy * dy)
if (thisText) {
thisText.set({
left: (start.x + points[(i + 1) % points.length].x) / 2,
top: (start.y + points[(i + 1) % points.length].y) / 2,
text: length.toFixed(0),
})
return
}
const midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2) const midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2)
// Create new text object if it doesn't exist // Create new text object if it doesn't exist
@ -168,38 +172,46 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.canvas = canvas this.canvas = canvas
}, },
fillCell(cell = { width: 50, height: 100, padding: 10 }) { fillCell(cell = { width: 50, height: 100, padding: 10 }) {
const points = this.getCurrentPoints() const points = this.points
let bounds const minX = Math.min(...points.map((p) => p.x))
const maxX = Math.max(...points.map((p) => p.x))
const minY = Math.min(...points.map((p) => p.y))
const maxY = Math.max(...points.map((p) => p.y))
try { const boundingBoxWidth = maxX - minX
bounds = fabric.util.makeBoundingBoxFromPoints(points) const boundingBoxHeight = maxY - minY
} catch (error) {
alert('다각형의 꼭지점이 4개 이상이어야 합니다.')
return
}
for (let x = bounds.left; x < bounds.left + bounds.width; x += cell.width + cell.padding) { const rectWidth = cell.width
for (let y = bounds.top; y < bounds.top + bounds.height; y += cell.height + cell.padding) { const rectHeight = cell.height
const rect = new fabric.Rect({
left: x, const cols = Math.floor((boundingBoxWidth + cell.padding) / (rectWidth + cell.padding))
top: y, const rows = Math.floor((boundingBoxHeight + cell.padding) / (rectHeight + cell.padding))
width: cell.width,
height: cell.height, for (let i = 0; i < cols; i++) {
fill: 'transparent', for (let j = 0; j < rows; j++) {
stroke: 'black', const rectLeft = minX + i * (rectWidth + cell.padding)
selectable: false, const rectTop = minY + j * (rectHeight + cell.padding)
})
const rectPoints = [ const rectPoints = [
new fabric.Point(rect.left, rect.top), { x: rectLeft, y: rectTop },
new fabric.Point(rect.left + rect.width, rect.top), { x: rectLeft + rectWidth, y: rectTop },
new fabric.Point(rect.left, rect.top + rect.height), { x: rectLeft, y: rectTop + rectHeight },
new fabric.Point(rect.left + rect.width, rect.top + rect.height), { x: rectLeft + rectWidth, y: rectTop + rectHeight },
] ]
const isInside = rectPoints.every((rectPoint) => this.inPolygon(rectPoint) && this.distanceFromEdge(rectPoint) >= cell.padding) const allPointsInside = rectPoints.every((point) => this.inPolygon(point))
if (allPointsInside) {
const rect = new fabric.Rect({
left: rectLeft,
top: rectTop,
width: rectWidth,
height: rectHeight,
stroke: 'black', // or any other color
fill: 'transparent',
selectable: false,
})
if (isInside) {
this.canvas.add(rect) this.canvas.add(rect)
} }
} }

View File

@ -292,56 +292,6 @@ export const getDirectionByPoint = (a, b) => {
} }
} }
/**
* 선분의 교차점을 찾는 함수입니다. 함수는 선분이 실제로 교차하는 지점 내에서 교차하는지 확인합니다.
* @param {Object} line1 번째 선분, {x1, y1, x2, y2} 형태의 객체
* @param {Object} line2 번째 선분, {x1, y1, x2, y2} 형태의 객체
* @returns {{x: number, y: number}|null} 교차점의 좌표를 반환하거나, 교차점이 없으면 null을 반환합니다.
*/
export function calculateIntersection(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
const denominator = (x1_1 - x2_1) * (y1_2 - y2_2) - (y1_1 - y2_1) * (x1_2 - x2_2)
if (denominator === 0) return null // 선분이 평행하거나 일치하는 경우
const t = ((x1_1 - x1_2) * (y1_2 - y2_2) - (y1_1 - y1_2) * (x1_2 - x2_2)) / denominator
const u = -((x1_1 - x2_1) * (y1_1 - y1_2) - (y1_1 - y2_1) * (x1_1 - x1_2)) / denominator
// t와 u가 모두 0과 1 사이에 있을 때, 선분 내에서 교차
if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
const intersectionX = x1_1 + t * (x2_1 - x1_1)
const intersectionY = y1_1 + t * (y2_1 - y1_1)
// Determine the min and max for line1 and line2 for both x and y
const line1MinX = Math.min(line1.x1, line1.x2)
const line1MaxX = Math.max(line1.x1, line1.x2)
const line2MinX = Math.min(line2.x1, line2.x2)
const line2MaxX = Math.max(line2.x1, line2.x2)
const line1MinY = Math.min(line1.y1, line1.y2)
const line1MaxY = Math.max(line1.y1, line1.y2)
const line2MinY = Math.min(line2.y1, line2.y2)
const line2MaxY = Math.max(line2.y1, line2.y2)
// 교차점이 선분의 범위 내에 있는지 확인
if (
intersectionX >= line1MinX &&
intersectionX <= line1MaxX &&
intersectionX >= line2MinX &&
intersectionX <= line2MaxX &&
intersectionY >= line1MinY &&
intersectionY <= line1MaxY &&
intersectionY >= line2MinY &&
intersectionY <= line2MaxY
) {
return { x: Math.round(intersectionX), y: Math.round(intersectionY) }
}
}
return null // 교차점이 선분의 범위 내에 없음
}
export const findIntersection1 = (line1, line2) => { export const findIntersection1 = (line1, line2) => {
const { x1, y1, x2, y2 } = line1 // 첫 번째 선의 두 점 const { x1, y1, x2, y2 } = line1 // 첫 번째 선의 두 점
@ -372,7 +322,7 @@ export const findIntersection1 = (line1, line2) => {
return { x, y } return { x, y }
} }
export const calculateIntersection2 = (line1, line2) => { export const calculateIntersection = (line1, line2) => {
const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2]) const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2])
if (!result) { if (!result) {
@ -425,68 +375,51 @@ export function findOrthogonalPoint(line1, line2) {
*/ */
export const sortedPoints = (points) => { export const sortedPoints = (points) => {
const copyPoints = [...points] const copyPoints = [...points]
//points를 x,y좌표를 기준으로 정렬합니다. copyPoints.forEach((point) => {
copyPoints.sort((a, b) => { point.x1 = point.x
if (a.x === b.x) { point.y1 = point.y
return a.y - b.y const nextPoint = copyPoints[(copyPoints.indexOf(point) + 1) % copyPoints.length]
} point.x2 = nextPoint.x
return a.x - b.x point.y2 = nextPoint.y
}) })
// 이때 copyPoints를 순회하며 최초엔 x값을 비교하여 같은 점을 찾는다. 이때 이 점이 2번째 점이 된다. // copyPoint에서 x1, y1 값을 기준으로 시작 인덱스
// 그 다음점은 2번째 점과 y값이 같은 점이 된다. const startIndex = getStartIndex(copyPoints)
// 또 그다음 점은 3번째 점과 x값이 같은 점이 된다. const startDirection = getDirectionByPoint(
// 이를 반복하여 copyPoints를 재배열한다. { x: copyPoints[startIndex].x1, y: copyPoints[startIndex].y1 },
const resultPoints = [copyPoints[0]] { x: copyPoints[startIndex].x2, y: copyPoints[startIndex].y2 },
let index = 1 )
let currentPoint = { ...copyPoints[0] }
copyPoints.splice(0, 1) const resultPoints = [copyPoints[startIndex]]
while (index < points.length) {
if (index === points.length - 1) { let currentPoint = copyPoints[startIndex]
resultPoints.push(copyPoints[0])
index++ switch (startDirection) {
case 'right': {
copyPoints.forEach((point, index) => {
if (index === startIndex) return
const nextPoint = copyPoints.find((p) => p.x2 === currentPoint.x && p.y2 === currentPoint.y)
resultPoints.push(nextPoint)
currentPoint = nextPoint
})
break break
} else if (index % 2 === 0) { }
// 짝수번째는 y값이 같은 점을 찾는다. case 'bottom': {
for (let i = 0; i < copyPoints.length; i++) { copyPoints.forEach((point, index) => {
// y값이 같은 point가 많은 경우 그 중 x값이 가장 큰걸 찾는다. if (index === startIndex) return
let temp = copyPoints.filter((point) => point.y === currentPoint.y)
if (temp.length === 0) {
// temp가 비어있을 경우 copyPoints에서 가장 가까운 점을 찾는다.
temp = Array.of(findClosestPointByY(currentPoint, copyPoints))
}
// temp중 x값이 가장 가까운 값
const min = temp.reduce((prev, current) => (Math.abs(current.x - currentPoint.x) <= Math.abs(prev.x - currentPoint.x) ? current : prev)) const nextPoint = copyPoints.find((p) => p.x1 === currentPoint.x2 && p.y1 === currentPoint.y2)
resultPoints.push(nextPoint)
resultPoints.push(min) currentPoint = nextPoint
currentPoint = min })
copyPoints.splice(copyPoints.indexOf(min), 1) break
index++
break
}
} else {
// 홀수번째는 x값이 같은 점을 찾는다.
for (let i = 0; i < copyPoints.length; i++) {
// x값이 같은 point가 많은 경우 그 중 y값이 가장 큰걸 찾는다.
let temp = copyPoints.filter((point) => point.x === currentPoint.x)
if (temp.length === 0) {
// temp가 비어있을 경우 copyPoints에서 가장 가까운 점을 찾는다.
temp = Array.of(findClosestPointByX(currentPoint, copyPoints))
}
// temp중 y값이 가장 가까운 값
const min = temp.reduce((prev, current) => (Math.abs(current.y - currentPoint.y) <= Math.abs(prev.y - currentPoint.y) ? current : prev))
resultPoints.push(min)
currentPoint = min
copyPoints.splice(copyPoints.indexOf(min), 1)
index++
break
}
} }
} }
return resultPoints
return resultPoints.map((point) => {
return { x: point.x, y: point.y }
})
} }
/** /**