템플릿 사각형 수정
This commit is contained in:
parent
c44fa88ed8
commit
aebf4e0c42
@ -155,7 +155,6 @@ export default function Roof2() {
|
|||||||
|
|
||||||
canvas?.add(polygon)
|
canvas?.add(polygon)
|
||||||
|
|
||||||
polygon.drawRoof(-50)
|
|
||||||
addBackgroundInPolygon(polygon)
|
addBackgroundInPolygon(polygon)
|
||||||
|
|
||||||
const lines = togglePolygonLine(polygon)
|
const lines = togglePolygonLine(polygon)
|
||||||
@ -176,11 +175,15 @@ export default function Roof2() {
|
|||||||
|
|
||||||
const makeQLine = () => {
|
const makeQLine = () => {
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
const line = new QLine([50, 50, 200, 50], {
|
const line = new QLine(
|
||||||
stroke: 'black',
|
[50, 50, 200, 50],
|
||||||
strokeWidth: 1,
|
{
|
||||||
fontSize: fontSize,
|
stroke: 'black',
|
||||||
})
|
strokeWidth: 1,
|
||||||
|
fontSize: fontSize,
|
||||||
|
},
|
||||||
|
50,
|
||||||
|
)
|
||||||
|
|
||||||
canvas?.add(line)
|
canvas?.add(line)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ export class QLine extends fabric.Group {
|
|||||||
line
|
line
|
||||||
text
|
text
|
||||||
fontSize
|
fontSize
|
||||||
length
|
length = 0
|
||||||
x1
|
x1
|
||||||
y1
|
y1
|
||||||
x2
|
x2
|
||||||
@ -13,12 +13,13 @@ export class QLine extends fabric.Group {
|
|||||||
type = 'QLine'
|
type = 'QLine'
|
||||||
parent
|
parent
|
||||||
|
|
||||||
constructor(points, option) {
|
constructor(points, option, lengthTxt) {
|
||||||
const [x1, y1, x2, y2] = points
|
const [x1, y1, x2, y2] = points
|
||||||
|
|
||||||
if (!option.fontSize) {
|
if (!option.fontSize) {
|
||||||
throw new Error('Font size is required.')
|
throw new Error('Font size is required.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const line = new fabric.Line(points, { ...option, strokeWidth: 1 })
|
const line = new fabric.Line(points, { ...option, strokeWidth: 1 })
|
||||||
super([line], {})
|
super([line], {})
|
||||||
|
|
||||||
@ -31,6 +32,10 @@ export class QLine extends fabric.Group {
|
|||||||
this.direction = option.direction
|
this.direction = option.direction
|
||||||
this.parent = option.parent
|
this.parent = option.parent
|
||||||
|
|
||||||
|
if (lengthTxt > 0) {
|
||||||
|
this.length = Number(lengthTxt)
|
||||||
|
}
|
||||||
|
|
||||||
this.#init()
|
this.#init()
|
||||||
this.#addControl()
|
this.#addControl()
|
||||||
}
|
}
|
||||||
@ -66,7 +71,16 @@ export class QLine extends fabric.Group {
|
|||||||
this.removeWithUpdate(this.text)
|
this.removeWithUpdate(this.text)
|
||||||
this.text = null
|
this.text = null
|
||||||
}
|
}
|
||||||
|
if (this.length > 0) {
|
||||||
|
const text = new fabric.Textbox(this.length.toFixed(0).toString(), {
|
||||||
|
left: (this.x1 + this.x2) / 2,
|
||||||
|
top: (this.y1 + this.y2) / 2,
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
})
|
||||||
|
this.text = text
|
||||||
|
this.addWithUpdate(text)
|
||||||
|
return
|
||||||
|
}
|
||||||
const scaleX = this.scaleX
|
const scaleX = this.scaleX
|
||||||
const scaleY = this.scaleY
|
const scaleY = this.scaleY
|
||||||
const x1 = this.left
|
const x1 = this.left
|
||||||
@ -77,7 +91,7 @@ export class QLine extends fabric.Group {
|
|||||||
const dy = y2 - y1
|
const dy = y2 - y1
|
||||||
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0))
|
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0))
|
||||||
|
|
||||||
const text = new fabric.Textbox(this.length.toString(), {
|
const text = new fabric.Textbox(this.length.toFixed(0).toString(), {
|
||||||
left: (x1 + x2) / 2,
|
left: (x1 + x2) / 2,
|
||||||
top: (y1 + y2) / 2,
|
top: (y1 + y2) / 2,
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import {
|
import {
|
||||||
|
calculateIntersection,
|
||||||
distanceBetweenPoints,
|
distanceBetweenPoints,
|
||||||
|
getDegreeByChon,
|
||||||
getDirection,
|
getDirection,
|
||||||
getDirectionByPoint,
|
getDirectionByPoint,
|
||||||
|
getRoofHeight,
|
||||||
|
getRoofHypotenuse,
|
||||||
} from '@/util/canvas-util'
|
} from '@/util/canvas-util'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
|
||||||
@ -15,7 +19,6 @@ export default class QPolygon extends fabric.Group {
|
|||||||
canvas
|
canvas
|
||||||
fontSize
|
fontSize
|
||||||
qCells = []
|
qCells = []
|
||||||
roof
|
|
||||||
name
|
name
|
||||||
constructor(points, options, canvas) {
|
constructor(points, options, canvas) {
|
||||||
if (!options.fontSize) {
|
if (!options.fontSize) {
|
||||||
@ -43,8 +46,8 @@ export default class QPolygon extends fabric.Group {
|
|||||||
this.points.forEach((point, i) => {
|
this.points.forEach((point, i) => {
|
||||||
const nextPoint = this.points[(i + 1) % this.points.length]
|
const nextPoint = this.points[(i + 1) % this.points.length]
|
||||||
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
||||||
stroke: 'black',
|
stroke: this.stroke,
|
||||||
strokeWidth: 1,
|
strokeWidth: this.strokeWidth,
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
direction: getDirectionByPoint(point, nextPoint),
|
direction: getDirectionByPoint(point, nextPoint),
|
||||||
})
|
})
|
||||||
@ -88,7 +91,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
})
|
})
|
||||||
this.texts = []
|
this.texts = []
|
||||||
}
|
}
|
||||||
const points = this.getCurrentPoints()
|
const points = this.points
|
||||||
|
|
||||||
points.forEach((start, i) => {
|
points.forEach((start, i) => {
|
||||||
const end = points[(i + 1) % points.length]
|
const end = points[(i + 1) % points.length]
|
||||||
@ -281,77 +284,170 @@ export default class QPolygon extends fabric.Group {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 지붕 그리기
|
|
||||||
* @param offset
|
|
||||||
*/
|
|
||||||
drawRoof(offset = -10) {
|
|
||||||
const points = this.getCurrentPoints()
|
|
||||||
const offsetPoints = []
|
|
||||||
for (let i = 0; i < points.length; i++) {
|
|
||||||
const prev = points[(i - 1 + points.length) % points.length]
|
|
||||||
const current = points[i]
|
|
||||||
const next = points[(i + 1) % points.length]
|
|
||||||
|
|
||||||
// 두 벡터 계산 (prev -> current, current -> next)
|
|
||||||
const vector1 = { x: current.x - prev.x, y: current.y - prev.y }
|
|
||||||
const vector2 = { x: next.x - current.x, y: next.y - current.y }
|
|
||||||
|
|
||||||
// 벡터의 길이 계산
|
|
||||||
const length1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y)
|
|
||||||
const length2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y)
|
|
||||||
|
|
||||||
// 벡터를 단위 벡터로 정규화
|
|
||||||
const unitVector1 = { x: vector1.x / length1, y: vector1.y / length1 }
|
|
||||||
const unitVector2 = { x: vector2.x / length2, y: vector2.y / length2 }
|
|
||||||
|
|
||||||
// 법선 벡터 계산 (왼쪽 방향)
|
|
||||||
const normal1 = { x: -unitVector1.y, y: unitVector1.x }
|
|
||||||
const normal2 = { x: -unitVector2.y, y: unitVector2.x }
|
|
||||||
|
|
||||||
// 법선 벡터 평균 계산
|
|
||||||
const averageNormal = {
|
|
||||||
x: (normal1.x + normal2.x) / 2,
|
|
||||||
y: (normal1.y + normal2.y) / 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 평균 법선 벡터를 단위 벡터로 정규화
|
|
||||||
const lengthNormal = Math.sqrt(
|
|
||||||
averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y,
|
|
||||||
)
|
|
||||||
const unitNormal = {
|
|
||||||
x: averageNormal.x / lengthNormal,
|
|
||||||
y: averageNormal.y / lengthNormal,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 오프셋 적용
|
|
||||||
const offsetPoint = {
|
|
||||||
x: current.x + unitNormal.x * offset,
|
|
||||||
y: current.y + unitNormal.y * offset,
|
|
||||||
}
|
|
||||||
|
|
||||||
offsetPoints.push(offsetPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
const roof = new QPolygon(
|
|
||||||
offsetPoints,
|
|
||||||
{
|
|
||||||
stroke: 'black',
|
|
||||||
strokeWidth: 1,
|
|
||||||
fill: 'transparent',
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
},
|
|
||||||
this.canvas,
|
|
||||||
)
|
|
||||||
|
|
||||||
this.roof = roof
|
|
||||||
|
|
||||||
this.addWithUpdate(outPolygon)
|
|
||||||
this.canvas.renderAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
fillBackground(pattern) {
|
fillBackground(pattern) {
|
||||||
this.polygon.set({ fill: pattern })
|
this.polygon.set({ fill: pattern })
|
||||||
this.canvas.renderAll()
|
this.canvas.requestRenderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 보조선 그리기 사각형에서만
|
||||||
|
drawHelpLine(chon) {
|
||||||
|
let type
|
||||||
|
let smallestLength = Infinity
|
||||||
|
let maxLength = 0
|
||||||
|
|
||||||
|
this.lines.forEach((line) => {
|
||||||
|
if (line.length < smallestLength) {
|
||||||
|
smallestLength = line.length
|
||||||
|
}
|
||||||
|
if (line.length > maxLength) {
|
||||||
|
maxLength = line.length
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const smallestLines = this.lines.filter(
|
||||||
|
(line) => line.length === smallestLength,
|
||||||
|
)
|
||||||
|
|
||||||
|
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(4)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// 옆으로 누워있는 지붕의 높이
|
||||||
|
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(4)),
|
||||||
|
)
|
||||||
|
|
||||||
|
// 용마루
|
||||||
|
const ridge = new QLine([point1.x, point1.y, point2.x, point2.y], {
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.addWithUpdate(realLine1)
|
||||||
|
this.addWithUpdate(realLine2)
|
||||||
|
this.addWithUpdate(realLine3)
|
||||||
|
this.addWithUpdate(realLine4)
|
||||||
|
this.addWithUpdate(realLine5)
|
||||||
|
this.addWithUpdate(realLine6)
|
||||||
|
this.addWithUpdate(ridge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,13 @@ import {
|
|||||||
findTopTwoIndexesByDistance,
|
findTopTwoIndexesByDistance,
|
||||||
getDirection,
|
getDirection,
|
||||||
} from '@/util/canvas-util'
|
} from '@/util/canvas-util'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import { fontSizeState, sortedPolygonArray } from '@/store/canvasAtom'
|
import {
|
||||||
|
fontSizeState,
|
||||||
|
roofState,
|
||||||
|
sortedPolygonArray,
|
||||||
|
wallState,
|
||||||
|
} from '@/store/canvasAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
|
||||||
export const Mode = {
|
export const Mode = {
|
||||||
@ -30,6 +35,8 @@ export function useMode() {
|
|||||||
const [fontSize] = useRecoilState(fontSizeState)
|
const [fontSize] = useRecoilState(fontSizeState)
|
||||||
const [shape, setShape] = useState(0)
|
const [shape, setShape] = useState(0)
|
||||||
const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
|
const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
|
||||||
|
const [roof, setRoof] = useRecoilState(roofState)
|
||||||
|
const [wall, setWall] = useRecoilState(wallState)
|
||||||
|
|
||||||
const addEvent = (mode) => {
|
const addEvent = (mode) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@ -210,7 +217,8 @@ export function useMode() {
|
|||||||
// handleOuterlines()
|
// handleOuterlines()
|
||||||
handleOuterlinesTest() //외곽선 그리기 테스트
|
handleOuterlinesTest() //외곽선 그리기 테스트
|
||||||
|
|
||||||
makePolygon()
|
const wall = makePolygon()
|
||||||
|
setWall(wall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,11 +406,13 @@ export function useMode() {
|
|||||||
|
|
||||||
// 캔버스를 다시 그립니다.
|
// 캔버스를 다시 그립니다.
|
||||||
if (!otherLines) {
|
if (!otherLines) {
|
||||||
polygon.fillCell()
|
// polygon.fillCell()
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
polygon.setViewLengthText(false)
|
polygon.setViewLengthText(false)
|
||||||
setMode(Mode.DEFAULT)
|
setMode(Mode.DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return polygon
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -714,7 +724,6 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(newOuterlines)
|
|
||||||
makePolygon(newOuterlines)
|
makePolygon(newOuterlines)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,7 +789,9 @@ export function useMode() {
|
|||||||
offsetPoints.push(offsetPoint)
|
offsetPoints.push(offsetPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
makePolygon(offsetPoints)
|
const roof = makePolygon(offsetPoints)
|
||||||
|
setRoof(roof)
|
||||||
|
roof.drawHelpLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
const togglePolygonLine = (obj) => {
|
const togglePolygonLine = (obj) => {
|
||||||
|
|||||||
@ -20,6 +20,18 @@ export const canvasSizeState = atom({
|
|||||||
|
|
||||||
export const sortedPolygonArray = atom({
|
export const sortedPolygonArray = atom({
|
||||||
key: 'sortedArray',
|
key: 'sortedArray',
|
||||||
default : [],
|
default: [],
|
||||||
|
dangerouslyAllowMutability: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const roofState = atom({
|
||||||
|
key: 'roof',
|
||||||
|
default: {},
|
||||||
|
dangerouslyAllowMutability: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const wallState = atom({
|
||||||
|
key: 'wall',
|
||||||
|
default: {},
|
||||||
dangerouslyAllowMutability: true,
|
dangerouslyAllowMutability: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -264,3 +264,34 @@ export const getDirectionByPoint = (a, b) => {
|
|||||||
return vector.y > 0 ? 'bottom' : 'top'
|
return vector.y > 0 ? 'bottom' : 'top'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
|
||||||
|
if (denom === 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
|
||||||
|
|
||||||
|
// 교차점이 두 선분의 x 좌표 범위 내에 있는지 확인
|
||||||
|
if (
|
||||||
|
intersectX < Math.min(x1, x2) ||
|
||||||
|
intersectX > Math.max(x1, x2) ||
|
||||||
|
intersectX < Math.min(x3, x4) ||
|
||||||
|
intersectX > Math.max(x3, x4)
|
||||||
|
) {
|
||||||
|
return null // 교차점이 선분 범위 밖에 있음
|
||||||
|
}
|
||||||
|
|
||||||
|
return { x: intersectX, y: intersectY }
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user