6각형 보조선 라인
This commit is contained in:
parent
99bed48fce
commit
9e9be7b501
@ -170,19 +170,33 @@ export default function Roof2() {
|
|||||||
{ x: 550, y: 300 },
|
{ x: 550, y: 300 },
|
||||||
{ x: 550, y: 450 },
|
{ x: 550, y: 450 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const type1A = [
|
||||||
|
{ x: 67, y: 81 },
|
||||||
|
{ x: 67, y: 660 },
|
||||||
|
{ x: 437, y: 660 },
|
||||||
|
{ x: 437, y: 1190 },
|
||||||
|
{ x: 858, y: 1190 },
|
||||||
|
{ x: 858, y: 81 },
|
||||||
|
]
|
||||||
|
|
||||||
|
const type1B = [
|
||||||
|
{ x: 137, y: 42 },
|
||||||
|
{ x: 137, y: 621 },
|
||||||
|
{ x: 667, y: 621 },
|
||||||
|
{ x: 667, y: 991 },
|
||||||
|
{ x: 1088, y: 991 },
|
||||||
|
{ x: 1088, y: 42 },
|
||||||
|
]
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
const polygon = new QPolygon(
|
const polygon = new QPolygon(type1, {
|
||||||
type4,
|
|
||||||
{
|
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
name: 'QPolygon1',
|
name: 'QPolygon1',
|
||||||
},
|
})
|
||||||
canvas, // 필수로 넣어줘야 함
|
|
||||||
)
|
|
||||||
|
|
||||||
canvas?.add(polygon)
|
canvas?.add(polygon)
|
||||||
|
|
||||||
|
|||||||
108
src/components/fabric/HelpLine.js
Normal file
108
src/components/fabric/HelpLine.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { fabric } from 'fabric'
|
||||||
|
|
||||||
|
export class QLine extends fabric.Group {
|
||||||
|
line
|
||||||
|
text
|
||||||
|
fontSize
|
||||||
|
length = 0
|
||||||
|
x1
|
||||||
|
y1
|
||||||
|
x2
|
||||||
|
y2
|
||||||
|
direction
|
||||||
|
type = 'HelpLine'
|
||||||
|
parent
|
||||||
|
#lengthTxt = 0
|
||||||
|
|
||||||
|
constructor(points, option, lengthTxt) {
|
||||||
|
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 })
|
||||||
|
super([line], {})
|
||||||
|
|
||||||
|
this.x1 = x1
|
||||||
|
this.y1 = y1
|
||||||
|
this.x2 = x2
|
||||||
|
this.y2 = y2
|
||||||
|
this.line = line
|
||||||
|
this.fontSize = option.fontSize
|
||||||
|
this.direction = option.direction
|
||||||
|
this.parent = option.parent
|
||||||
|
|
||||||
|
if (lengthTxt > 0) {
|
||||||
|
this.#lengthTxt = Number(lengthTxt)
|
||||||
|
}
|
||||||
|
|
||||||
|
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', () => {
|
||||||
|
Object.keys(this.controls).forEach((controlKey) => {
|
||||||
|
if (controlKey !== 'ml' && controlKey !== 'mr') {
|
||||||
|
this.setControlVisible(controlKey, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ export class QLine extends fabric.Group {
|
|||||||
x2
|
x2
|
||||||
y2
|
y2
|
||||||
direction
|
direction
|
||||||
|
idx
|
||||||
type = 'QLine'
|
type = 'QLine'
|
||||||
parent
|
parent
|
||||||
#lengthTxt = 0
|
#lengthTxt = 0
|
||||||
@ -32,6 +33,7 @@ export class QLine extends fabric.Group {
|
|||||||
this.fontSize = option.fontSize
|
this.fontSize = option.fontSize
|
||||||
this.direction = option.direction
|
this.direction = option.direction
|
||||||
this.parent = option.parent
|
this.parent = option.parent
|
||||||
|
this.idx = option.idx
|
||||||
|
|
||||||
if (lengthTxt > 0) {
|
if (lengthTxt > 0) {
|
||||||
this.#lengthTxt = Number(lengthTxt)
|
this.#lengthTxt = Number(lengthTxt)
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import {
|
import {
|
||||||
|
calculateIntersection,
|
||||||
distanceBetweenPoints,
|
distanceBetweenPoints,
|
||||||
|
findClosestLineToPoint,
|
||||||
findTopTwoIndexesByDistance,
|
findTopTwoIndexesByDistance,
|
||||||
getDegreeByChon,
|
getDegreeByChon,
|
||||||
getDirectionByPoint,
|
getDirectionByPoint,
|
||||||
@ -23,14 +25,22 @@ export default class QPolygon extends fabric.Group {
|
|||||||
shape = 0 // 점 6개일때의 shape 모양
|
shape = 0 // 점 6개일때의 shape 모양
|
||||||
helpPoints = []
|
helpPoints = []
|
||||||
helpLines = []
|
helpLines = []
|
||||||
|
|
||||||
|
wall
|
||||||
constructor(points, options, canvas) {
|
constructor(points, options, canvas) {
|
||||||
if (points.length !== 4 && points.length !== 6) {
|
/*if (points.length !== 4 && points.length !== 6) {
|
||||||
throw new Error('Points must be 4 or 6.')
|
throw new Error('Points must be 4 or 6.')
|
||||||
}
|
}*/
|
||||||
if (!options.fontSize) {
|
if (!options.fontSize) {
|
||||||
throw new Error('Font size is required.')
|
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 sortPoints = sortedPoints(points)
|
||||||
const polygon = new fabric.Polygon(sortPoints, options)
|
const polygon = new fabric.Polygon(sortPoints, options)
|
||||||
|
|
||||||
@ -80,6 +90,10 @@ export default class QPolygon extends fabric.Group {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setWall(wall) {
|
||||||
|
this.wall = wall
|
||||||
|
}
|
||||||
|
|
||||||
setFontSize(fontSize) {
|
setFontSize(fontSize) {
|
||||||
this.fontSize = fontSize
|
this.fontSize = fontSize
|
||||||
this.texts.forEach((text) => {
|
this.texts.forEach((text) => {
|
||||||
@ -336,7 +350,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
this.#drawHelpLineInRect(chon)
|
this.#drawHelpLineInRect(chon)
|
||||||
} else if (this.lines.length === 6) {
|
} else if (this.lines.length === 6) {
|
||||||
// TODO : 6각형
|
// TODO : 6각형
|
||||||
this.#drawHelpLineInHexagon(chon)
|
this.#drawHelpLineInHexagon2(chon)
|
||||||
} else if (this.lines.length === 8) {
|
} else if (this.lines.length === 8) {
|
||||||
// TODO : 8각형
|
// TODO : 8각형
|
||||||
this.#drawHelpLineInOctagon(chon)
|
this.#drawHelpLineInOctagon(chon)
|
||||||
@ -596,9 +610,15 @@ export default class QPolygon extends fabric.Group {
|
|||||||
if (type === 1) {
|
if (type === 1) {
|
||||||
lines = [this.lines[0], this.lines[3]]
|
lines = [this.lines[0], this.lines[3]]
|
||||||
lines2 = [this.lines[1], this.lines[4]]
|
lines2 = [this.lines[1], this.lines[4]]
|
||||||
longestLines = [this.lines[4], this.lines[5]]
|
|
||||||
ridgeLength1 = lines2[0].length
|
ridgeLength1 =
|
||||||
ridgeLength2 = longestLines[0].length - lines[1].length
|
this.lines[1].length > this.lines[2].length
|
||||||
|
? this.lines[5].length - this.lines[0].length
|
||||||
|
: this.lines[1].length
|
||||||
|
ridgeLength2 =
|
||||||
|
this.lines[1].length > this.lines[2].length
|
||||||
|
? this.lines[2].length
|
||||||
|
: this.lines[4].length - this.lines[3].length
|
||||||
vPoint1 = {
|
vPoint1 = {
|
||||||
x: lines[0].x1 + lines[0].length / 2,
|
x: lines[0].x1 + lines[0].length / 2,
|
||||||
y: lines[0].y1 + lines[0].length / 2,
|
y: lines[0].y1 + lines[0].length / 2,
|
||||||
@ -628,19 +648,14 @@ export default class QPolygon extends fabric.Group {
|
|||||||
vPoint2.x,
|
vPoint2.x,
|
||||||
vPoint2.y - ridgeLength2,
|
vPoint2.y - ridgeLength2,
|
||||||
]
|
]
|
||||||
|
ridgeHelpLinePoint1 =
|
||||||
ridgeHelpLinePoint1 = [
|
ridgeLength1 > ridgeLength2
|
||||||
lines2[0].x2,
|
? [lines2[0].x2, lines2[0].y2, ridgeEndPoint2[2], ridgeEndPoint2[3]]
|
||||||
lines2[0].y2,
|
: [lines2[0].x2, lines2[0].y2, ridgeEndPoint1[2], ridgeEndPoint1[3]]
|
||||||
ridgeEndPoint1[2],
|
ridgeHelpLinePoint2 =
|
||||||
ridgeEndPoint1[3],
|
ridgeLength1 > ridgeLength2
|
||||||
]
|
? [lines2[1].x2, lines2[1].y2, ridgeEndPoint1[2], ridgeEndPoint1[3]]
|
||||||
ridgeHelpLinePoint2 = [
|
: [lines2[1].x2, lines2[1].y2, ridgeEndPoint2[2], ridgeEndPoint2[3]]
|
||||||
lines2[1].x2,
|
|
||||||
lines2[1].y2,
|
|
||||||
ridgeEndPoint2[2],
|
|
||||||
ridgeEndPoint2[3],
|
|
||||||
]
|
|
||||||
} else if (type === 2) {
|
} else if (type === 2) {
|
||||||
lines = [this.lines[2], this.lines[5]]
|
lines = [this.lines[2], this.lines[5]]
|
||||||
lines2 = [this.lines[0], this.lines[3]]
|
lines2 = [this.lines[0], this.lines[3]]
|
||||||
@ -693,9 +708,15 @@ export default class QPolygon extends fabric.Group {
|
|||||||
} else if (type === 3) {
|
} else if (type === 3) {
|
||||||
lines = [this.lines[1], this.lines[4]]
|
lines = [this.lines[1], this.lines[4]]
|
||||||
lines2 = [this.lines[2], this.lines[5]]
|
lines2 = [this.lines[2], this.lines[5]]
|
||||||
longestLines = [this.lines[0], this.lines[5]]
|
ridgeLength1 =
|
||||||
ridgeLength1 = this.lines[3].length
|
this.lines[2].length > this.lines[3].length
|
||||||
ridgeLength2 = longestLines[0].length - lines[0].length
|
? this.lines[0].length - lines[0].length
|
||||||
|
: this.lines[2].length
|
||||||
|
|
||||||
|
ridgeLength2 =
|
||||||
|
this.lines[2].length > this.lines[3].length
|
||||||
|
? this.lines[3].length
|
||||||
|
: this.lines[5].length - lines[1].length
|
||||||
vPoint1 = {
|
vPoint1 = {
|
||||||
x: lines[0].x1 + lines[0].length / 2,
|
x: lines[0].x1 + lines[0].length / 2,
|
||||||
y: lines[0].y1 - lines[0].length / 2,
|
y: lines[0].y1 - lines[0].length / 2,
|
||||||
@ -717,28 +738,24 @@ export default class QPolygon extends fabric.Group {
|
|||||||
vPoint1.x,
|
vPoint1.x,
|
||||||
vPoint1.y,
|
vPoint1.y,
|
||||||
vPoint1.x,
|
vPoint1.x,
|
||||||
vPoint1.y - ridgeLength2,
|
vPoint1.y - ridgeLength1,
|
||||||
]
|
]
|
||||||
|
|
||||||
ridgeEndPoint2 = [
|
ridgeEndPoint2 = [
|
||||||
vPoint2.x,
|
vPoint2.x,
|
||||||
vPoint2.y,
|
vPoint2.y,
|
||||||
vPoint2.x - ridgeLength1,
|
vPoint2.x - ridgeLength2,
|
||||||
vPoint2.y,
|
vPoint2.y,
|
||||||
]
|
]
|
||||||
|
|
||||||
ridgeHelpLinePoint1 = [
|
ridgeHelpLinePoint1 =
|
||||||
lines2[1].x2,
|
ridgeLength1 > ridgeLength2
|
||||||
lines2[1].y2,
|
? [lines2[1].x2, lines2[1].y2, ridgeEndPoint1[2], ridgeEndPoint1[3]]
|
||||||
ridgeEndPoint1[2],
|
: [lines2[1].x2, lines2[1].y2, ridgeEndPoint2[2], ridgeEndPoint2[3]]
|
||||||
ridgeEndPoint1[3],
|
ridgeHelpLinePoint2 =
|
||||||
]
|
ridgeLength1 > ridgeLength2
|
||||||
ridgeHelpLinePoint2 = [
|
? [lines2[0].x2, lines2[0].y2, ridgeEndPoint2[2], ridgeEndPoint2[3]]
|
||||||
lines2[0].x2,
|
: [lines2[0].x2, lines2[0].y2, ridgeEndPoint1[2], ridgeEndPoint1[3]]
|
||||||
lines2[0].y2,
|
|
||||||
ridgeEndPoint2[2],
|
|
||||||
ridgeEndPoint2[3],
|
|
||||||
]
|
|
||||||
} else if (type === 4) {
|
} else if (type === 4) {
|
||||||
lines = [this.lines[0], this.lines[3]]
|
lines = [this.lines[0], this.lines[3]]
|
||||||
lines2 = [this.lines[1], this.lines[4]]
|
lines2 = [this.lines[1], this.lines[4]]
|
||||||
@ -839,26 +856,18 @@ export default class QPolygon extends fabric.Group {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// 용마루 보조선
|
// 용마루 보조선
|
||||||
const ridgeHelpLine1 = new QLine(
|
const ridgeHelpLine1 = new QLine(ridgeHelpLinePoint1, {
|
||||||
ridgeHelpLinePoint1,
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
stroke: 'blue',
|
stroke: 'blue',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
},
|
})
|
||||||
getRoofHypotenuse(lines[0].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 용마루 보조선
|
// 용마루 보조선
|
||||||
const ridgeHelpLine2 = new QLine(
|
const ridgeHelpLine2 = new QLine(ridgeHelpLinePoint2, {
|
||||||
ridgeHelpLinePoint2,
|
|
||||||
{
|
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
stroke: 'blue',
|
stroke: 'blue',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
},
|
})
|
||||||
getRoofHypotenuse(lines[1].length / 2),
|
|
||||||
)
|
|
||||||
|
|
||||||
// 용마루
|
// 용마루
|
||||||
const ridge1 = new QLine(
|
const ridge1 = new QLine(
|
||||||
@ -919,6 +928,184 @@ export default class QPolygon extends fabric.Group {
|
|||||||
|
|
||||||
this.canvas.renderAll()
|
this.canvas.renderAll()
|
||||||
}
|
}
|
||||||
|
#drawHelpLineInHexagon2(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,
|
||||||
|
stroke: 'blue',
|
||||||
|
idx: index,
|
||||||
|
})
|
||||||
|
historyLines.push(line)
|
||||||
|
this.addWithUpdate(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.addWithUpdate(helpLine1)
|
||||||
|
this.addWithUpdate(helpLine2)
|
||||||
|
this.removeWithUpdate(prevLine)
|
||||||
|
this.removeWithUpdate(line)
|
||||||
|
this.canvas.requestRenderAll()
|
||||||
|
})
|
||||||
|
// 용마루
|
||||||
|
|
||||||
|
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: 'green',
|
||||||
|
strokeWidth: 5,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ridgePoint.push({ x: newX, y: newY })
|
||||||
|
|
||||||
|
this.removeWithUpdate(closestLine)
|
||||||
|
|
||||||
|
this.addWithUpdate(ridgeHelpLine)
|
||||||
|
|
||||||
|
const ridge = new QLine([helpPoint.x, helpPoint.y, newX, newY], {
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
stroke: 'skyblue',
|
||||||
|
strokeWidth: 5,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.addWithUpdate(ridge)
|
||||||
|
})
|
||||||
|
|
||||||
|
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.addWithUpdate(ridgeConnectLine)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
#drawHelpLineInOctagon(chon) {}
|
#drawHelpLineInOctagon(chon) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -241,9 +241,12 @@ export function useMode() {
|
|||||||
points.current = []
|
points.current = []
|
||||||
historyPoints.current = []
|
historyPoints.current = []
|
||||||
|
|
||||||
handleOuterlinesTest()
|
const roof = handleOuterlinesTest()
|
||||||
const wall = makePolygon()
|
const wall = makePolygon()
|
||||||
|
|
||||||
|
roof.setWall(wall)
|
||||||
setWall(wall)
|
setWall(wall)
|
||||||
|
roof.drawHelpLine()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +814,8 @@ export function useMode() {
|
|||||||
|
|
||||||
const roof = makePolygon(offsetPoints)
|
const roof = makePolygon(offsetPoints)
|
||||||
setRoof(roof)
|
setRoof(roof)
|
||||||
roof.drawHelpLine()
|
|
||||||
|
return roof
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -880,6 +884,7 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const roof = makePolygon(offsetPoints)
|
const roof = makePolygon(offsetPoints)
|
||||||
|
roof.setWall(polygon)
|
||||||
setRoof(roof)
|
setRoof(roof)
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -352,6 +352,18 @@ export function calculateIntersection(line1, line2) {
|
|||||||
return { x: intersectX, y: intersectY }
|
return { x: intersectX, y: intersectY }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
return { x: intersectionX, y: intersectionY }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* points배열을 입력받아 반시계방향으로 정렬된 points를 반환합니다.
|
* points배열을 입력받아 반시계방향으로 정렬된 points를 반환합니다.
|
||||||
* @param points
|
* @param points
|
||||||
@ -417,3 +429,61 @@ export const sortedPoints = (points) => {
|
|||||||
|
|
||||||
return resultPoints
|
return resultPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* point가 선 위에 있는지 확인
|
||||||
|
* @param line
|
||||||
|
* @param point
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
// 직선의 방정식.
|
||||||
|
// 방정식은 ax + by + c = 0이며, 점의 좌표를 대입하여 계산된 값은 직선과 점 사이의 관계를 나타낸다.
|
||||||
|
export function isPointOnLine(line, point) {
|
||||||
|
const a = line.y2 - line.y1
|
||||||
|
const b = line.x1 - line.x2
|
||||||
|
const c = line.x2 * line.y1 - line.x1 * line.y2
|
||||||
|
return a * point.x + b * point.y + c === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 점과 가까운 line 찾기
|
||||||
|
* @param point
|
||||||
|
* @param lines {Array}
|
||||||
|
* @returns {null}
|
||||||
|
*/
|
||||||
|
export function findClosestLineToPoint(point, lines) {
|
||||||
|
let closestLine = null
|
||||||
|
let closestDistance = Infinity
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const distance = calculateDistance(point, line)
|
||||||
|
|
||||||
|
if (distance < closestDistance) {
|
||||||
|
closestDistance = distance
|
||||||
|
closestLine = line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closestLine
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 점과 직선사이의 최단 거리
|
||||||
|
* @param point
|
||||||
|
* @param line
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function calculateDistance(point, line) {
|
||||||
|
const x1 = line.x1
|
||||||
|
const y1 = line.y1
|
||||||
|
const x2 = line.x2
|
||||||
|
const y2 = line.y2
|
||||||
|
const x0 = point.x
|
||||||
|
const y0 = point.y
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user