이벤트 수정 및 지붕선 그리기 수정
This commit is contained in:
parent
204d1ac3e4
commit
adbf79ecd3
@ -208,7 +208,7 @@ export default function Roof2() {
|
||||
]
|
||||
|
||||
if (canvas) {
|
||||
const polygon = new QPolygon(eightPoint, {
|
||||
const polygon = new QPolygon(type1, {
|
||||
fill: 'transparent',
|
||||
stroke: 'black',
|
||||
strokeWidth: 1,
|
||||
|
||||
@ -36,28 +36,36 @@ export class QLine extends fabric.Group {
|
||||
}
|
||||
|
||||
const line = new fabric.Line(points, { ...option, strokeWidth: 1 })
|
||||
super([line], {})
|
||||
|
||||
this.initPoints = points
|
||||
this.initOption = option
|
||||
this.initLengthTxt = lengthTxt
|
||||
// 길이가 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
|
||||
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)
|
||||
if (lengthTxt > 0) {
|
||||
this.lengthTxt = Number(lengthTxt)
|
||||
}
|
||||
|
||||
option.isActiveLengthText ?? this.init()
|
||||
this.addControl()
|
||||
}
|
||||
|
||||
option.isActiveLengthText ?? this.init()
|
||||
this.addControl()
|
||||
}
|
||||
|
||||
init() {
|
||||
@ -156,6 +164,7 @@ export class QLine extends fabric.Group {
|
||||
initPoints: this.initPoints,
|
||||
initOption: this.initOption,
|
||||
initLengthTxt: this.initLengthTxt,
|
||||
points: this.points,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
sortedPoints,
|
||||
} from '@/util/canvas-util'
|
||||
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 {
|
||||
type = 'QPolygon'
|
||||
@ -73,6 +73,7 @@ export default class QPolygon extends fabric.Group {
|
||||
stroke: this.stroke,
|
||||
strokeWidth: this.strokeWidth,
|
||||
fontSize: this.fontSize,
|
||||
idx: i,
|
||||
direction: getDirectionByPoint(point, nextPoint),
|
||||
})
|
||||
|
||||
@ -321,19 +322,20 @@ export default class QPolygon extends fabric.Group {
|
||||
|
||||
// 보조선 그리기
|
||||
drawHelpLine(chon = 4) {
|
||||
if (!this.isValid()) {
|
||||
drawHelpLineInHexagon(this, chon)
|
||||
/*if (!this.isValid()) {
|
||||
return
|
||||
}
|
||||
}*/
|
||||
|
||||
if (this.lines.length === 4) {
|
||||
/*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) {
|
||||
} /!* else if (this.lines.length === 8) {
|
||||
// TODO : 8각형
|
||||
this.drawHelpLineInOctagon(chon)
|
||||
}*/
|
||||
}*!/*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -925,6 +927,7 @@ export default class QPolygon extends fabric.Group {
|
||||
initPoints: this.initPoints,
|
||||
initOption: this.initOption,
|
||||
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 { 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 { fabric } from 'fabric'
|
||||
|
||||
export const Mode = {
|
||||
DRAW_LINE: 'drawLine', // 기준선 긋기모드
|
||||
@ -32,8 +33,12 @@ export function useMode() {
|
||||
const [roof, setRoof] = useRecoilState(roofState)
|
||||
const [wall, setWall] = useRecoilState(wallState)
|
||||
|
||||
const [endPoint, setEndPoint] = useState(null)
|
||||
|
||||
const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState)
|
||||
|
||||
const [canvasSize] = useRecoilState(canvasSizeState)
|
||||
|
||||
useEffect(() => {
|
||||
// 이벤트 리스너 추가
|
||||
if (!canvas) {
|
||||
@ -47,6 +52,93 @@ export function useMode() {
|
||||
}
|
||||
}, [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) => {
|
||||
switch (mode) {
|
||||
case 'default':
|
||||
@ -98,6 +190,7 @@ export function useMode() {
|
||||
originY: 'center',
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
historyPoints.current.push(circle)
|
||||
points.current.push(circle)
|
||||
canvas?.add(circle)
|
||||
@ -142,6 +235,8 @@ export function useMode() {
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
setEndPoint(endPointCircle)
|
||||
|
||||
canvas?.add(endPointCircle)
|
||||
|
||||
historyPoints.current.push(endPointCircle)
|
||||
@ -221,10 +316,12 @@ export function useMode() {
|
||||
}
|
||||
|
||||
const changeMode = (canvas, mode) => {
|
||||
setEndPoint(null)
|
||||
setMode(mode)
|
||||
// mode변경 시 이전 이벤트 제거
|
||||
setCanvas(canvas)
|
||||
canvas?.off('mouse:down')
|
||||
|
||||
addEvent(mode)
|
||||
}
|
||||
|
||||
@ -242,6 +339,8 @@ export function useMode() {
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
setEndPoint(circle)
|
||||
|
||||
historyPoints.current.push(circle)
|
||||
points.current.push(circle)
|
||||
canvas?.add(circle)
|
||||
@ -308,7 +407,7 @@ export function useMode() {
|
||||
originY: 'center',
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
setEndPoint(endPointCircle)
|
||||
canvas?.add(endPointCircle)
|
||||
|
||||
historyPoints.current.push(endPointCircle)
|
||||
@ -556,7 +655,7 @@ export function useMode() {
|
||||
if (!otherLines) {
|
||||
// polygon.fillCell()
|
||||
canvas.renderAll()
|
||||
polygon.setViewLengthText(false)
|
||||
// polygon.setViewLengthText(false)
|
||||
setMode(Mode.DEFAULT)
|
||||
}
|
||||
|
||||
|
||||
@ -649,3 +649,26 @@ export function removeDuplicatePoints(points) {
|
||||
|
||||
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 QPolygon from '@/components/fabric/QPolygon'
|
||||
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 = () => {
|
||||
fabric.QPolygon = fabric.util.createClass(fabric.Group, {})
|
||||
@ -14,8 +26,287 @@ export const defineQPloygon = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export const drawHelpLineInHexagon2 = (polygon, chon) => {
|
||||
const oneSideLines = [...polygon.lines].map((line) => {
|
||||
export const drawHelpLineInHexagon = (polygon, chon) => {
|
||||
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
|
||||
if (line.direction === 'top') {
|
||||
newX1 = line.x2
|
||||
@ -42,288 +333,4 @@ export const drawHelpLineInHexagon2 = (polygon, chon) => {
|
||||
}
|
||||
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