Merge branch 'feature/test' into feature/test-jy
# Conflicts: # src/components/fabric/QPolygon.js
This commit is contained in:
commit
a061ec018d
@ -12,6 +12,7 @@
|
||||
"@nextui-org/react": "^2.4.2",
|
||||
"fabric": "^5.3.0",
|
||||
"framer-motion": "^11.2.13",
|
||||
"mathjs": "^13.0.2",
|
||||
"next": "14.2.3",
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
|
||||
@ -169,7 +169,7 @@ export default function Roof2() {
|
||||
{ x: 1088, y: 42 },
|
||||
]
|
||||
if (canvas) {
|
||||
const polygon = new QPolygon(type1, {
|
||||
const polygon = new QPolygon(type4, {
|
||||
fill: 'transparent',
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
|
||||
@ -13,6 +13,9 @@ export class QLine extends fabric.Group {
|
||||
idx
|
||||
type = 'QLine'
|
||||
parent
|
||||
isAlreadyInterSection = false
|
||||
|
||||
interSectionPoints = []
|
||||
#lengthTxt = 0
|
||||
|
||||
constructor(points, option = { isActiveLengthText: true }, lengthTxt) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { fabric } from 'fabric'
|
||||
import {
|
||||
calculateIntersection,
|
||||
calculateIntersection2,
|
||||
distanceBetweenPoints,
|
||||
findClosestLineToPoint,
|
||||
findTopTwoIndexesByDistance,
|
||||
@ -530,13 +531,97 @@ export default class QPolygon extends fabric.Group {
|
||||
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
|
||||
|
||||
#drawHelpLineInHexagon(chon) {
|
||||
const historyLines = []
|
||||
const helpPoints = []
|
||||
const notInterSectionLines = []
|
||||
const ridge = []
|
||||
const maxLength = this.lines.reduce((max, obj) => Math.min(max, obj.length), 999999)
|
||||
this.points.forEach((point, index) => {
|
||||
const wallPoint = this.wall.points[index]
|
||||
// 두 점의 좌표
|
||||
@ -550,8 +635,139 @@ export default class QPolygon extends fabric.Group {
|
||||
// x1, y1을 기준으로 x2, y2와의 거리를 유지한 새로운 직선 생성
|
||||
const angle = Math.atan2(y2 - y1, x2 - x1)
|
||||
|
||||
newX2 = x1 + (maxLength + 50) * Math.cos(angle)
|
||||
newY2 = y1 + (maxLength + 50) * Math.sin(angle)
|
||||
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
|
||||
|
||||
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,
|
||||
|
||||
1373
src/hooks/useMode.js
1373
src/hooks/useMode.js
File diff suppressed because it is too large
Load Diff
@ -13,8 +13,8 @@ export const fontSizeState = atom({
|
||||
export const canvasSizeState = atom({
|
||||
key: 'canvasSize',
|
||||
default: {
|
||||
vertical: 1000,
|
||||
horizontal: 1000,
|
||||
vertical: 1500,
|
||||
horizontal: 1500,
|
||||
},
|
||||
})
|
||||
|
||||
@ -35,3 +35,9 @@ export const wallState = atom({
|
||||
default: {},
|
||||
dangerouslyAllowMutability: true,
|
||||
})
|
||||
|
||||
export const templatePolygonArrayState = atom({
|
||||
key: 'templatePolygon',
|
||||
default: {}, //object ex) big, mid, sht = {point : [{x1, y1}, {x2, y1}], direction : left or right or top or bottom}
|
||||
})
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { intersect } from 'mathjs'
|
||||
|
||||
/**
|
||||
* Collection of function to use on canvas
|
||||
*/
|
||||
@ -9,18 +11,14 @@ export function polygonPositionHandler(dim, finalMatrix, fabricObject) {
|
||||
let y = fabricObject.points[this.pointIndex].y - fabricObject.pathOffset.y
|
||||
return fabric.util.transformPoint(
|
||||
{ x, y },
|
||||
fabric.util.multiplyTransformMatrices(
|
||||
fabricObject.canvas.viewportTransform,
|
||||
fabricObject.calcTransformMatrix(),
|
||||
),
|
||||
fabric.util.multiplyTransformMatrices(fabricObject.canvas.viewportTransform, fabricObject.calcTransformMatrix()),
|
||||
)
|
||||
}
|
||||
|
||||
function getObjectSizeWithStroke(object) {
|
||||
let stroke = new fabric.Point(
|
||||
object.strokeUniform ? 1 / object.scaleX : 1,
|
||||
object.strokeUniform ? 1 / object.scaleY : 1,
|
||||
).multiply(object.strokeWidth)
|
||||
let stroke = new fabric.Point(object.strokeUniform ? 1 / object.scaleX : 1, object.strokeUniform ? 1 / object.scaleY : 1).multiply(
|
||||
object.strokeWidth,
|
||||
)
|
||||
return new fabric.Point(object.width + stroke.x, object.height + stroke.y)
|
||||
}
|
||||
|
||||
@ -28,30 +26,21 @@ function getObjectSizeWithStroke(object) {
|
||||
export function actionHandler(eventData, transform, x, y) {
|
||||
let polygon = transform.target,
|
||||
currentControl = polygon.controls[polygon.__corner],
|
||||
mouseLocalPosition = polygon.toLocalPoint(
|
||||
new fabric.Point(x, y),
|
||||
'center',
|
||||
'center',
|
||||
),
|
||||
mouseLocalPosition = polygon.toLocalPoint(new fabric.Point(x, y), 'center', 'center'),
|
||||
polygonBaseSize = getObjectSizeWithStroke(polygon),
|
||||
size = polygon._getTransformedDimensions(0, 0)
|
||||
polygon.points[currentControl.pointIndex] = {
|
||||
x:
|
||||
(mouseLocalPosition.x * polygonBaseSize.x) / size.x +
|
||||
polygon.pathOffset.x,
|
||||
y:
|
||||
(mouseLocalPosition.y * polygonBaseSize.y) / size.y +
|
||||
polygon.pathOffset.y,
|
||||
x: (mouseLocalPosition.x * polygonBaseSize.x) / size.x + polygon.pathOffset.x,
|
||||
y: (mouseLocalPosition.y * polygonBaseSize.y) / size.y + polygon.pathOffset.y,
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// define a function that can keep the polygon in the same position when we change its width/height/top/left
|
||||
export function anchorWrapper(anchorIndex, fn) {
|
||||
return function (eventData, transform, x, y) {
|
||||
return function(eventData, transform, x, y) {
|
||||
let fabricObject = transform.target
|
||||
let originX =
|
||||
fabricObject?.points[anchorIndex].x - fabricObject.pathOffset.x
|
||||
let originX = fabricObject?.points[anchorIndex].x - fabricObject.pathOffset.x
|
||||
let originY = fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y
|
||||
let absolutePoint = fabric.util.transformPoint(
|
||||
{
|
||||
@ -63,12 +52,8 @@ export function anchorWrapper(anchorIndex, fn) {
|
||||
let actionPerformed = fn(eventData, transform, x, y)
|
||||
let newDim = fabricObject._setPositionDimensions({})
|
||||
let polygonBaseSize = getObjectSizeWithStroke(fabricObject)
|
||||
let newX =
|
||||
(fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) /
|
||||
polygonBaseSize.x
|
||||
let newY =
|
||||
(fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) /
|
||||
polygonBaseSize.y
|
||||
let newX = (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) / polygonBaseSize.x
|
||||
let newY = (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) / polygonBaseSize.y
|
||||
fabricObject.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5)
|
||||
return actionPerformed
|
||||
}
|
||||
@ -104,9 +89,7 @@ export function addDistanceTextToPolygon(polygon) {
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
const start = points[i]
|
||||
const end = points[(i + 1) % points.length] // 다음 점 (마지막 점의 경우 첫번째 점으로)
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2),
|
||||
) // 두 점 사이의 거리 계산
|
||||
const distance = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)) // 두 점 사이의 거리 계산
|
||||
|
||||
const text = new fabric.Textbox(distance.toFixed(2), {
|
||||
// 소수 둘째자리까지 표시
|
||||
@ -160,10 +143,7 @@ export const getStartIndex = (lines) => {
|
||||
let smallestY1 = lines[0].y1
|
||||
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
if (
|
||||
lines[i].x1 < smallestX1 ||
|
||||
(lines[i].x1 === smallestX1 && lines[i].y1 < smallestY1)
|
||||
) {
|
||||
if (lines[i].x1 < smallestX1 || (lines[i].x1 === smallestX1 && lines[i].y1 < smallestY1)) {
|
||||
smallestIndex = i
|
||||
smallestX1 = lines[i].x1
|
||||
smallestY1 = lines[i].y1
|
||||
@ -184,10 +164,7 @@ export const getStartIndexPoint = (points) => {
|
||||
let smallestY1 = points[0].y
|
||||
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
if (
|
||||
points[i].x < smallestX1 ||
|
||||
(points[i].x === smallestX1 && points[i].y < smallestY1)
|
||||
) {
|
||||
if (points[i].x < smallestX1 || (points[i].x === smallestX1 && points[i].y < smallestY1)) {
|
||||
smallestIndex = i
|
||||
smallestX1 = points[i].x
|
||||
smallestY1 = points[i].y
|
||||
@ -316,50 +293,40 @@ export const getDirectionByPoint = (a, b) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* line을 두개를 이용해서 교차점을 찾는 함수
|
||||
* @param line1
|
||||
* @param line2
|
||||
* @returns {{x: number, y: number}|null}
|
||||
* 두 선분의 교차점을 찾는 함수입니다. 이 함수는 두 선분이 실제로 교차하는 지점 내에서 교차하는지 확인합니다.
|
||||
* @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 = line1.x1,
|
||||
y1 = line1.y1,
|
||||
x2 = line1.x2,
|
||||
y2 = line1.y2
|
||||
const x3 = line2.x1,
|
||||
y3 = line2.y1,
|
||||
x4 = line2.x2,
|
||||
y4 = line2.y2
|
||||
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 denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
|
||||
if (denom === 0) return null // 선분이 평행하거나 일치
|
||||
const denominator = (x1_1 - x2_1) * (y1_2 - y2_2) - (y1_1 - y2_1) * (x1_2 - x2_2)
|
||||
if (denominator === 0) return null // 선분이 평행하거나 일치하는 경우
|
||||
|
||||
const intersectX =
|
||||
((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / denom
|
||||
const intersectY =
|
||||
((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / denom
|
||||
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
|
||||
|
||||
// 교차점이 두 선분의 x 좌표 범위 내에 있는지 확인
|
||||
if (
|
||||
intersectX < Math.min(x1, x2) ||
|
||||
intersectX > Math.max(x1, x2) ||
|
||||
intersectX < Math.min(x3, x4) ||
|
||||
intersectX > Math.max(x3, x4)
|
||||
) {
|
||||
return null // 교차점이 선분 범위 밖에 있음
|
||||
// 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)
|
||||
return { x: Math.round(intersectionX), y: Math.round(intersectionY) }
|
||||
}
|
||||
|
||||
return { x: intersectX, y: intersectY }
|
||||
return null // 교차점이 선분의 범위 내에 없음
|
||||
}
|
||||
|
||||
export const calculateIntersection2 = (line1, line2) => {
|
||||
const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2])
|
||||
return { x: Math.round(result[0]), y: Math.round(result[1]) }
|
||||
}
|
||||
|
||||
function findOrthogonalPoint(x1, y1, x2, y2, x3, y3, x4, y4) {
|
||||
// Calculate the intersection point of two lines
|
||||
const intersectionX =
|
||||
((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) /
|
||||
((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
||||
const intersectionY =
|
||||
((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) /
|
||||
((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
||||
const intersectionX = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
||||
const intersectionY = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
||||
|
||||
return { x: intersectionX, y: intersectionY }
|
||||
}
|
||||
@ -399,9 +366,7 @@ export const sortedPoints = (points) => {
|
||||
// y값이 같은 point가 많은 경우 그 중 x값이 가장 큰걸 찾는다.
|
||||
const temp = copyPoints.filter((point) => point.y === currentPoint.y)
|
||||
// temp중 x값이 가장 큰 값
|
||||
const max = temp.reduce((prev, current) =>
|
||||
prev.x >= current.x ? prev : current,
|
||||
)
|
||||
const max = temp.reduce((prev, current) => (prev.x >= current.x ? prev : current))
|
||||
resultPoints.push(max)
|
||||
currentPoint = max
|
||||
copyPoints.splice(copyPoints.indexOf(max), 1)
|
||||
@ -414,9 +379,7 @@ export const sortedPoints = (points) => {
|
||||
// x값이 같은 point가 많은 경우 그 중 y값이 가장 큰걸 찾는다.
|
||||
const temp = copyPoints.filter((point) => point.x === currentPoint.x)
|
||||
// temp중 y값이 가장 큰 값
|
||||
const max = temp.reduce((prev, current) =>
|
||||
prev.y >= current.y ? prev : current,
|
||||
)
|
||||
const max = temp.reduce((prev, current) => (prev.y >= current.y ? prev : current))
|
||||
|
||||
resultPoints.push(max)
|
||||
currentPoint = max
|
||||
@ -481,9 +444,7 @@ export function calculateDistance(point, line) {
|
||||
const x0 = point.x
|
||||
const y0 = point.y
|
||||
|
||||
const numerator = Math.abs(
|
||||
(y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1,
|
||||
)
|
||||
const numerator = Math.abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1)
|
||||
const denominator = Math.sqrt(Math.pow(y2 - y1, 2) + Math.pow(x2 - x1, 2))
|
||||
return numerator / denominator
|
||||
}
|
||||
}
|
||||
2
startscript.js
Normal file
2
startscript.js
Normal file
@ -0,0 +1,2 @@
|
||||
var exec = require('child_process').exec
|
||||
exec('yarn start', { windowsHide: true })
|
||||
68
yarn.lock
68
yarn.lock
@ -14,6 +14,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.24.7":
|
||||
version "7.24.8"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e"
|
||||
integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@formatjs/ecma402-abstract@2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz#39197ab90b1c78b7342b129a56a7acdb8f512e17"
|
||||
@ -2262,6 +2269,11 @@ commander@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz"
|
||||
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
|
||||
|
||||
complex.js@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.1.1.tgz#0675dac8e464ec431fb2ab7d30f41d889fb25c31"
|
||||
integrity sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==
|
||||
|
||||
compute-scroll-into-view@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz#753f11d972596558d8fe7c6bcbc8497690ab4c87"
|
||||
@ -2324,7 +2336,7 @@ debug@4:
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
decimal.js@^10.3.1:
|
||||
decimal.js@^10.3.1, decimal.js@^10.4.3:
|
||||
version "10.4.3"
|
||||
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz"
|
||||
integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
|
||||
@ -2393,6 +2405,11 @@ emoji-regex@^9.2.2:
|
||||
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz"
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
|
||||
escape-latex@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1"
|
||||
integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==
|
||||
|
||||
escodegen@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz"
|
||||
@ -2474,6 +2491,11 @@ form-data@^4.0.0:
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fraction.js@^4.3.7:
|
||||
version "4.3.7"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||
|
||||
framer-motion@^11.2.13:
|
||||
version "11.2.13"
|
||||
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-11.2.13.tgz#ab23fbc386233b1a1548757d840190054e5e1f1d"
|
||||
@ -2703,6 +2725,11 @@ jackspeak@^3.1.2:
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
javascript-natural-sort@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
|
||||
integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==
|
||||
|
||||
jiti@^1.21.0:
|
||||
version "1.21.6"
|
||||
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz"
|
||||
@ -2810,6 +2837,21 @@ make-dir@^3.1.0:
|
||||
dependencies:
|
||||
semver "^6.0.0"
|
||||
|
||||
mathjs@^13.0.2:
|
||||
version "13.0.2"
|
||||
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-13.0.2.tgz#eb87e31a21d9ffc57e26ce98ddb14a4a07b13d91"
|
||||
integrity sha512-8vK/+InU4FTphRTWsrnvRsgSjbyNupRQYDDIXLuEGDZtJsGdbA9dVV4HZ0amBQb+RXplRjVJNGZZfB0WoHWFWA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.24.7"
|
||||
complex.js "^2.1.1"
|
||||
decimal.js "^10.4.3"
|
||||
escape-latex "^1.2.0"
|
||||
fraction.js "^4.3.7"
|
||||
javascript-natural-sort "^0.7.1"
|
||||
seedrandom "^3.0.5"
|
||||
tiny-emitter "^2.1.0"
|
||||
typed-function "^4.2.1"
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
|
||||
@ -3263,6 +3305,11 @@ scroll-into-view-if-needed@3.0.10:
|
||||
dependencies:
|
||||
compute-scroll-into-view "^3.0.2"
|
||||
|
||||
seedrandom@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
|
||||
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
|
||||
|
||||
semver@^6.0.0:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
@ -3370,7 +3417,14 @@ string_decoder@^1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.2.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
@ -3480,6 +3534,11 @@ thenify-all@^1.0.0:
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
tiny-emitter@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
|
||||
@ -3519,6 +3578,11 @@ tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0:
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz"
|
||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||
|
||||
typed-function@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-4.2.1.tgz#19aa51847aa2dea9ef5e7fb7641c060179a74426"
|
||||
integrity sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==
|
||||
|
||||
universalify@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user