801 lines
21 KiB
JavaScript
801 lines
21 KiB
JavaScript
import { fabric } from 'fabric'
|
|
import {
|
|
distanceBetweenPoints,
|
|
findTopTwoIndexesByDistance,
|
|
getDegreeByChon,
|
|
getDirectionByPoint,
|
|
getRoofHeight,
|
|
getRoofHypotenuse,
|
|
sortedPoints,
|
|
} from '@/util/canvas-util'
|
|
import { QLine } from '@/components/fabric/QLine'
|
|
|
|
export default class QPolygon extends fabric.Group {
|
|
type = 'QPolygon'
|
|
polygon
|
|
points
|
|
texts = []
|
|
lines = []
|
|
canvas
|
|
fontSize
|
|
qCells = []
|
|
name
|
|
shape = 0 // 점 6개일때의 shape 모양
|
|
helpPoints = []
|
|
helpLines = []
|
|
constructor(points, options, canvas) {
|
|
if (points.length !== 4 && points.length !== 6) {
|
|
throw new Error('Points must be 4 or 6.')
|
|
}
|
|
if (!options.fontSize) {
|
|
throw new Error('Font size is required.')
|
|
}
|
|
|
|
const sortPoints = sortedPoints(points)
|
|
const polygon = new fabric.Polygon(sortPoints, options)
|
|
|
|
super([polygon], {})
|
|
|
|
this.fontSize = options.fontSize
|
|
this.points = sortPoints
|
|
this.polygon = polygon
|
|
this.name = options.name
|
|
this.#init()
|
|
this.#addEvent()
|
|
this.#initLines()
|
|
this.setShape()
|
|
}
|
|
|
|
#initLines() {
|
|
this.points.forEach((point, i) => {
|
|
const nextPoint = this.points[(i + 1) % this.points.length]
|
|
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
|
stroke: this.stroke,
|
|
strokeWidth: this.strokeWidth,
|
|
fontSize: this.fontSize,
|
|
direction: getDirectionByPoint(point, nextPoint),
|
|
})
|
|
|
|
this.lines.push(line)
|
|
})
|
|
}
|
|
|
|
#init() {
|
|
this.#addLengthText()
|
|
}
|
|
|
|
#addEvent() {
|
|
this.on('scaling', (e) => {
|
|
this.#updateLengthText()
|
|
})
|
|
|
|
this.on('selected', function () {
|
|
// 모든 컨트롤 떼기
|
|
|
|
Object.keys(this.controls).forEach((controlKey) => {
|
|
if (controlKey !== 'mtr') {
|
|
this.setControlVisible(controlKey, false)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
setFontSize(fontSize) {
|
|
this.fontSize = fontSize
|
|
this.texts.forEach((text) => {
|
|
text.set({ fontSize })
|
|
})
|
|
|
|
this.getObjects().forEach((obj) => {
|
|
if (obj.type[0] === 'Q') {
|
|
obj.setFontSize(fontSize)
|
|
}
|
|
})
|
|
|
|
this.addWithUpdate()
|
|
}
|
|
|
|
#addLengthText() {
|
|
if (this.texts.length > 0) {
|
|
this.texts.forEach((text) => {
|
|
this.canvas.remove(text)
|
|
})
|
|
this.texts = []
|
|
}
|
|
const points = this.points
|
|
|
|
points.forEach((start, i) => {
|
|
const end = points[(i + 1) % points.length]
|
|
const dx = end.x - start.x
|
|
const dy = end.y - start.y
|
|
const length = Math.sqrt(dx * dx + dy * dy)
|
|
|
|
const midPoint = new fabric.Point(
|
|
(start.x + end.x) / 2,
|
|
(start.y + end.y) / 2,
|
|
)
|
|
|
|
// Create new text object if it doesn't exist
|
|
const text = new fabric.Text(length.toFixed(0), {
|
|
left: midPoint.x,
|
|
top: midPoint.y,
|
|
fontSize: this.fontSize,
|
|
selectable: false,
|
|
})
|
|
|
|
this.texts.push(text)
|
|
this.addWithUpdate(text)
|
|
})
|
|
|
|
this.canvas.renderAll()
|
|
}
|
|
|
|
#updateLengthText() {
|
|
const points = this.getCurrentPoints()
|
|
|
|
points.forEach((start, i) => {
|
|
const end = points[(i + 1) % points.length]
|
|
const dx = end.x - start.x
|
|
const dy = end.y - start.y
|
|
const length = Math.sqrt(dx * dx + dy * dy)
|
|
|
|
// Update the text object with the new length
|
|
this.texts[i].set({ text: length.toFixed(0) })
|
|
})
|
|
|
|
this.canvas.renderAll()
|
|
}
|
|
|
|
fillCell(cell = { width: 50, height: 100, padding: 10 }) {
|
|
const points = this.getCurrentPoints()
|
|
let bounds
|
|
|
|
try {
|
|
bounds = fabric.util.makeBoundingBoxFromPoints(points)
|
|
} catch (error) {
|
|
alert('다각형의 꼭지점이 4개 이상이어야 합니다.')
|
|
return
|
|
}
|
|
|
|
for (
|
|
let x = bounds.left;
|
|
x < bounds.left + bounds.width;
|
|
x += cell.width + cell.padding
|
|
) {
|
|
for (
|
|
let y = bounds.top;
|
|
y < bounds.top + bounds.height;
|
|
y += cell.height + cell.padding
|
|
) {
|
|
const rect = new fabric.Rect({
|
|
left: x,
|
|
top: y,
|
|
width: cell.width,
|
|
height: cell.height,
|
|
fill: 'transparent',
|
|
stroke: 'black',
|
|
selectable: false,
|
|
})
|
|
|
|
const rectPoints = [
|
|
new fabric.Point(rect.left, rect.top),
|
|
new fabric.Point(rect.left + rect.width, rect.top),
|
|
new fabric.Point(rect.left, rect.top + rect.height),
|
|
new fabric.Point(rect.left + rect.width, rect.top + rect.height),
|
|
]
|
|
|
|
const isInside = rectPoints.every(
|
|
(rectPoint) =>
|
|
this.inPolygon(rectPoint) &&
|
|
this.#distanceFromEdge(rectPoint) >= cell.padding,
|
|
)
|
|
|
|
if (isInside) {
|
|
this.addWithUpdate(rect)
|
|
}
|
|
}
|
|
}
|
|
|
|
this.canvas.renderAll()
|
|
}
|
|
|
|
/**
|
|
* this.lines의 direction이 top 인 line의 모든 합이 bottom 인 line의 모든 합과 같은지 확인
|
|
* this.lines의 direction이 left 인 line의 모든 합이 right 인 line의 모든 합과 같은지 확인
|
|
* return {boolean}
|
|
*/
|
|
isValid() {
|
|
const leftLinesLengthSum = this.lines
|
|
.filter((line) => line.direction === 'left')
|
|
.reduce((sum, line) => sum + line.length, 0)
|
|
const rightLinesLengthSum = this.lines
|
|
.filter((line) => line.direction === 'right')
|
|
.reduce((sum, line) => sum + line.length, 0)
|
|
|
|
const topLinesLengthSum = this.lines
|
|
.filter((line) => line.direction === 'top')
|
|
.reduce((sum, line) => sum + line.length, 0)
|
|
const bottomLinesLengthSum = this.lines
|
|
.filter((line) => line.direction === 'bottom')
|
|
.reduce((sum, line) => sum + line.length, 0)
|
|
|
|
return (
|
|
leftLinesLengthSum === rightLinesLengthSum &&
|
|
topLinesLengthSum === bottomLinesLengthSum
|
|
)
|
|
}
|
|
|
|
inPolygon(point) {
|
|
const vertices = this.getCurrentPoints()
|
|
let intersects = 0
|
|
|
|
for (let i = 0; i < vertices.length; i++) {
|
|
let vertex1 = vertices[i]
|
|
let vertex2 = vertices[(i + 1) % vertices.length]
|
|
|
|
if (vertex1.y > vertex2.y) {
|
|
let tmp = vertex1
|
|
vertex1 = vertex2
|
|
vertex2 = tmp
|
|
}
|
|
|
|
if (point.y === vertex1.y || point.y === vertex2.y) {
|
|
point.y += 0.01
|
|
}
|
|
|
|
if (point.y <= vertex1.y || point.y > vertex2.y) {
|
|
continue
|
|
}
|
|
|
|
let xInt =
|
|
((point.y - vertex1.y) * (vertex2.x - vertex1.x)) /
|
|
(vertex2.y - vertex1.y) +
|
|
vertex1.x
|
|
if (xInt < point.x) {
|
|
intersects++
|
|
}
|
|
}
|
|
|
|
return intersects % 2 === 1
|
|
}
|
|
|
|
#distanceFromEdge(point) {
|
|
const vertices = this.getCurrentPoints()
|
|
let minDistance = Infinity
|
|
|
|
for (let i = 0; i < vertices.length; i++) {
|
|
let vertex1 = vertices[i]
|
|
let vertex2 = vertices[(i + 1) % vertices.length]
|
|
|
|
const dx = vertex2.x - vertex1.x
|
|
const dy = vertex2.y - vertex1.y
|
|
|
|
const t =
|
|
((point.x - vertex1.x) * dx + (point.y - vertex1.y) * dy) /
|
|
(dx * dx + dy * dy)
|
|
|
|
let closestPoint
|
|
if (t < 0) {
|
|
closestPoint = vertex1
|
|
} else if (t > 1) {
|
|
closestPoint = vertex2
|
|
} else {
|
|
closestPoint = new fabric.Point(vertex1.x + t * dx, vertex1.y + t * dy)
|
|
}
|
|
|
|
const distance = distanceBetweenPoints(point, closestPoint)
|
|
if (distance < minDistance) {
|
|
minDistance = distance
|
|
}
|
|
}
|
|
|
|
return minDistance
|
|
}
|
|
|
|
setViewLengthText(boolean) {
|
|
this.texts.forEach((text) => {
|
|
text.visible = boolean
|
|
})
|
|
|
|
this.canvas.renderAll()
|
|
}
|
|
|
|
getCurrentPoints() {
|
|
const scaleX = this.scaleX
|
|
const scaleY = this.scaleY
|
|
|
|
const left = this.left
|
|
const top = this.top
|
|
|
|
// 시작점
|
|
const point = this.points[0]
|
|
|
|
const movingX = left - point.x * scaleX
|
|
const movingY = top - point.y * scaleY
|
|
|
|
return this.points.map((point) => {
|
|
return {
|
|
x: point.x * scaleX + movingX,
|
|
y: point.y * scaleY + movingY,
|
|
}
|
|
})
|
|
}
|
|
|
|
fillBackground(pattern) {
|
|
this.polygon.set({ fill: pattern })
|
|
this.canvas.requestRenderAll()
|
|
}
|
|
|
|
// 보조선 그리기 사각형에서만
|
|
drawHelpLine(chon = 4) {
|
|
if (!this.isValid()) {
|
|
return
|
|
}
|
|
|
|
if (this.lines.length === 4) {
|
|
this.#drawHelpLineInRect(chon)
|
|
} else if (this.lines.length === 6) {
|
|
// TODO : 6각형
|
|
this.#drawHelpLineInHexagon(chon)
|
|
} else if (this.lines.length === 8) {
|
|
// TODO : 8각형
|
|
this.#drawHelpLineInOctagon(chon)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 현재 점 6개만 가능
|
|
*/
|
|
setShape() {
|
|
let shape = 0
|
|
if (this.lines.length !== 6) {
|
|
return
|
|
}
|
|
//외각선 기준
|
|
const topIndex = findTopTwoIndexesByDistance(this.lines).sort(
|
|
(a, b) => a - b,
|
|
) //배열중에 큰 2값을 가져옴 TODO: 나중에는 인자로 받아서 다각으로 수정 해야됨
|
|
|
|
//일단 배열 6개 짜리 기준의 선 번호
|
|
if (topIndex[0] === 4) {
|
|
if (topIndex[1] === 5) {
|
|
//1번
|
|
shape = 1
|
|
}
|
|
} else if (topIndex[0] === 1) {
|
|
//4번
|
|
if (topIndex[1] === 2) {
|
|
shape = 4
|
|
}
|
|
} else if (topIndex[0] === 0) {
|
|
if (topIndex[1] === 1) {
|
|
//2번
|
|
shape = 2
|
|
} else if (topIndex[1] === 5) {
|
|
//3번
|
|
shape = 3
|
|
}
|
|
}
|
|
|
|
this.shape = shape
|
|
}
|
|
|
|
/**
|
|
* 현재 점 6개만 가능
|
|
* @returns {number}
|
|
*/
|
|
getShape() {
|
|
return this.shape
|
|
}
|
|
|
|
#drawHelpLineInRect(chon) {
|
|
let type = 1
|
|
let smallestLength = Infinity
|
|
let maxLength = 0
|
|
|
|
this.lines.forEach((line) => {
|
|
if (line.length < smallestLength) {
|
|
smallestLength = line.length
|
|
}
|
|
if (line.length > maxLength) {
|
|
maxLength = line.length
|
|
}
|
|
})
|
|
|
|
// QPolygon 객체의 모든 선들을 가져옵니다.
|
|
const lines = [...this.lines]
|
|
|
|
// 이 선들을 길이에 따라 정렬합니다.
|
|
lines.sort((a, b) => a.length - b.length)
|
|
|
|
// 정렬된 배열에서 가장 작은 두 선을 선택합니다.
|
|
let smallestLines
|
|
|
|
if (smallestLength === maxLength) {
|
|
// 정사각형인 경우 0, 2번째 라인이 가장 짧은 라인
|
|
|
|
smallestLines = [lines[0], lines[2]]
|
|
} else {
|
|
smallestLines = lines.slice(0, 2)
|
|
}
|
|
|
|
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(chon)),
|
|
)
|
|
|
|
// 옆으로 누워있는 지붕의 높이
|
|
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(chon)),
|
|
)
|
|
|
|
// 용마루
|
|
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)
|
|
if (smallestLength !== maxLength) {
|
|
// 정사각형이 아닌경우에만 용마루를 추가한다.
|
|
this.canvas.add(ridge)
|
|
}
|
|
}
|
|
|
|
#drawHelpLineInHexagon(chon) {
|
|
let type = this.shape
|
|
|
|
// 1 = 0, 3
|
|
// 2 = 2, 5
|
|
// 3 = 1, 4
|
|
// 4 = 0, 3
|
|
|
|
// 라인 기준점 1,2
|
|
let lines, lines2
|
|
// 용마루 시작점 2개
|
|
let vPoint1, vPoint2
|
|
// 용마루 시작점과 만나는 지붕의 중앙
|
|
let centerPoint1, centerPoint2
|
|
|
|
// 용마루 길이
|
|
let ridgeLength = 0
|
|
let ridgePoint1, ridgePoint2
|
|
if (type === 1) {
|
|
lines = [this.lines[0], this.lines[3]]
|
|
lines2 = [this.lines[1], this.lines[4]]
|
|
vPoint1 = {
|
|
x: lines[0].x1 + lines[0].length / 2,
|
|
y: lines[0].y1 + lines[0].length / 2,
|
|
}
|
|
vPoint2 = {
|
|
x: lines[1].x1 + lines[1].length / 2,
|
|
y: lines[1].y1 - lines[1].length / 2,
|
|
}
|
|
centerPoint1 = {
|
|
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
}
|
|
centerPoint2 = {
|
|
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
}
|
|
|
|
ridgeLength = Math.min(this.lines[1].length, this.lines[2].length)
|
|
ridgePoint1 = [vPoint1.x, vPoint1.y, vPoint1.x + ridgeLength, vPoint1.y]
|
|
ridgePoint2 = [vPoint2.x, vPoint2.y, vPoint2.x, vPoint2.y - ridgeLength]
|
|
} else if (type === 2) {
|
|
lines = [this.lines[2], this.lines[5]]
|
|
lines2 = [this.lines[0], this.lines[3]]
|
|
vPoint1 = {
|
|
x: lines[0].x1 - lines[0].length / 2,
|
|
y: lines[0].y1 - lines[0].length / 2,
|
|
}
|
|
vPoint2 = {
|
|
x: lines[1].x1 - lines[1].length / 2,
|
|
y: lines[1].y1 + lines[1].length / 2,
|
|
}
|
|
centerPoint1 = {
|
|
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
}
|
|
centerPoint2 = {
|
|
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
}
|
|
|
|
ridgeLength = Math.min(this.lines[3].length, this.lines[4].length)
|
|
ridgePoint1 = [vPoint1.x, vPoint1.y, vPoint1.x - ridgeLength, vPoint1.y]
|
|
ridgePoint2 = [vPoint2.x, vPoint2.y, vPoint2.x, vPoint2.y + ridgeLength]
|
|
} else if (type === 3) {
|
|
lines = [this.lines[1], this.lines[4]]
|
|
lines2 = [this.lines[2], this.lines[5]]
|
|
vPoint1 = {
|
|
x: lines[0].x1 + lines[0].length / 2,
|
|
y: lines[0].y1 - lines[0].length / 2,
|
|
}
|
|
vPoint2 = {
|
|
x: lines[1].x1 - lines[1].length / 2,
|
|
y: lines[1].y1 - lines[1].length / 2,
|
|
}
|
|
centerPoint1 = {
|
|
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
}
|
|
centerPoint2 = {
|
|
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
}
|
|
|
|
ridgeLength = Math.min(this.lines[2].length, this.lines[3].length)
|
|
ridgePoint1 = [vPoint1.x, vPoint1.y, vPoint1.x, vPoint1.y - ridgeLength]
|
|
ridgePoint2 = [vPoint2.x, vPoint2.y, vPoint2.x - ridgeLength, vPoint2.y]
|
|
} else if (type === 4) {
|
|
lines = [this.lines[0], this.lines[3]]
|
|
lines2 = [this.lines[1], this.lines[4]]
|
|
vPoint1 = {
|
|
x: lines[0].x1 + lines[0].length / 2,
|
|
y: lines[0].y1 + lines[0].length / 2,
|
|
}
|
|
vPoint2 = {
|
|
x: lines[1].x1 - lines[1].length / 2,
|
|
y: lines[1].y1 + lines[1].length / 2,
|
|
}
|
|
centerPoint1 = {
|
|
x: (lines[0].x1 + lines[0].x2) / 2,
|
|
y: (lines[0].y1 + lines[0].y2) / 2,
|
|
}
|
|
centerPoint2 = {
|
|
x: (lines[1].x1 + lines[1].x2) / 2,
|
|
y: (lines[1].y1 + lines[1].y2) / 2,
|
|
}
|
|
|
|
ridgeLength = Math.min(this.lines[4].length, this.lines[5].length)
|
|
ridgePoint1 = [vPoint1.x, vPoint1.y, vPoint1.x + ridgeLength, vPoint1.y]
|
|
ridgePoint2 = [vPoint2.x, vPoint2.y, vPoint2.x, vPoint2.y + ridgeLength]
|
|
}
|
|
|
|
const realLine1 = new QLine(
|
|
[lines[0].x1, lines[0].y1, vPoint1.x, vPoint1.y],
|
|
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
getRoofHypotenuse(lines[0].length / 2),
|
|
)
|
|
|
|
const realLine2 = new QLine(
|
|
[lines[0].x2, lines[0].y2, vPoint1.x, vPoint1.y],
|
|
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
getRoofHypotenuse(lines[0].length / 2),
|
|
)
|
|
|
|
const realLine3 = new QLine(
|
|
[lines[1].x1, lines[1].y1, vPoint2.x, vPoint2.y],
|
|
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
getRoofHypotenuse(lines[1].length / 2),
|
|
)
|
|
|
|
const realLine4 = new QLine(
|
|
[lines[1].x2, lines[1].y2, vPoint2.x, vPoint2.y],
|
|
{ fontSize: this.fontSize, stroke: 'blue', strokeWidth: 1 },
|
|
getRoofHypotenuse(lines[1].length / 2),
|
|
)
|
|
|
|
// 옆으로 누워있는 지붕의 높이 점선
|
|
const realLine5 = new QLine(
|
|
[vPoint1.x, vPoint1.y, centerPoint1.x, centerPoint1.y],
|
|
{
|
|
fontSize: this.fontSize,
|
|
stroke: 'blue',
|
|
strokeWidth: 1,
|
|
strokeDashArray: [5, 5],
|
|
},
|
|
getRoofHeight(lines[0].length / 2, getDegreeByChon(chon)),
|
|
)
|
|
|
|
// 옆으로 누워있는 지붕의 높이 점선
|
|
const realLine6 = new QLine(
|
|
[vPoint2.x, vPoint2.y, centerPoint2.x, centerPoint2.y],
|
|
{
|
|
fontSize: this.fontSize,
|
|
stroke: 'blue',
|
|
strokeWidth: 1,
|
|
strokeDashArray: [5, 5],
|
|
},
|
|
getRoofHeight(lines[1].length / 2, getDegreeByChon(chon)),
|
|
)
|
|
|
|
// 용마루 보조선
|
|
const ridgeHelpLine1 = new QLine(
|
|
[lines2[0].x2, lines2[0].y2, ridgePoint1[2], ridgePoint1[3]],
|
|
{
|
|
fontSize: this.fontSize,
|
|
stroke: 'blue',
|
|
strokeWidth: 1,
|
|
},
|
|
getRoofHypotenuse(lines[0].length / 2),
|
|
)
|
|
|
|
// 용마루 보조선
|
|
const ridgeHelpLine2 = new QLine(
|
|
[lines2[1].x2, lines2[1].y2, ridgePoint2[2], ridgePoint2[3]],
|
|
{
|
|
fontSize: this.fontSize,
|
|
stroke: 'blue',
|
|
strokeWidth: 1,
|
|
},
|
|
getRoofHypotenuse(lines[1].length / 2),
|
|
)
|
|
|
|
// 용마루
|
|
const ridge1 = new QLine(ridgePoint1, {
|
|
fontSize: this.fontSize,
|
|
stroke: 'blue',
|
|
strokeWidth: 1,
|
|
})
|
|
|
|
// 용마루
|
|
const ridge2 = new QLine(ridgePoint2, {
|
|
fontSize: this.fontSize,
|
|
stroke: 'blue',
|
|
strokeWidth: 1,
|
|
})
|
|
|
|
const ridgeEndLine = new QLine(
|
|
[ridgePoint1[2], ridgePoint1[3], ridgePoint2[2], ridgePoint2[3]],
|
|
{
|
|
fontSize: this.fontSize,
|
|
stroke: 'blue',
|
|
strokeWidth: 1,
|
|
},
|
|
Math.abs(realLine1.length - realLine3.length),
|
|
)
|
|
this.helpLines = [
|
|
realLine1,
|
|
realLine2,
|
|
realLine3,
|
|
realLine4,
|
|
realLine5,
|
|
realLine6,
|
|
ridge1,
|
|
ridge2,
|
|
ridgeEndLine,
|
|
]
|
|
this.addWithUpdate(realLine1)
|
|
this.addWithUpdate(realLine2)
|
|
this.addWithUpdate(realLine3)
|
|
this.addWithUpdate(realLine4)
|
|
this.addWithUpdate(realLine5)
|
|
this.addWithUpdate(realLine6)
|
|
this.addWithUpdate(ridgeHelpLine1)
|
|
this.addWithUpdate(ridgeHelpLine2)
|
|
this.addWithUpdate(ridge1)
|
|
this.addWithUpdate(ridge2)
|
|
this.addWithUpdate(ridgeEndLine)
|
|
|
|
this.canvas.renderAll()
|
|
}
|
|
|
|
#drawHelpLineInOctagon(chon) {}
|
|
}
|