Merge branch 'feature/test' into feature/test-jy
# Conflicts: # src/components/Roof2.jsx # src/components/fabric/QPolygon.js # src/hooks/useMode.js
This commit is contained in:
commit
e29d581f10
@ -3,7 +3,6 @@ import { useEffect, useState } from 'react'
|
|||||||
import { Mode, useMode } from '@/hooks/useMode'
|
import { Mode, useMode } from '@/hooks/useMode'
|
||||||
import { Button } from '@nextui-org/react'
|
import { Button } from '@nextui-org/react'
|
||||||
import QRect from '@/components/fabric/QRect'
|
import QRect from '@/components/fabric/QRect'
|
||||||
import QPolygon from '@/components/fabric/QPolygon'
|
|
||||||
|
|
||||||
import RangeSlider from './ui/RangeSlider'
|
import RangeSlider from './ui/RangeSlider'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
@ -11,6 +10,8 @@ import { canvasSizeState, fontSizeState, sortedPolygonArray } from '@/store/canv
|
|||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { getCanvasState, insertCanvasState } from '@/lib/canvas'
|
import { getCanvasState, insertCanvasState } from '@/lib/canvas'
|
||||||
import { calculateIntersection2 } from '@/util/canvas-util'
|
import { calculateIntersection2 } from '@/util/canvas-util'
|
||||||
|
import { CustomLine } from '@/components/fabric/QLine'
|
||||||
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
|
|
||||||
export default function Roof2() {
|
export default function Roof2() {
|
||||||
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
|
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
|
||||||
@ -99,12 +100,10 @@ export default function Roof2() {
|
|||||||
selectable: true,
|
selectable: true,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
},
|
},
|
||||||
canvas,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
canvas?.add(polygon)
|
canvas?.add(polygon)
|
||||||
|
|
||||||
polygon.fillCell({ width: 50, height: 30, padding: 10 })
|
// polygon.fillCell({ width: 50, height: 30, padding: 10 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,14 +185,14 @@ export default function Roof2() {
|
|||||||
]
|
]
|
||||||
|
|
||||||
const eightPoint = [
|
const eightPoint = [
|
||||||
{ x: 240, y: 130 },
|
{ x: 240.1111, y: 130.1111 },
|
||||||
{ x: 240, y: 630 },
|
{ x: 240.1111, y: 630.1111 },
|
||||||
{ x: 640, y: 630 },
|
{ x: 640.1111, y: 630.1111 },
|
||||||
{ x: 640, y: 480 },
|
{ x: 640.1111, y: 480.1111 },
|
||||||
{ x: 440, y: 480 },
|
{ x: 440.1111, y: 480.1111 },
|
||||||
{ x: 440, y: 280 },
|
{ x: 440.1111, y: 280.1111 },
|
||||||
{ x: 740, y: 280 },
|
{ x: 740.1111, y: 280.1111 },
|
||||||
{ x: 740, y: 130 },
|
{ x: 740.1111, y: 130.1111 },
|
||||||
]
|
]
|
||||||
|
|
||||||
const eightPoint2 = [
|
const eightPoint2 = [
|
||||||
@ -251,8 +250,6 @@ export default function Roof2() {
|
|||||||
|
|
||||||
canvas?.add(polygon)
|
canvas?.add(polygon)
|
||||||
|
|
||||||
console.log(polygon)
|
|
||||||
|
|
||||||
handleOuterlinesTest2(polygon)
|
handleOuterlinesTest2(polygon)
|
||||||
|
|
||||||
// const lines = togglePolygonLine(polygon)
|
// const lines = togglePolygonLine(polygon)
|
||||||
@ -273,27 +270,19 @@ export default function Roof2() {
|
|||||||
|
|
||||||
const makeQLine = () => {
|
const makeQLine = () => {
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
const line = new QLine(
|
const line = new QLine([50, 250, 900, 250], {
|
||||||
[50, 250, 900, 250],
|
stroke: 'black',
|
||||||
{
|
strokeWidth: 5,
|
||||||
stroke: 'black',
|
fontSize: fontSize,
|
||||||
strokeWidth: 5,
|
selectable: true,
|
||||||
fontSize: fontSize,
|
})
|
||||||
selectable: true,
|
|
||||||
},
|
|
||||||
50,
|
|
||||||
)
|
|
||||||
|
|
||||||
const line2 = new QLine(
|
const line2 = new QLine([450, 450, 821, 78], {
|
||||||
[450, 450, 821, 78],
|
stroke: 'black',
|
||||||
{
|
strokeWidth: 5,
|
||||||
stroke: 'black',
|
fontSize: fontSize,
|
||||||
strokeWidth: 5,
|
selectable: true,
|
||||||
fontSize: fontSize,
|
})
|
||||||
selectable: true,
|
|
||||||
},
|
|
||||||
50,
|
|
||||||
)
|
|
||||||
|
|
||||||
canvas?.add(line)
|
canvas?.add(line)
|
||||||
canvas?.add(line2)
|
canvas?.add(line2)
|
||||||
@ -301,8 +290,6 @@ export default function Roof2() {
|
|||||||
const interSectionPoint = calculateIntersection2(line, line2)
|
const interSectionPoint = calculateIntersection2(line, line2)
|
||||||
|
|
||||||
if (interSectionPoint) {
|
if (interSectionPoint) {
|
||||||
console.log(interSectionPoint)
|
|
||||||
|
|
||||||
const circle = new fabric.Circle({
|
const circle = new fabric.Circle({
|
||||||
radius: 5,
|
radius: 5,
|
||||||
fill: 'red',
|
fill: 'red',
|
||||||
|
|||||||
@ -1,112 +1,87 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { getDirection, getDirectionByPoint } from '@/util/canvas-util'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { getDirection } from '@/util/canvas-util'
|
||||||
|
|
||||||
export class QLine extends fabric.Group {
|
export const QLine = fabric.util.createClass(fabric.Line, {
|
||||||
line
|
type: 'QLine',
|
||||||
text
|
text: null,
|
||||||
fontSize
|
id: null,
|
||||||
length = 0
|
line: null,
|
||||||
x1
|
length: 0,
|
||||||
y1
|
direction: null,
|
||||||
x2
|
idx: 0,
|
||||||
y2
|
initialize: function (points, options, canvas) {
|
||||||
direction
|
this.callSuper('initialize', points, options)
|
||||||
idx
|
if (options.id) {
|
||||||
type = 'QLine'
|
this.id = options.id
|
||||||
parent
|
} else {
|
||||||
isAlreadyInterSection = false
|
this.id = uuidv4()
|
||||||
|
}
|
||||||
interSectionPoints = []
|
this.line = this
|
||||||
lengthTxt = 0
|
|
||||||
|
|
||||||
initPoints
|
|
||||||
initOption
|
|
||||||
initLengthTxt
|
|
||||||
|
|
||||||
constructor(points, option = { isActiveLengthText: true }, lengthTxt) {
|
|
||||||
// 소수점 전부 제거
|
// 소수점 전부 제거
|
||||||
points.forEach((point) => {
|
points.forEach((point) => {
|
||||||
point = Math.round(point)
|
point = Math.round(point)
|
||||||
})
|
})
|
||||||
|
|
||||||
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.initPoints = points
|
|
||||||
this.initOption = option
|
|
||||||
this.initLengthTxt = lengthTxt
|
|
||||||
|
|
||||||
this.x1 = x1
|
|
||||||
this.y1 = y1
|
|
||||||
this.x2 = x2
|
|
||||||
this.y2 = y2
|
|
||||||
this.line = line
|
|
||||||
this.fontSize = option.fontSize
|
|
||||||
this.direction = option.direction ?? getDirectionByPoint({ x: x1, y: y1 }, { x: x2, y: y2 })
|
|
||||||
this.parent = option.parent
|
|
||||||
this.idx = option.idx
|
|
||||||
|
|
||||||
if (lengthTxt > 0) {
|
|
||||||
this.lengthTxt = Number(lengthTxt)
|
|
||||||
}
|
|
||||||
|
|
||||||
option.isActiveLengthText ?? 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', () => {
|
|
||||||
console.log(this)
|
|
||||||
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 scaleX = this.scaleX
|
||||||
const scaleY = this.scaleY
|
const scaleY = this.scaleY
|
||||||
const x1 = this.left
|
const x1 = this.left
|
||||||
const y1 = this.top
|
const y1 = this.top
|
||||||
const x2 = this.left + this.width * scaleX
|
const x2 = this.left + this.width * scaleX
|
||||||
const y2 = this.top + this.height * scaleY
|
const y2 = this.top + this.height * scaleY
|
||||||
|
this.idx = options.idx ?? 0
|
||||||
|
const dx = x2 - x1
|
||||||
|
const dy = y2 - y1
|
||||||
|
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0))
|
||||||
|
|
||||||
|
this.direction = options.direction ?? getDirection({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
|
||||||
|
|
||||||
|
if (canvas) {
|
||||||
|
this.canvas = canvas
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
toObject: function (propertiesToInclude) {
|
||||||
|
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
|
||||||
|
type: this.type,
|
||||||
|
text: this.text,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
this.addLengthText()
|
||||||
|
|
||||||
|
this.on('moving', () => {
|
||||||
|
this.addLengthText()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.on('modified', (e) => {
|
||||||
|
this.addLengthText()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.on('removed', () => {
|
||||||
|
const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
||||||
|
if (thisText) {
|
||||||
|
this.canvas.remove(thisText)
|
||||||
|
}
|
||||||
|
this.text = null
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
addLengthText() {
|
||||||
|
const thisText = this.canvas.getObjects().find((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if (thisText) {
|
||||||
|
thisText.set({ text: this.length.toFixed(0).toString(), left: (x1 + x2) / 2, top: (y1 + y2) / 2 })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const dx = x2 - x1
|
const dx = x2 - x1
|
||||||
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))
|
||||||
@ -115,51 +90,27 @@ export class QLine extends fabric.Group {
|
|||||||
left: (x1 + x2) / 2,
|
left: (x1 + x2) / 2,
|
||||||
top: (y1 + y2) / 2,
|
top: (y1 + y2) / 2,
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
|
selectable: false,
|
||||||
|
parentId: this.id,
|
||||||
|
name: 'lengthText',
|
||||||
})
|
})
|
||||||
this.text = text
|
|
||||||
this.addWithUpdate(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this.text = text
|
||||||
|
this.canvas.add(text)
|
||||||
|
},
|
||||||
setFontSize(fontSize) {
|
setFontSize(fontSize) {
|
||||||
this.fontSize = fontSize
|
this.fontSize = fontSize
|
||||||
this.text.set({ fontSize })
|
this.text.set({ fontSize })
|
||||||
this.addWithUpdate()
|
},
|
||||||
}
|
_render: function (ctx) {
|
||||||
|
this.callSuper('_render', ctx)
|
||||||
fromObject(object, callback) {
|
this.init()
|
||||||
console.log('fromObject', object, callback)
|
},
|
||||||
}
|
_set: function (key, value) {
|
||||||
|
|
||||||
async = true
|
|
||||||
|
|
||||||
toObject(propertiesToInclude) {
|
|
||||||
return fabric.util.object.extend(this.callSuper('toObject'), {
|
|
||||||
length: this.length,
|
|
||||||
line: this.line,
|
|
||||||
text: this.text,
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
x1: this.x1,
|
|
||||||
y1: this.y1,
|
|
||||||
x2: this.x2,
|
|
||||||
y2: this.y2,
|
|
||||||
direction: this.direction,
|
|
||||||
idx: this.idx,
|
|
||||||
type: this.type,
|
|
||||||
parent: this.parent,
|
|
||||||
isAlreadyInterSection: this.isAlreadyInterSection,
|
|
||||||
interSectionPoints: this.interSectionPoints,
|
|
||||||
lengthTxt: this.lengthTxt,
|
|
||||||
setFontSize: this.setFontSize,
|
|
||||||
addLengthText: this.addLengthText,
|
|
||||||
init: this.init,
|
|
||||||
addControl: this.addControl,
|
|
||||||
initPoints: this.initPoints,
|
|
||||||
initOption: this.initOption,
|
|
||||||
initLengthTxt: this.initLengthTxt,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_set(key, value) {
|
|
||||||
this.callSuper('_set', key, value)
|
this.callSuper('_set', key, value)
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
setCanvas(canvas) {
|
||||||
|
this.canvas = canvas
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|||||||
184
src/components/fabric/QLine2.js
Normal file
184
src/components/fabric/QLine2.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
/**
|
||||||
|
* 문제 없는경우 제거
|
||||||
|
*/
|
||||||
|
import { fabric } from 'fabric'
|
||||||
|
import { getDirection, getDirectionByPoint } from '@/util/canvas-util'
|
||||||
|
|
||||||
|
export class QLine2 extends fabric.Group {
|
||||||
|
line
|
||||||
|
text
|
||||||
|
fontSize
|
||||||
|
length = 0
|
||||||
|
x1
|
||||||
|
y1
|
||||||
|
x2
|
||||||
|
y2
|
||||||
|
direction
|
||||||
|
idx
|
||||||
|
type = 'QLine2'
|
||||||
|
parent
|
||||||
|
isAlreadyInterSection = false
|
||||||
|
|
||||||
|
interSectionPoints = []
|
||||||
|
lengthTxt = 0
|
||||||
|
|
||||||
|
initPoints
|
||||||
|
initOption
|
||||||
|
initLengthTxt
|
||||||
|
|
||||||
|
constructor(points, option = { isActiveLengthText: true }, lengthTxt) {
|
||||||
|
// 소수점 전부 제거
|
||||||
|
points.forEach((point) => {
|
||||||
|
point = Math.round(point)
|
||||||
|
})
|
||||||
|
|
||||||
|
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 })
|
||||||
|
|
||||||
|
// 길이가 1이하인 선은 생성하지 않음
|
||||||
|
if (Math.abs(x1 - x2) <= 1 && Math.abs(y1 - y2) <= 1) {
|
||||||
|
super([], {})
|
||||||
|
this.initPoints = points
|
||||||
|
this.initOption = option
|
||||||
|
this.initLengthTxt = lengthTxt
|
||||||
|
} else {
|
||||||
|
super([line], {})
|
||||||
|
this.initPoints = points
|
||||||
|
this.initOption = option
|
||||||
|
this.initLengthTxt = lengthTxt
|
||||||
|
|
||||||
|
this.x1 = x1
|
||||||
|
this.y1 = y1
|
||||||
|
this.x2 = x2
|
||||||
|
this.y2 = y2
|
||||||
|
this.line = line
|
||||||
|
this.fontSize = option.fontSize
|
||||||
|
this.direction = option.direction ?? getDirectionByPoint({ x: x1, y: y1 }, { x: x2, y: y2 })
|
||||||
|
this.parent = option.parent
|
||||||
|
this.idx = option.idx
|
||||||
|
|
||||||
|
if (lengthTxt > 0) {
|
||||||
|
this.lengthTxt = Number(lengthTxt)
|
||||||
|
}
|
||||||
|
|
||||||
|
option.isActiveLengthText ?? 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', () => {
|
||||||
|
console.log(this)
|
||||||
|
Object.keys(this.controls).forEach((controlKey) => {
|
||||||
|
if (controlKey !== 'ml' && controlKey !== 'mr') {
|
||||||
|
this.setControlVisible(controlKey, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromObject(object, callback) {
|
||||||
|
const { points, initOption, initLengthTxt } = object
|
||||||
|
const instance = new QLine(points, initOption, initLengthTxt)
|
||||||
|
callback && callback(instance)
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
fromObject(object, callback) {
|
||||||
|
console.log('fromObject', object, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
async = true
|
||||||
|
|
||||||
|
toObject(propertiesToInclude) {
|
||||||
|
return fabric.util.object.extend(this.callSuper('toObject'), {
|
||||||
|
length: this.length,
|
||||||
|
line: this.line,
|
||||||
|
text: this.text,
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
x1: this.x1,
|
||||||
|
y1: this.y1,
|
||||||
|
x2: this.x2,
|
||||||
|
y2: this.y2,
|
||||||
|
direction: this.direction,
|
||||||
|
idx: this.idx,
|
||||||
|
type: this.type,
|
||||||
|
parent: this.parent,
|
||||||
|
isAlreadyInterSection: this.isAlreadyInterSection,
|
||||||
|
interSectionPoints: this.interSectionPoints,
|
||||||
|
lengthTxt: this.lengthTxt,
|
||||||
|
setFontSize: this.setFontSize,
|
||||||
|
addLengthText: this.addLengthText,
|
||||||
|
init: this.init,
|
||||||
|
addControl: this.addControl,
|
||||||
|
initPoints: this.initPoints,
|
||||||
|
initOption: this.initOption,
|
||||||
|
initLengthTxt: this.initLengthTxt,
|
||||||
|
points: this.points,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_set(key, value) {
|
||||||
|
this.callSuper('_set', key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,75 +1,107 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import {
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
calculateIntersection,
|
|
||||||
calculateIntersection2,
|
|
||||||
distanceBetweenPoints,
|
|
||||||
findClosestLineToPoint,
|
|
||||||
findTopTwoIndexesByDistance,
|
|
||||||
getAdjacent,
|
|
||||||
getDegreeByChon,
|
|
||||||
getDirectionByPoint,
|
|
||||||
getRoofHeight,
|
|
||||||
getRoofHypotenuse,
|
|
||||||
sortedPoints,
|
|
||||||
} from '@/util/canvas-util'
|
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPoints } from '@/util/canvas-util'
|
||||||
|
import { drawHelpLineInHexagon } from '@/util/qpolygon-utils'
|
||||||
|
|
||||||
export default class QPolygon extends fabric.Group {
|
export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||||
type = 'QPolygon'
|
type: 'QPolygon',
|
||||||
polygon
|
lines: [],
|
||||||
points
|
texts: [],
|
||||||
texts = []
|
id: null,
|
||||||
lines = []
|
length: 0,
|
||||||
canvas
|
initialize: function (points, options, canvas) {
|
||||||
fontSize
|
|
||||||
qCells = []
|
|
||||||
name
|
|
||||||
shape = 0 // 점 6개일때의 shape 모양
|
|
||||||
helpPoints = []
|
|
||||||
helpLines = []
|
|
||||||
|
|
||||||
wall
|
|
||||||
initPoints
|
|
||||||
|
|
||||||
initOption
|
|
||||||
ridges = []
|
|
||||||
hips = []
|
|
||||||
innerLines = []
|
|
||||||
|
|
||||||
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.')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 소수점 전부 제거
|
// 소수점 전부 제거
|
||||||
points.forEach((point) => {
|
points.forEach((point) => {
|
||||||
point.x = Math.round(point.x)
|
point.x = Math.round(point.x)
|
||||||
point.y = Math.round(point.y)
|
point.y = Math.round(point.y)
|
||||||
})
|
})
|
||||||
|
points = sortedPoints(points)
|
||||||
|
this.callSuper('initialize', points, options)
|
||||||
|
if (options.id) {
|
||||||
|
this.id = options.id
|
||||||
|
} else {
|
||||||
|
this.id = uuidv4()
|
||||||
|
}
|
||||||
|
|
||||||
const sortPoints = sortedPoints(points)
|
if (canvas) {
|
||||||
const polygon = new fabric.Polygon(sortPoints, options)
|
this.canvas = canvas
|
||||||
|
}
|
||||||
super([polygon], { selectable: false })
|
|
||||||
|
|
||||||
this.fontSize = options.fontSize
|
|
||||||
this.points = sortPoints
|
|
||||||
this.polygon = polygon
|
|
||||||
this.name = options.name
|
|
||||||
|
|
||||||
this.initPoints = points
|
|
||||||
this.initOption = options
|
|
||||||
|
|
||||||
this.init()
|
this.init()
|
||||||
this.addEvent()
|
|
||||||
this.initLines()
|
this.initLines()
|
||||||
this.setShape()
|
this.setShape()
|
||||||
}
|
},
|
||||||
|
|
||||||
|
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
|
||||||
|
},
|
||||||
|
|
||||||
|
toObject: function (propertiesToInclude) {
|
||||||
|
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
|
||||||
|
type: this.type,
|
||||||
|
text: this.text,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
init: function () {
|
||||||
|
this.addLengthText()
|
||||||
|
|
||||||
|
this.on('moving', () => {
|
||||||
|
this.addLengthText()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.on('modified', (e) => {
|
||||||
|
this.addLengthText()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.on('selected', () => {
|
||||||
|
Object.keys(this.controls).forEach((controlKey) => {
|
||||||
|
if (controlKey !== 'ml' && controlKey !== 'mr') {
|
||||||
|
this.setControlVisible(controlKey, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
this.on('removed', () => {
|
||||||
|
const thisText = this.canvas.getObjects().filter((obj) => obj.name === 'lengthText' && obj.parentId === this.id)
|
||||||
|
thisText.forEach((text) => {
|
||||||
|
this.canvas.remove(text)
|
||||||
|
})
|
||||||
|
this.texts = null
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
initLines() {
|
initLines() {
|
||||||
|
this.lines = []
|
||||||
|
|
||||||
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], {
|
||||||
@ -77,61 +109,28 @@ export default class QPolygon extends fabric.Group {
|
|||||||
strokeWidth: this.strokeWidth,
|
strokeWidth: this.strokeWidth,
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
direction: getDirectionByPoint(point, nextPoint),
|
direction: getDirectionByPoint(point, nextPoint),
|
||||||
|
idx: i,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.lines.push(line)
|
this.lines.push(line)
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
|
|
||||||
init() {
|
// 보조선 그리기
|
||||||
this.addLengthText()
|
drawHelpLine(chon = 4) {
|
||||||
}
|
drawHelpLineInHexagon(this, chon)
|
||||||
|
},
|
||||||
addEvent() {
|
|
||||||
this.on('scaling', (e) => {
|
|
||||||
this.updateLengthText()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.on('selected', function() {
|
|
||||||
// 모든 컨트롤 떼기
|
|
||||||
|
|
||||||
Object.keys(this.controls).forEach((controlKey) => {
|
|
||||||
if (controlKey !== 'mtr') {
|
|
||||||
this.setControlVisible(controlKey, false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setWall(wall) {
|
|
||||||
this.wall = wall
|
|
||||||
}
|
|
||||||
|
|
||||||
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.canvas.add()
|
|
||||||
}
|
|
||||||
|
|
||||||
addLengthText() {
|
addLengthText() {
|
||||||
if (this.texts.length > 0) {
|
const points = this.getCurrentPoints()
|
||||||
this.texts.forEach((text) => {
|
|
||||||
this.canvas.remove(text)
|
|
||||||
})
|
|
||||||
this.texts = []
|
|
||||||
}
|
|
||||||
const points = this.points
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
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
|
||||||
@ -145,31 +144,29 @@ export default class QPolygon extends fabric.Group {
|
|||||||
top: midPoint.y,
|
top: midPoint.y,
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
|
parentId: this.id,
|
||||||
|
idx: i,
|
||||||
|
name: 'lengthText',
|
||||||
})
|
})
|
||||||
|
|
||||||
this.texts.push(text)
|
this.texts.push(text)
|
||||||
this.canvas.add(text)
|
this.canvas.add(text)
|
||||||
|
this.canvas.renderAll()
|
||||||
})
|
})
|
||||||
|
},
|
||||||
this.canvas.renderAll()
|
setFontSize(fontSize) {
|
||||||
}
|
this.fontSize = fontSize
|
||||||
|
this.text.set({ fontSize })
|
||||||
updateLengthText() {
|
},
|
||||||
const points = this.getCurrentPoints()
|
_render: function (ctx) {
|
||||||
|
this.callSuper('_render', ctx)
|
||||||
points.forEach((start, i) => {
|
},
|
||||||
const end = points[(i + 1) % points.length]
|
_set: function (key, value) {
|
||||||
const dx = end.x - start.x
|
this.callSuper('_set', key, value)
|
||||||
const dy = end.y - start.y
|
},
|
||||||
const length = Math.sqrt(dx * dx + dy * dy)
|
setCanvas(canvas) {
|
||||||
|
this.canvas = canvas
|
||||||
// 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 }) {
|
fillCell(cell = { width: 50, height: 100, padding: 10 }) {
|
||||||
const points = this.getCurrentPoints()
|
const points = this.getCurrentPoints()
|
||||||
let bounds
|
let bounds
|
||||||
@ -209,23 +206,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.canvas.renderAll()
|
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) {
|
inPolygon(point) {
|
||||||
const vertices = this.getCurrentPoints()
|
const vertices = this.getCurrentPoints()
|
||||||
let intersects = 0
|
let intersects = 0
|
||||||
@ -255,7 +236,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return intersects % 2 === 1
|
return intersects % 2 === 1
|
||||||
}
|
},
|
||||||
|
|
||||||
distanceFromEdge(point) {
|
distanceFromEdge(point) {
|
||||||
const vertices = this.getCurrentPoints()
|
const vertices = this.getCurrentPoints()
|
||||||
@ -286,16 +267,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return minDistance
|
return minDistance
|
||||||
}
|
},
|
||||||
|
|
||||||
setViewLengthText(boolean) {
|
|
||||||
this.texts.forEach((text) => {
|
|
||||||
text.visible = boolean
|
|
||||||
})
|
|
||||||
|
|
||||||
this.canvas.renderAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
getCurrentPoints() {
|
getCurrentPoints() {
|
||||||
const scaleX = this.scaleX
|
const scaleX = this.scaleX
|
||||||
const scaleY = this.scaleY
|
const scaleY = this.scaleY
|
||||||
@ -315,6 +287,16 @@ export default class QPolygon extends fabric.Group {
|
|||||||
y: point.y * scaleY + movingY,
|
y: point.y * scaleY + movingY,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
setWall: function (wall) {
|
||||||
|
this.wall = wall
|
||||||
|
},
|
||||||
|
setViewLengthText(isView) {
|
||||||
|
this.texts.forEach((text) => {
|
||||||
|
text.set({ visible: isView })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fillBackground(pattern) {
|
fillBackground(pattern) {
|
||||||
|
|||||||
941
src/components/fabric/QPolygon3.js
Normal file
941
src/components/fabric/QPolygon3.js
Normal file
@ -0,0 +1,941 @@
|
|||||||
|
/**
|
||||||
|
* 문제 없는경우 제거
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { fabric } from 'fabric'
|
||||||
|
import {
|
||||||
|
calculateIntersection,
|
||||||
|
calculateIntersection2,
|
||||||
|
distanceBetweenPoints,
|
||||||
|
findClosestLineToPoint,
|
||||||
|
findTopTwoIndexesByDistance,
|
||||||
|
getDegreeByChon,
|
||||||
|
getDirectionByPoint,
|
||||||
|
getRoofHeight,
|
||||||
|
getRoofHypotenuse,
|
||||||
|
sortedPoints,
|
||||||
|
} from '@/util/canvas-util'
|
||||||
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
import { drawHelpLineInHexagon } from '@/util/qpolygon-utils'
|
||||||
|
|
||||||
|
export default class QPolygon3 extends fabric.Group {
|
||||||
|
type = 'QPolygon3'
|
||||||
|
polygon
|
||||||
|
points
|
||||||
|
texts = []
|
||||||
|
lines = []
|
||||||
|
canvas
|
||||||
|
fontSize
|
||||||
|
qCells = []
|
||||||
|
name
|
||||||
|
shape = 0 // 점 6개일때의 shape 모양
|
||||||
|
helpPoints = []
|
||||||
|
helpLines = []
|
||||||
|
|
||||||
|
wall
|
||||||
|
|
||||||
|
initPoints
|
||||||
|
initOption
|
||||||
|
|
||||||
|
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.')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 소수점 전부 제거
|
||||||
|
points.forEach((point) => {
|
||||||
|
point.x = Math.round(point.x)
|
||||||
|
point.y = Math.round(point.y)
|
||||||
|
})
|
||||||
|
|
||||||
|
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.initPoints = points
|
||||||
|
this.initOption = options
|
||||||
|
|
||||||
|
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,
|
||||||
|
idx: i,
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setWall(wall) {
|
||||||
|
this.wall = wall
|
||||||
|
}
|
||||||
|
|
||||||
|
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.canvas.add()
|
||||||
|
}
|
||||||
|
|
||||||
|
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.canvas.add(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.canvas.add(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) {
|
||||||
|
drawHelpLineInHexagon(this, chon)
|
||||||
|
/*if (!this.isValid()) {
|
||||||
|
return
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*if (this.lines.length === 4) {
|
||||||
|
this.drawHelpLineInRect(chon)
|
||||||
|
} else if (this.lines.length === 6 || this.lines.length === 8) {
|
||||||
|
// TODO : 6각형
|
||||||
|
drawHelpLineInHexagon2(this, 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.canvas.add(realLine1)
|
||||||
|
this.canvas.add(realLine2)
|
||||||
|
this.canvas.add(realLine3)
|
||||||
|
this.canvas.add(realLine4)
|
||||||
|
this.canvas.add(realLine5)
|
||||||
|
this.canvas.add(realLine6)
|
||||||
|
if (smallestLength !== maxLength) {
|
||||||
|
// 정사각형이 아닌경우에만 용마루를 추가한다.
|
||||||
|
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
|
||||||
|
|
||||||
|
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 = 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
|
||||||
|
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.canvas.add(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.canvas.add(helpLine1)
|
||||||
|
this.canvas.add(helpLine2)
|
||||||
|
this.canvas.remove(prevLine)
|
||||||
|
this.canvas.remove(line)
|
||||||
|
this.canvas.renderAll()
|
||||||
|
})
|
||||||
|
// 용마루
|
||||||
|
|
||||||
|
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: 'purple',
|
||||||
|
strokeWidth: 5,
|
||||||
|
})
|
||||||
|
|
||||||
|
ridgePoint.push({ x: newX, y: newY })
|
||||||
|
|
||||||
|
const ridge = new QLine([helpPoint.x, helpPoint.y, newX, newY], {
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
stroke: 'skyblue',
|
||||||
|
strokeWidth: 5,
|
||||||
|
})
|
||||||
|
|
||||||
|
this.canvas.add(ridge)
|
||||||
|
this.canvas.renderAll()
|
||||||
|
|
||||||
|
this.canvas.add(ridgeHelpLine)
|
||||||
|
this.canvas.remove(closestLine)
|
||||||
|
this.canvas.renderAll()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 용마루 끼리 연결
|
||||||
|
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.canvas.add(ridgeConnectLine)
|
||||||
|
this.canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canvas.renderAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
drawHelpLineInOctagon(chon) {}
|
||||||
|
|
||||||
|
getObject() {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
sou
|
||||||
|
|
||||||
|
toObject(propertiesToInclude) {
|
||||||
|
return fabric.util.object.extend(this.callSuper('toObject'), {
|
||||||
|
points: this.points,
|
||||||
|
fontSize: this.fontSize,
|
||||||
|
name: this.name,
|
||||||
|
shape: this.shape,
|
||||||
|
texts: this.texts,
|
||||||
|
lines: this.lines,
|
||||||
|
wall: this.wall,
|
||||||
|
initPoints: this.initPoints,
|
||||||
|
initOption: this.initOption,
|
||||||
|
objects: this.getObjects().map((obj) => obj.toObject(propertiesToInclude)),
|
||||||
|
pattern: this.pattern,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
_set(key, value) {
|
||||||
|
this.callSuper('_set', key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,9 +4,9 @@ import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/can
|
|||||||
|
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { canvasSizeState, fontSizeState } from '@/store/canvasAtom'
|
import { canvasSizeState, fontSizeState } from '@/store/canvasAtom'
|
||||||
import QPolygon from '@/components/fabric/QPolygon'
|
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import QRect from '@/components/fabric/QRect'
|
import QRect from '@/components/fabric/QRect'
|
||||||
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
|
|
||||||
export function useCanvas(id) {
|
export function useCanvas(id) {
|
||||||
const [canvas, setCanvas] = useState()
|
const [canvas, setCanvas] = useState()
|
||||||
@ -110,28 +110,25 @@ export function useCanvas(id) {
|
|||||||
fabric.Object.prototype.cornerStyle = 'rect'
|
fabric.Object.prototype.cornerStyle = 'rect'
|
||||||
fabric.Object.prototype.cornerStrokeColor = '#2BEBC8'
|
fabric.Object.prototype.cornerStrokeColor = '#2BEBC8'
|
||||||
fabric.Object.prototype.cornerSize = 6
|
fabric.Object.prototype.cornerSize = 6
|
||||||
|
fabric.QLine = QLine
|
||||||
|
fabric.QPolygon = QPolygon
|
||||||
QPolygon.prototype.canvas = canvas
|
QPolygon.prototype.canvas = canvas
|
||||||
QLine.prototype.canvas = canvas
|
QLine.prototype.canvas = canvas
|
||||||
QRect.prototype.canvas = canvas
|
QRect.prototype.canvas = canvas
|
||||||
|
|
||||||
fabric.QLine = fabric.util.createClass(fabric.Group, {})
|
|
||||||
fabric.QPolygon = fabric.util.createClass(fabric.Group, {})
|
|
||||||
|
|
||||||
// fromObject 메서드를 QLine 클래스에 직접 추가
|
|
||||||
fabric.QLine.fromObject = function (object, callback) {
|
fabric.QLine.fromObject = function (object, callback) {
|
||||||
const { initOption, initPoints, initLengthTxt } = object
|
function _callback(instance) {
|
||||||
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
|
delete instance.points
|
||||||
return callback(new QLine(initPoints, initOption, initLengthTxt))
|
callback && callback(instance)
|
||||||
})
|
}
|
||||||
|
const options = fabric.util.object.clone(object, true)
|
||||||
|
options.points = [object.x1, object.y1, object.x2, object.y2]
|
||||||
|
|
||||||
|
fabric.Object._fromObject('QLine', options, _callback, 'points')
|
||||||
}
|
}
|
||||||
|
|
||||||
// fromObject 메서드를 QLine 클래스에 직접 추가
|
|
||||||
fabric.QPolygon.fromObject = function (object, callback) {
|
fabric.QPolygon.fromObject = function (object, callback) {
|
||||||
const { initOption, initPoints, initLengthTxt } = object
|
fabric.Object._fromObject('QPolygon', object, callback, 'points')
|
||||||
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
|
|
||||||
return callback(new QPolygon(initPoints, initOption, initLengthTxt))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,44 +553,19 @@ export function useCanvas(id) {
|
|||||||
const addCanvas = () => {
|
const addCanvas = () => {
|
||||||
// const canvasState = canvas
|
// const canvasState = canvas
|
||||||
|
|
||||||
const objs = canvas
|
const objs = canvas?.toJSON(['selectable', 'name', 'parentId', 'id', 'length', 'idx', 'direction', 'lines', 'points'])
|
||||||
|
|
||||||
console.log(objs)
|
|
||||||
const str = JSON.stringify(objs)
|
const str = JSON.stringify(objs)
|
||||||
|
|
||||||
canvas?.clear()
|
canvas?.clear()
|
||||||
|
|
||||||
console.log(str)
|
|
||||||
console.log(JSON.parse(str))
|
|
||||||
|
|
||||||
// 역직렬화하여 캔버스에 객체를 다시 추가합니다.
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
canvas?.loadFromJSON(
|
// 역직렬화하여 캔버스에 객체를 다시 추가합니다.
|
||||||
JSON.parse(str),
|
canvas?.loadFromJSON(JSON.parse(str), function () {
|
||||||
function () {
|
// 모든 객체가 로드되고 캔버스에 추가된 후 호출됩니다.
|
||||||
// 모든 객체가 로드되고 캔버스에 추가된 후 호출됩니다.
|
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
||||||
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
})
|
||||||
console.log('Objects are reloaded and rendered on canvas.')
|
|
||||||
},
|
|
||||||
function (o, object) {
|
|
||||||
// 각 객체가 로드될 때마다 호출됩니다.
|
|
||||||
console.log('Object loaded: ', o, object)
|
|
||||||
|
|
||||||
canvas?.add(object)
|
|
||||||
canvas?.renderAll()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
/*canvas?.loadFromJSON(JSON.parse(str), () => {
|
|
||||||
console.log('load done')
|
|
||||||
})*/
|
|
||||||
|
|
||||||
/*const stateArr = canvasState.map((state) => state.getObject().getObjects())
|
|
||||||
|
|
||||||
const newCanvasList = [...canvasList, JSON.stringify(stateArr)]
|
|
||||||
|
|
||||||
setCanvasList(newCanvasList)*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeCanvas = (idx) => {
|
const changeCanvas = (idx) => {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -657,3 +657,26 @@ export function removeDuplicatePoints(points) {
|
|||||||
|
|
||||||
return uniquePoints
|
return uniquePoints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x,y가 다르면서 가장 가까운 점
|
||||||
|
* @param targetPoint
|
||||||
|
* @param points
|
||||||
|
* @returns {null}
|
||||||
|
*/
|
||||||
|
export function findClosestPointWithDifferentXY(targetPoint, points) {
|
||||||
|
let closestPoint = null
|
||||||
|
let smallestDistance = Infinity
|
||||||
|
|
||||||
|
points.forEach((point) => {
|
||||||
|
if (point.x !== targetPoint.x && point.y !== targetPoint.y) {
|
||||||
|
const distance = Math.sqrt(Math.pow(point.x - targetPoint.x, 2) + Math.pow(point.y - targetPoint.y, 2))
|
||||||
|
if (distance < smallestDistance) {
|
||||||
|
smallestDistance = distance
|
||||||
|
closestPoint = point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return closestPoint
|
||||||
|
}
|
||||||
|
|||||||
@ -2,11 +2,8 @@ import { fabric } from 'fabric'
|
|||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
|
||||||
export const defineQLine = () => {
|
export const defineQLine = () => {
|
||||||
fabric.QLine = fabric.util.createClass(fabric.Group, {})
|
/*fabric.QLine = QLine
|
||||||
fabric.QLine.fromObject = function (object, callback) {
|
fabric.QLine.fromObject = (object, callback) => {
|
||||||
const { initOption, initPoints, initLengthTxt } = object
|
return new fabric.QLine([object.x1, object.y1, object.x2, object.y2], object)
|
||||||
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
|
}*/
|
||||||
return callback(new QLine(initPoints, initOption, initLengthTxt))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +1,356 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import QPolygon from '@/components/fabric/QPolygon'
|
import QPolygon from '@/components/fabric/QPolygon3'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { calculateIntersection, calculateIntersection2, distanceBetweenPoints, findIntersection1, removeDuplicatePoints } from '@/util/canvas-util'
|
import { calculateIntersection2, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
|
||||||
|
|
||||||
export const defineQPloygon = () => {
|
export const defineQPloygon = () => {
|
||||||
fabric.QPolygon = fabric.util.createClass(fabric.Group, {})
|
fabric.QPolygon = fabric.util.createClass(fabric.Group, {})
|
||||||
// fromObject 메서드를 QLine 클래스에 직접 추가
|
// fromObject 메서드를 QLine 클래스에 직접 추가
|
||||||
fabric.QPolygon.fromObject = function (object, callback) {
|
fabric.QPolygon.fromObject = function (object, callback) {
|
||||||
const { initOption, initPoints, initLengthTxt } = object
|
const { initOption, initPoints, initLengthTxt } = object
|
||||||
|
|
||||||
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
|
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
|
||||||
return callback(new QPolygon(initPoints, initOption, initLengthTxt))
|
return callback(new QPolygon(initPoints, object, initLengthTxt))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const drawHelpLineInHexagon2 = (polygon, chon) => {
|
export const drawHelpLineInHexagon = (polygon, chon) => {
|
||||||
const oneSideLines = [...polygon.lines].map((line) => {
|
const centerLines = drawCenterLines(polygon)
|
||||||
|
let helpLines = []
|
||||||
|
|
||||||
|
const ridgeStartPoints = []
|
||||||
|
const ridgeEndPoints = []
|
||||||
|
|
||||||
|
const centerInterSectionPoints = []
|
||||||
|
|
||||||
|
let maxLength = 0
|
||||||
|
|
||||||
|
polygon.lines = polygon.lines.sort((a, b) => a.length - b.length)
|
||||||
|
polygon.wall.lines = getOneSideLines(polygon.wall)
|
||||||
|
|
||||||
|
// 짧은 라인 순서대로 삼각 지붕을 그린다.
|
||||||
|
polygon.lines.forEach((line, index) => {
|
||||||
|
if (line.length > maxLength) {
|
||||||
|
maxLength = line.length
|
||||||
|
}
|
||||||
|
const wallLine = polygon.wall.lines.filter((wallLine) => wallLine.idx === line.idx)[0]
|
||||||
|
|
||||||
|
const checkPoint1 = polygon.points.filter((point) => point.x === line.x1 && point.y === line.y1)[0]
|
||||||
|
const checkPoint2 = polygon.points.filter((point) => point.x === line.x2 && point.y === line.y2)[0]
|
||||||
|
|
||||||
|
if (checkPoint1.alreadyIntersected || checkPoint2.alreadyIntersected) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const angle1 = Math.atan2(wallLine.y1 - line.y1, wallLine.x1 - line.x1)
|
||||||
|
const angle2 = Math.atan2(wallLine.y2 - line.y2, wallLine.x2 - line.x2)
|
||||||
|
|
||||||
|
// line을 이등변 삼각형의 밑변으로 보고 높이를 구한다.
|
||||||
|
|
||||||
|
const helpLineLength = Math.sqrt(2 * Math.pow(line.length / 2, 2))
|
||||||
|
|
||||||
|
const firstX2 = Math.floor(line.x1 + helpLineLength * Math.cos(angle1))
|
||||||
|
const firstY2 = Math.floor(line.y1 + helpLineLength * Math.sin(angle1))
|
||||||
|
|
||||||
|
const secondX2 = Math.floor(line.x2 + helpLineLength * Math.cos(angle2))
|
||||||
|
const secondY2 = Math.floor(line.y2 + helpLineLength * Math.sin(angle2))
|
||||||
|
|
||||||
|
const firstHelpLine = new QLine([line.x1, line.y1, firstX2, firstY2], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'skyblue',
|
||||||
|
})
|
||||||
|
|
||||||
|
const secondHelpLine = new QLine([line.x2, line.y2, secondX2, secondY2], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'skyblue',
|
||||||
|
})
|
||||||
|
|
||||||
|
const interSectionPoint = calculateIntersection2(firstHelpLine, secondHelpLine)
|
||||||
|
|
||||||
|
if (interSectionPoint) {
|
||||||
|
if (polygon.inPolygon(interSectionPoint) && polygon.wall.inPolygon(interSectionPoint)) {
|
||||||
|
checkPoint1.alreadyIntersected = true
|
||||||
|
checkPoint2.alreadyIntersected = true
|
||||||
|
|
||||||
|
const helpLine1 = new QLine([line.x1, line.y1, interSectionPoint.x, interSectionPoint.y], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'skyblue',
|
||||||
|
})
|
||||||
|
|
||||||
|
const helpLine2 = new QLine([line.x2, line.y2, interSectionPoint.x, interSectionPoint.y], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'skyblue',
|
||||||
|
})
|
||||||
|
|
||||||
|
helpLines.push(helpLine1)
|
||||||
|
helpLines.push(helpLine2)
|
||||||
|
|
||||||
|
polygon.canvas.add(helpLine1)
|
||||||
|
polygon.canvas.add(helpLine2)
|
||||||
|
|
||||||
|
ridgeStartPoints.push(interSectionPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
})
|
||||||
|
// points를 순회하면서 이미 그려진 점이 아닌 경우 centerLine과 만나는 점을 찾는다.
|
||||||
|
polygon.points.forEach((point, index) => {
|
||||||
|
if (point.alreadyIntersected) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const wallPoint = polygon.wall.points[index]
|
||||||
|
|
||||||
|
const angle = Math.atan2(wallPoint.y - point.y, wallPoint.x - point.x)
|
||||||
|
|
||||||
|
const newX2 = Math.floor(point.x + (maxLength / 2 + 50) * Math.cos(angle))
|
||||||
|
const newY2 = Math.floor(point.y + (maxLength / 2 + 50) * Math.sin(angle))
|
||||||
|
|
||||||
|
const helpLine = new QLine([point.x, point.y, newX2, newY2], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'green',
|
||||||
|
})
|
||||||
|
|
||||||
|
const relatedPoints = []
|
||||||
|
|
||||||
|
centerLines.forEach((centerLine) => {
|
||||||
|
const interSectionPoint = calculateIntersection2(helpLine, centerLine)
|
||||||
|
|
||||||
|
if (interSectionPoint) {
|
||||||
|
if (polygon.inPolygon(interSectionPoint) && polygon.wall.inPolygon(interSectionPoint)) {
|
||||||
|
relatedPoints.push(interSectionPoint)
|
||||||
|
|
||||||
|
centerInterSectionPoints.push(interSectionPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
helpLine.set({ relatedPoints: relatedPoints })
|
||||||
|
helpLines.push(helpLine)
|
||||||
|
})
|
||||||
|
|
||||||
|
helpLines = helpLines.filter((line) => line.relatedPoints?.length > 0)
|
||||||
|
|
||||||
|
ridgeStartPoints.forEach((point) => {
|
||||||
|
point.alreadyIntersected = false
|
||||||
|
// x 혹은 y가 같으면서 가장 가까운 점을 찾는다.
|
||||||
|
let arrivalPoint
|
||||||
|
let hipLine
|
||||||
|
let distance = Infinity
|
||||||
|
let startPoint
|
||||||
|
helpLines.forEach((line) => {
|
||||||
|
line.relatedPoints.forEach((relatedPoint) => {
|
||||||
|
if (Math.abs(point.x - relatedPoint.x) <= 2 || Math.abs(point.y - relatedPoint.y) <= 2) {
|
||||||
|
if (distanceBetweenPoints(point, relatedPoint) < distance) {
|
||||||
|
startPoint = point
|
||||||
|
distance = distanceBetweenPoints(point, relatedPoint)
|
||||||
|
hipLine = line
|
||||||
|
arrivalPoint = relatedPoint
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (arrivalPoint) {
|
||||||
|
hipLine.relatedPoints.forEach((relatedPoint) => {
|
||||||
|
if (relatedPoint.x !== arrivalPoint.x && relatedPoint.y !== arrivalPoint.y) {
|
||||||
|
centerInterSectionPoints.splice(centerInterSectionPoints.indexOf(relatedPoint), 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
helpLines.splice(helpLines.indexOf(hipLine), 1)
|
||||||
|
|
||||||
|
const helpLine = new QLine([hipLine.x1, hipLine.y1, arrivalPoint.x, arrivalPoint.y], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'red',
|
||||||
|
})
|
||||||
|
const ridge = new QLine([startPoint.x, startPoint.y, arrivalPoint.x, arrivalPoint.y], {
|
||||||
|
stroke: 'green',
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
polygon.canvas.add(helpLine)
|
||||||
|
polygon.canvas.add(ridge)
|
||||||
|
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
ridgeEndPoints.push(arrivalPoint)
|
||||||
|
|
||||||
|
point.alreadyIntersected = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 안쓰는 점 제거
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ridgeEndRemainingPoints = [...ridgeEndPoints]
|
||||||
|
|
||||||
|
const uniqueInterSectionPoints = Array.from(new Set(centerInterSectionPoints.map((point) => `${point.x},${point.y}`))).map((key) => {
|
||||||
|
const [x, y] = key.split(',').map(Number)
|
||||||
|
return { x, y }
|
||||||
|
})
|
||||||
|
|
||||||
|
while (ridgeEndRemainingPoints.length > 0) {
|
||||||
|
const point = ridgeEndRemainingPoints.shift()
|
||||||
|
let isExist = false
|
||||||
|
uniqueInterSectionPoints.forEach((uniquePoint) => {
|
||||||
|
const degree = calculateAngle(point, uniquePoint)
|
||||||
|
|
||||||
|
if (Math.abs(45 - Math.abs(degree)) <= 5 || Math.abs(135 - Math.abs(degree)) <= 5) {
|
||||||
|
const line = new QLine([point.x, point.y, uniquePoint.x, uniquePoint.y], {
|
||||||
|
stroke: 'purple',
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
ridgeEndPoints.push(uniquePoint)
|
||||||
|
|
||||||
|
ridgeEndPoints.splice(ridgeEndPoints.indexOf(point), 1)
|
||||||
|
|
||||||
|
isExist = true
|
||||||
|
|
||||||
|
polygon.canvas.add(line)
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isExist) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const ridgeEndRemainingPoints2 = [...ridgeEndPoints]
|
||||||
|
|
||||||
|
while (ridgeEndRemainingPoints2.length > 0) {
|
||||||
|
// 남아있는 점끼리 연결한다.
|
||||||
|
const point = ridgeEndRemainingPoints2.shift()
|
||||||
|
const closestPoint = findClosestPoint(point, ridgeEndRemainingPoints2)
|
||||||
|
if (!closestPoint) continue
|
||||||
|
const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], {
|
||||||
|
stroke: 'purple',
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
polygon.canvas.add(line)
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ridgeEndPoints와 가까운 centerInterSectionPoints를 찾아서 연결한다.
|
||||||
|
const remainingPoints = centerInterSectionPoints
|
||||||
|
/*
|
||||||
|
helpLines.forEach((line) => {
|
||||||
|
remainingPoints.forEach((point) => {
|
||||||
|
if (line.relatedPoints.includes(point)) {
|
||||||
|
const hip = new QLine([line.x1, line.y1, point.x, point.y], {
|
||||||
|
stroke: 'red',
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
polygon.canvas.add(hip)
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// centerInterSectionPoints에 남아있는 점들을 가까운 점끼리 연결한다.
|
||||||
|
while (remainingPoints.length > 0) {
|
||||||
|
const point = remainingPoints.shift()
|
||||||
|
const closestPoint = findClosestPoint(point, remainingPoints)
|
||||||
|
if (!closestPoint) continue
|
||||||
|
const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], {
|
||||||
|
stroke: 'purple',
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
polygon.canvas.add(line)
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
const notIntersectedRidgeStartPoints = ridgeStartPoints.filter((point) => !point.alreadyIntersected)
|
||||||
|
// 만나지 않은 마루 시작점
|
||||||
|
while (notIntersectedRidgeStartPoints.length > 0) {
|
||||||
|
const point = notIntersectedRidgeStartPoints.shift()
|
||||||
|
const closestPoint = findClosestPoint(point, notIntersectedRidgeStartPoints)
|
||||||
|
if (!closestPoint) continue
|
||||||
|
const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], {
|
||||||
|
stroke: 'purple',
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
polygon.canvas.add(line)
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
export const drawHelpLineInHexagon2 = (polygon, chon) => {}
|
||||||
|
|
||||||
|
export const drawCenterLines = (polygon) => {
|
||||||
|
const centerLines = []
|
||||||
|
|
||||||
|
const oneSideLines = getOneSideLines(polygon)
|
||||||
|
|
||||||
|
const horizontalLines = oneSideLines.filter((line) => line.direction === 'right')
|
||||||
|
const verticalLines = oneSideLines.filter((line) => line.direction === 'bottom')
|
||||||
|
// horizontalLines 를 y1 좌표 기준으로 정렬한다.
|
||||||
|
horizontalLines.sort((a, b) => a.y1 - b.y1)
|
||||||
|
// verticalLines 를 x1 좌표 기준으로 정렬한다.
|
||||||
|
verticalLines.sort((a, b) => a.x1 - b.x1)
|
||||||
|
|
||||||
|
let maxHorizontalLineLength = 0
|
||||||
|
let maxVerticalLineLength = 0
|
||||||
|
// 모든 가로선의 중심선을 긋는다.
|
||||||
|
horizontalLines.forEach((line, index) => {
|
||||||
|
const nextLine = horizontalLines[(index + 1) % horizontalLines.length]
|
||||||
|
|
||||||
|
line.set({ strokeWidth: 5 })
|
||||||
|
nextLine.set({ strokeWidth: 5 })
|
||||||
|
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
|
||||||
|
const startCenterX = Math.min(line.x1, nextLine.x1)
|
||||||
|
const startCenterY = (line.y1 + nextLine.y1) / 2
|
||||||
|
|
||||||
|
const endCenterX = line.x2 > nextLine.x2 ? line.x2 : nextLine.x2
|
||||||
|
const endCenterY = startCenterY
|
||||||
|
|
||||||
|
const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 1,
|
||||||
|
direction: 'horizontal',
|
||||||
|
})
|
||||||
|
|
||||||
|
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.y2 > nextLine.y2 ? line.y2 : nextLine.y2
|
||||||
|
|
||||||
|
const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'blue',
|
||||||
|
strokeWidth: 1,
|
||||||
|
direction: 'vertical',
|
||||||
|
})
|
||||||
|
|
||||||
|
centerLines.push(centerLine)
|
||||||
|
})
|
||||||
|
|
||||||
|
return centerLines
|
||||||
|
}
|
||||||
|
|
||||||
|
const getOneSideLines = (polygon) => {
|
||||||
|
return [...polygon.lines].map((line) => {
|
||||||
let newX1, newY1, newX2, newY2
|
let newX1, newY1, newX2, newY2
|
||||||
if (line.direction === 'top') {
|
if (line.direction === 'top') {
|
||||||
newX1 = line.x2
|
newX1 = line.x2
|
||||||
@ -42,288 +377,10 @@ export const drawHelpLineInHexagon2 = (polygon, chon) => {
|
|||||||
}
|
}
|
||||||
return line
|
return line
|
||||||
})
|
})
|
||||||
|
|
||||||
const centerLines = []
|
|
||||||
const helpLines = []
|
|
||||||
const ridgeStartPoints = []
|
|
||||||
|
|
||||||
const horizontalLines = oneSideLines.filter((line) => line.direction === 'right')
|
|
||||||
const verticalLines = oneSideLines.filter((line) => line.direction === 'bottom')
|
|
||||||
// horizontalLines 를 y1 좌표 기준으로 정렬한다.
|
|
||||||
horizontalLines.sort((a, b) => a.y1 - b.y1)
|
|
||||||
// verticalLines 를 x1 좌표 기준으로 정렬한다.
|
|
||||||
verticalLines.sort((a, b) => a.x1 - b.x1)
|
|
||||||
|
|
||||||
const maxHorizontalLineLength = horizontalLines.reduce((prev, current) => (prev.length > current.length ? prev.length : current.length))
|
|
||||||
const maxVerticalLineLength = verticalLines.reduce((prev, current) => (prev.length > current.length ? prev.length : current.length))
|
|
||||||
|
|
||||||
// 모든 가로선의 중심선을 긋는다.
|
|
||||||
horizontalLines.forEach((line, index) => {
|
|
||||||
const nextLine = horizontalLines[(index + 1) % horizontalLines.length]
|
|
||||||
|
|
||||||
line.line.set({ strokeWidth: 5 })
|
|
||||||
nextLine.line.set({ strokeWidth: 5 })
|
|
||||||
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
|
|
||||||
const startCenterX = Math.min(line.x1, nextLine.x1)
|
|
||||||
const startCenterY = (line.y1 + nextLine.y1) / 2
|
|
||||||
|
|
||||||
const endCenterX = line.length >= nextLine.length ? startCenterX + line.length : startCenterX + nextLine.length
|
|
||||||
const endCenterY = startCenterY
|
|
||||||
|
|
||||||
const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 1,
|
|
||||||
direction: 'horizontal',
|
|
||||||
})
|
|
||||||
|
|
||||||
/*polygon.canvas.add(centerLine)
|
|
||||||
polygon.canvas.renderAll()*/
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
const centerLine = new QLine([startCenterX, startCenterY, endCenterX, endCenterY], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 1,
|
|
||||||
direction: 'vertical',
|
|
||||||
})
|
|
||||||
|
|
||||||
/*polygon.canvas.add(centerLine)
|
|
||||||
polygon.canvas.renderAll()*/
|
|
||||||
centerLines.push(centerLine)
|
|
||||||
})
|
|
||||||
|
|
||||||
polygon.points.forEach((point, index) => {
|
|
||||||
const wallPoint = polygon.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)
|
|
||||||
|
|
||||||
let previousIndex = index === 0 ? polygon.lines.length - 1 : index - 1
|
|
||||||
const maxLength = Math.max(polygon.lines[index].length, polygon.lines[previousIndex].length)
|
|
||||||
|
|
||||||
newX2 = Math.floor(x1 + (maxLength / 2 + polygon.points.length * 10) * Math.cos(angle))
|
|
||||||
newY2 = Math.floor(y1 + (maxLength / 2 + polygon.points.length * 10) * Math.sin(angle))
|
|
||||||
|
|
||||||
const line = new QLine([x1, y1, newX2, newY2], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'green',
|
|
||||||
idx: index,
|
|
||||||
})
|
|
||||||
line.set({ degree: fabric.util.radiansToDegrees(angle) })
|
|
||||||
polygon.canvas.add(line)
|
|
||||||
helpLines.push(line)
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
})
|
|
||||||
|
|
||||||
helpLines.forEach((line, index) => {
|
|
||||||
for (let i = index + 1; i < helpLines.length; i++) {
|
|
||||||
const nextLine = helpLines[i]
|
|
||||||
|
|
||||||
if (line.isAlreadyInterSection || nextLine.isAlreadyInterSection) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
let intersectionPoint = calculateIntersection(line, nextLine)
|
|
||||||
|
|
||||||
if (!intersectionPoint) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const circle = new fabric.Circle({
|
|
||||||
radius: 3,
|
|
||||||
fill: 'red',
|
|
||||||
left: intersectionPoint.x - 3,
|
|
||||||
top: intersectionPoint.y - 3,
|
|
||||||
})
|
|
||||||
|
|
||||||
polygon.canvas.add(circle)
|
|
||||||
|
|
||||||
line.set({ isAlreadyInterSection: true })
|
|
||||||
nextLine.set({ isAlreadyInterSection: true })
|
|
||||||
|
|
||||||
const helpLine1 = new QLine([nextLine.x1, nextLine.y1, intersectionPoint.x, intersectionPoint.y], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'skyblue',
|
|
||||||
})
|
|
||||||
|
|
||||||
const helpLine2 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'skyblue',
|
|
||||||
})
|
|
||||||
|
|
||||||
ridgeStartPoints.push(intersectionPoint)
|
|
||||||
polygon.canvas.add(helpLine1)
|
|
||||||
polygon.canvas.add(helpLine2)
|
|
||||||
polygon.canvas.remove(nextLine)
|
|
||||||
polygon.canvas.remove(line)
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 안만나는 선들
|
|
||||||
const notInterSectionLines = helpLines.filter((line) => !line.isAlreadyInterSection)
|
|
||||||
const ridgeEndPoints = []
|
|
||||||
let interSectionPoints = []
|
|
||||||
|
|
||||||
notInterSectionLines.forEach((line, index) => {
|
|
||||||
let subCenterLines
|
|
||||||
if (Math.abs(line.degree) < 90) {
|
|
||||||
subCenterLines = centerLines.filter((centerLine) => centerLine.direction === 'vertical')
|
|
||||||
} else {
|
|
||||||
subCenterLines = centerLines.filter((centerLine) => centerLine.direction === 'horizontal')
|
|
||||||
}
|
|
||||||
|
|
||||||
centerLines.forEach((centerLine) => {
|
|
||||||
const interSectionPoint = calculateIntersection2(line, centerLine)
|
|
||||||
|
|
||||||
if (!interSectionPoint) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ridgeStartPoints.forEach((point) => {
|
|
||||||
line.interSectionPoints.push(interSectionPoint)
|
|
||||||
interSectionPoints.push(interSectionPoint)
|
|
||||||
|
|
||||||
const newLine = new QLine([line.x1, line.y1, interSectionPoint.x, interSectionPoint.y], {
|
|
||||||
stroke: 'black',
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
})
|
|
||||||
|
|
||||||
const circle = new fabric.Circle({
|
|
||||||
radius: 3,
|
|
||||||
fill: 'blue',
|
|
||||||
left: interSectionPoint.x - 3,
|
|
||||||
top: interSectionPoint.y - 3,
|
|
||||||
})
|
|
||||||
polygon.canvas.add(circle)
|
|
||||||
polygon.canvas.add(newLine)
|
|
||||||
|
|
||||||
polygon.canvas.remove(line)
|
|
||||||
|
|
||||||
line.set({ isAlreadyInterSection: true })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
interSectionPoints = removeDuplicatePoints(interSectionPoints)
|
|
||||||
|
|
||||||
const startRidgePoint = ridgeStartPoints[0]
|
|
||||||
|
|
||||||
const endRidgePoint = ridgeStartPoints[ridgeStartPoints.length - 1]
|
|
||||||
|
|
||||||
let step = 0
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (step % 2 === 0) {
|
|
||||||
const nextPoint = interSectionPoints.find((point) => point.x === startRidgePoint.x || point.y === startRidgePoint.y)
|
|
||||||
|
|
||||||
if (nextPoint) {
|
|
||||||
const ridge = new QLine([startRidgePoint.x, startRidgePoint.y, nextPoint.x, nextPoint.y], {
|
|
||||||
stroke: 'green',
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
})
|
|
||||||
polygon.canvas.add(ridge)
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('nextPoint', nextPoint)
|
|
||||||
console.log('startRidgePoint', startRidgePoint)
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
|
|
||||||
step++
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ridgeStartPoints.forEach((point, index) => {
|
|
||||||
for (let i = index + 1; i < ridgeStartPoints.length; i++) {
|
|
||||||
const currentPoint = ridgeStartPoints[index]
|
|
||||||
const nextPoint = ridgeStartPoints[i]
|
|
||||||
|
|
||||||
if (currentPoint.x === nextPoint.x || currentPoint.y === nextPoint.y) {
|
|
||||||
const ridge = new QLine([currentPoint.x, currentPoint.y, nextPoint.x, nextPoint.y], {
|
|
||||||
stroke: 'black',
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
})
|
|
||||||
polygon.canvas.add(ridge)
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})*/
|
|
||||||
|
|
||||||
/*ridgeStartPoints.forEach((point, index) => {
|
|
||||||
let arrivalPoint
|
|
||||||
let distance = Infinity
|
|
||||||
let startPoint
|
|
||||||
interSectionPoints.forEach((interSectionPoint) => {
|
|
||||||
if (Math.abs(point.x - interSectionPoint.x) < 1 || Math.abs(point.y - interSectionPoint.y) < 1) {
|
|
||||||
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: polygon.fontSize,
|
|
||||||
})
|
|
||||||
|
|
||||||
const helpLine = new QLine([line.x1, line.y1, arrivalPoint.x, arrivalPoint.y], {
|
|
||||||
stroke: 'red',
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
})
|
|
||||||
|
|
||||||
ridgeEndPoints.push(arrivalPoint)
|
|
||||||
polygon.canvas.add(ridge)
|
|
||||||
polygon.canvas.add(helpLine)
|
|
||||||
// polygon.canvas.remove(line)
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
debugger
|
|
||||||
}
|
|
||||||
})*/
|
|
||||||
|
|
||||||
/*for (let i = 0; i < ridgeEndPoints.length; i = i + 2) {
|
|
||||||
const currentRidgeEndPoint = ridgeEndPoints[i]
|
|
||||||
const nextRidgeEndPoint = ridgeEndPoints[(i + 1) % ridgeEndPoints.length]
|
|
||||||
const ridgeConnectLine = new QLine([currentRidgeEndPoint.x, currentRidgeEndPoint.y, nextRidgeEndPoint.x, nextRidgeEndPoint.y], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'green',
|
|
||||||
})
|
|
||||||
|
|
||||||
polygon.canvas.add(ridgeConnectLine)
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
const calculateAngle = (point1, point2) => {
|
||||||
export const drawHelpLineInHexagon = (polygon, chon) => {
|
const deltaX = point2.x - point1.x
|
||||||
// 가장 긴라인을 기준으로 centerLine을 그린다.
|
const deltaY = point2.y - point1.y
|
||||||
|
const angleInRadians = Math.atan2(deltaY, deltaX)
|
||||||
|
return angleInRadians * (180 / Math.PI)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user