이벤트 수정 및 지붕선 그리기 수정
This commit is contained in:
parent
204d1ac3e4
commit
adbf79ecd3
@ -208,7 +208,7 @@ export default function Roof2() {
|
|||||||
]
|
]
|
||||||
|
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
const polygon = new QPolygon(eightPoint, {
|
const polygon = new QPolygon(type1, {
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
|
|||||||
@ -36,8 +36,15 @@ export class QLine extends fabric.Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const line = new fabric.Line(points, { ...option, strokeWidth: 1 })
|
const line = new fabric.Line(points, { ...option, strokeWidth: 1 })
|
||||||
super([line], {})
|
|
||||||
|
|
||||||
|
// 길이가 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.initPoints = points
|
||||||
this.initOption = option
|
this.initOption = option
|
||||||
this.initLengthTxt = lengthTxt
|
this.initLengthTxt = lengthTxt
|
||||||
@ -59,6 +66,7 @@ export class QLine extends fabric.Group {
|
|||||||
option.isActiveLengthText ?? this.init()
|
option.isActiveLengthText ?? this.init()
|
||||||
this.addControl()
|
this.addControl()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.addLengthText(true)
|
this.addLengthText(true)
|
||||||
@ -156,6 +164,7 @@ export class QLine extends fabric.Group {
|
|||||||
initPoints: this.initPoints,
|
initPoints: this.initPoints,
|
||||||
initOption: this.initOption,
|
initOption: this.initOption,
|
||||||
initLengthTxt: this.initLengthTxt,
|
initLengthTxt: this.initLengthTxt,
|
||||||
|
points: this.points,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
sortedPoints,
|
sortedPoints,
|
||||||
} from '@/util/canvas-util'
|
} from '@/util/canvas-util'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { drawHelpLineInHexagon2 } from '@/util/qpolygon-utils'
|
import { drawHelpLineInHexagon } from '@/util/qpolygon-utils'
|
||||||
|
|
||||||
export default class QPolygon extends fabric.Group {
|
export default class QPolygon extends fabric.Group {
|
||||||
type = 'QPolygon'
|
type = 'QPolygon'
|
||||||
@ -73,6 +73,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
stroke: this.stroke,
|
stroke: this.stroke,
|
||||||
strokeWidth: this.strokeWidth,
|
strokeWidth: this.strokeWidth,
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
|
idx: i,
|
||||||
direction: getDirectionByPoint(point, nextPoint),
|
direction: getDirectionByPoint(point, nextPoint),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -321,19 +322,20 @@ export default class QPolygon extends fabric.Group {
|
|||||||
|
|
||||||
// 보조선 그리기
|
// 보조선 그리기
|
||||||
drawHelpLine(chon = 4) {
|
drawHelpLine(chon = 4) {
|
||||||
if (!this.isValid()) {
|
drawHelpLineInHexagon(this, chon)
|
||||||
|
/*if (!this.isValid()) {
|
||||||
return
|
return
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (this.lines.length === 4) {
|
/*if (this.lines.length === 4) {
|
||||||
this.drawHelpLineInRect(chon)
|
this.drawHelpLineInRect(chon)
|
||||||
} else if (this.lines.length === 6 || this.lines.length === 8) {
|
} else if (this.lines.length === 6 || this.lines.length === 8) {
|
||||||
// TODO : 6각형
|
// TODO : 6각형
|
||||||
drawHelpLineInHexagon2(this, chon)
|
drawHelpLineInHexagon2(this, chon)
|
||||||
} /* else if (this.lines.length === 8) {
|
} /!* else if (this.lines.length === 8) {
|
||||||
// TODO : 8각형
|
// TODO : 8각형
|
||||||
this.drawHelpLineInOctagon(chon)
|
this.drawHelpLineInOctagon(chon)
|
||||||
}*/
|
}*!/*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -925,6 +927,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
initPoints: this.initPoints,
|
initPoints: this.initPoints,
|
||||||
initOption: this.initOption,
|
initOption: this.initOption,
|
||||||
objects: this.getObjects().map((obj) => obj.toObject(propertiesToInclude)),
|
objects: this.getObjects().map((obj) => obj.toObject(propertiesToInclude)),
|
||||||
|
pattern: this.pattern,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,9 @@ import QPolygon from '@/components/fabric/QPolygon'
|
|||||||
import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util'
|
import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
|
|
||||||
import { fontSizeState, roofPolygonPatternArrayState, roofState, sortedPolygonArray, wallState } from '@/store/canvasAtom'
|
import { canvasSizeState, fontSizeState, roofPolygonPatternArrayState, roofState, sortedPolygonArray, wallState } from '@/store/canvasAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
import { fabric } from 'fabric'
|
||||||
|
|
||||||
export const Mode = {
|
export const Mode = {
|
||||||
DRAW_LINE: 'drawLine', // 기준선 긋기모드
|
DRAW_LINE: 'drawLine', // 기준선 긋기모드
|
||||||
@ -32,8 +33,12 @@ export function useMode() {
|
|||||||
const [roof, setRoof] = useRecoilState(roofState)
|
const [roof, setRoof] = useRecoilState(roofState)
|
||||||
const [wall, setWall] = useRecoilState(wallState)
|
const [wall, setWall] = useRecoilState(wallState)
|
||||||
|
|
||||||
|
const [endPoint, setEndPoint] = useState(null)
|
||||||
|
|
||||||
const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState)
|
const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState)
|
||||||
|
|
||||||
|
const [canvasSize] = useRecoilState(canvasSizeState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 이벤트 리스너 추가
|
// 이벤트 리스너 추가
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
@ -47,6 +52,93 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
}, [canvas]) // 빈 배열을 전달하여 컴포넌트가 마운트될 때만 실행되도록 함
|
}, [canvas]) // 빈 배열을 전달하여 컴포넌트가 마운트될 때만 실행되도록 함
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (canvas?.getObjects().find((obj) => obj.name === 'connectLine')) {
|
||||||
|
canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'connectLine'))
|
||||||
|
}
|
||||||
|
canvas?.off('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint))
|
||||||
|
canvas?.off('mouse:move')
|
||||||
|
canvas?.on('mouse:move', drawMouseLines)
|
||||||
|
canvas?.off('mouse:out', removeMouseLines)
|
||||||
|
canvas?.on('mouse:out', removeMouseLines)
|
||||||
|
if (!endPoint) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas?.on('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint))
|
||||||
|
}, [endPoint])
|
||||||
|
|
||||||
|
const drawMouseLines = (e) => {
|
||||||
|
// 현재 마우스 포인터의 위치를 가져옵니다.
|
||||||
|
const pointer = canvas?.getPointer(e.e)
|
||||||
|
|
||||||
|
// 기존에 그려진 가이드라인을 제거합니다.
|
||||||
|
removeMouseLines()
|
||||||
|
|
||||||
|
if (canvas?.getActiveObject()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 가로선을 그립니다.
|
||||||
|
const horizontalLine = new fabric.Line([0, pointer.y, canvasSize.horizontal, pointer.y], {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'mouseLine',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 세로선을 그립니다.
|
||||||
|
const verticalLine = new fabric.Line([pointer.x, 0, pointer.x, canvasSize.vertical], {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'mouseLine',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 선들을 캔버스에 추가합니다.
|
||||||
|
canvas?.add(horizontalLine, verticalLine)
|
||||||
|
|
||||||
|
// 캔버스를 다시 그립니다.
|
||||||
|
canvas?.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 마우스 포인터의 가이드라인을 제거합니다.
|
||||||
|
*/
|
||||||
|
const removeMouseLines = () => {
|
||||||
|
if (canvas?._objects.length > 0) {
|
||||||
|
const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine')
|
||||||
|
mouseLines.forEach((item) => canvas?.remove(item))
|
||||||
|
}
|
||||||
|
canvas?.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
const addLineEndPointToMousePoint = (e, endPoint) => {
|
||||||
|
if (canvas?.getObjects().find((obj) => obj.name === 'connectLine')) {
|
||||||
|
canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'connectLine'))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!endPoint) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointer = canvas?.getPointer(e.e)
|
||||||
|
|
||||||
|
// 마우스 포인터 위치랑 endPoint를 연결하는 line 생성
|
||||||
|
const line = new QLine([endPoint.left, endPoint.top, pointer.x, pointer.y], {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 2,
|
||||||
|
selectable: false,
|
||||||
|
viewLengthText: true,
|
||||||
|
fontSize: fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
line.set({ name: 'connectLine' })
|
||||||
|
|
||||||
|
canvas?.add(line)
|
||||||
|
canvas?.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
const addEvent = (mode) => {
|
const addEvent = (mode) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'default':
|
case 'default':
|
||||||
@ -98,6 +190,7 @@ export function useMode() {
|
|||||||
originY: 'center',
|
originY: 'center',
|
||||||
selectable: false,
|
selectable: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
historyPoints.current.push(circle)
|
historyPoints.current.push(circle)
|
||||||
points.current.push(circle)
|
points.current.push(circle)
|
||||||
canvas?.add(circle)
|
canvas?.add(circle)
|
||||||
@ -142,6 +235,8 @@ export function useMode() {
|
|||||||
selectable: false,
|
selectable: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setEndPoint(endPointCircle)
|
||||||
|
|
||||||
canvas?.add(endPointCircle)
|
canvas?.add(endPointCircle)
|
||||||
|
|
||||||
historyPoints.current.push(endPointCircle)
|
historyPoints.current.push(endPointCircle)
|
||||||
@ -221,10 +316,12 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const changeMode = (canvas, mode) => {
|
const changeMode = (canvas, mode) => {
|
||||||
|
setEndPoint(null)
|
||||||
setMode(mode)
|
setMode(mode)
|
||||||
// mode변경 시 이전 이벤트 제거
|
// mode변경 시 이전 이벤트 제거
|
||||||
setCanvas(canvas)
|
setCanvas(canvas)
|
||||||
canvas?.off('mouse:down')
|
canvas?.off('mouse:down')
|
||||||
|
|
||||||
addEvent(mode)
|
addEvent(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +339,8 @@ export function useMode() {
|
|||||||
selectable: false,
|
selectable: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setEndPoint(circle)
|
||||||
|
|
||||||
historyPoints.current.push(circle)
|
historyPoints.current.push(circle)
|
||||||
points.current.push(circle)
|
points.current.push(circle)
|
||||||
canvas?.add(circle)
|
canvas?.add(circle)
|
||||||
@ -308,7 +407,7 @@ export function useMode() {
|
|||||||
originY: 'center',
|
originY: 'center',
|
||||||
selectable: false,
|
selectable: false,
|
||||||
})
|
})
|
||||||
|
setEndPoint(endPointCircle)
|
||||||
canvas?.add(endPointCircle)
|
canvas?.add(endPointCircle)
|
||||||
|
|
||||||
historyPoints.current.push(endPointCircle)
|
historyPoints.current.push(endPointCircle)
|
||||||
@ -556,7 +655,7 @@ export function useMode() {
|
|||||||
if (!otherLines) {
|
if (!otherLines) {
|
||||||
// polygon.fillCell()
|
// polygon.fillCell()
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
polygon.setViewLengthText(false)
|
// polygon.setViewLengthText(false)
|
||||||
setMode(Mode.DEFAULT)
|
setMode(Mode.DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -649,3 +649,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
|
||||||
|
}
|
||||||
|
|||||||
@ -1,7 +1,19 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import QPolygon from '@/components/fabric/QPolygon'
|
import QPolygon from '@/components/fabric/QPolygon'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { calculateIntersection, calculateIntersection2, distanceBetweenPoints, findIntersection1, removeDuplicatePoints } from '@/util/canvas-util'
|
import {
|
||||||
|
calculateDistance,
|
||||||
|
calculateIntersection,
|
||||||
|
calculateIntersection2,
|
||||||
|
distanceBetweenPoints,
|
||||||
|
findClosestLineToPoint,
|
||||||
|
findClosestPoint,
|
||||||
|
findClosestPointWithDifferentXY,
|
||||||
|
findIntersection1,
|
||||||
|
getRoofHypotenuse,
|
||||||
|
removeDuplicatePoints,
|
||||||
|
} from '@/util/canvas-util'
|
||||||
|
import { help } from 'mathjs'
|
||||||
|
|
||||||
export const defineQPloygon = () => {
|
export const defineQPloygon = () => {
|
||||||
fabric.QPolygon = fabric.util.createClass(fabric.Group, {})
|
fabric.QPolygon = fabric.util.createClass(fabric.Group, {})
|
||||||
@ -14,8 +26,287 @@ export const defineQPloygon = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
const helpLineLength = Math.min(line.length)
|
||||||
|
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
|
||||||
|
const secondHelpLine = new QLine([line.x2, line.y2, secondX2, secondY2], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
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) => {
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 안쓰는 점 제거
|
||||||
|
*/
|
||||||
|
centerInterSectionPoints.forEach((point) => {
|
||||||
|
ridgeEndPoints.forEach((endPoint) => {
|
||||||
|
if (!(Math.abs(point.x - endPoint.x) < 2 && Math.abs(point.y - endPoint.y) < 2)) {
|
||||||
|
centerInterSectionPoints.splice(centerInterSectionPoints.indexOf(point), 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// ridgeEndPoints와 가까운 centerInterSectionPoints를 찾아서 연결한다.
|
||||||
|
const remainingPoints = centerInterSectionPoints
|
||||||
|
const ridgeEndRemainingPoints = ridgeEndPoints
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
while (ridgeEndRemainingPoints.length > 0) {
|
||||||
|
const point = ridgeEndRemainingPoints.shift()
|
||||||
|
const closestPoint = findClosestPoint(point, remainingPoints)
|
||||||
|
if (!closestPoint) continue
|
||||||
|
const line = new QLine([point.x, point.y, closestPoint.x, closestPoint.y], {
|
||||||
|
stroke: 'green',
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
polygon.canvas.add(line)
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.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.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 +333,4 @@ 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()
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
export const drawHelpLineInHexagon = (polygon, chon) => {
|
|
||||||
// 가장 긴라인을 기준으로 centerLine을 그린다.
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user