test
This commit is contained in:
parent
3b9abe4bb3
commit
89007b79ac
@ -12,7 +12,7 @@ import { QLine } from '@/components/fabric/QLine'
|
|||||||
import { getTests, getCanvasState, insertCanvasState } from '@/lib/canvas'
|
import { getTests, getCanvasState, insertCanvasState } from '@/lib/canvas'
|
||||||
|
|
||||||
export default function Roof2() {
|
export default function Roof2() {
|
||||||
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas, changeCanvas } = useCanvas('canvas')
|
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
|
||||||
|
|
||||||
//canvas 기본 사이즈
|
//canvas 기본 사이즈
|
||||||
const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState)
|
const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState)
|
||||||
@ -174,8 +174,31 @@ export default function Roof2() {
|
|||||||
{ x: 1088, y: 991 },
|
{ x: 1088, y: 991 },
|
||||||
{ x: 1088, y: 42 },
|
{ x: 1088, y: 42 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const eightPoint = [
|
||||||
|
{ x: 240, y: 130 },
|
||||||
|
{ x: 240, y: 630 },
|
||||||
|
{ x: 640, y: 630 },
|
||||||
|
{ x: 640, y: 480 },
|
||||||
|
{ x: 440, y: 480 },
|
||||||
|
{ x: 440, y: 280 },
|
||||||
|
{ x: 740, y: 280 },
|
||||||
|
{ x: 740, y: 130 },
|
||||||
|
]
|
||||||
|
|
||||||
|
const eightPoint2 = [
|
||||||
|
{ x: 197, y: 215 },
|
||||||
|
{ x: 197, y: 815 },
|
||||||
|
{ x: 397, y: 815 },
|
||||||
|
{ x: 397, y: 1115 },
|
||||||
|
{ x: 697, y: 1115 },
|
||||||
|
{ x: 697, y: 815 },
|
||||||
|
{ x: 897, y: 815 },
|
||||||
|
{ x: 897, y: 215 },
|
||||||
|
]
|
||||||
|
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
const polygon = new QPolygon(type4, {
|
const polygon = new QPolygon(eightPoint, {
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
@ -212,7 +235,7 @@ export default function Roof2() {
|
|||||||
[200, 200, 500, 500],
|
[200, 200, 500, 500],
|
||||||
{
|
{
|
||||||
stroke: 'black',
|
stroke: 'black',
|
||||||
strokeWidth: 1,
|
strokeWidth: 5,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
},
|
},
|
||||||
@ -378,11 +401,14 @@ export default function Roof2() {
|
|||||||
<Button className="m-1 p-2" onClick={PolygonToLine}>
|
<Button className="m-1 p-2" onClick={PolygonToLine}>
|
||||||
PolygonToLine
|
PolygonToLine
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="m-1 p-2" onClick={handleSaveCanvas}>
|
{/*<Button className="m-1 p-2" onClick={handleSaveCanvas}>
|
||||||
canvas 내용 저장하기
|
canvas 내용 저장하기
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="m-1 p-2" onClick={handleLoadCanvas}>
|
<Button className="m-1 p-2" onClick={handleLoadCanvas}>
|
||||||
canvas 내용 불러오기
|
canvas 내용 불러오기
|
||||||
|
</Button>*/}
|
||||||
|
<Button className="m-1 p-2" onClick={addCanvas}>
|
||||||
|
캔버스 추가
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
||||||
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
||||||
|
|||||||
@ -12,6 +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'
|
||||||
|
|
||||||
export default class QPolygon extends fabric.Group {
|
export default class QPolygon extends fabric.Group {
|
||||||
type = 'QPolygon'
|
type = 'QPolygon'
|
||||||
@ -49,7 +50,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
const sortPoints = sortedPoints(points)
|
const sortPoints = sortedPoints(points)
|
||||||
const polygon = new fabric.Polygon(sortPoints, options)
|
const polygon = new fabric.Polygon(sortPoints, options)
|
||||||
|
|
||||||
super([polygon], {})
|
super([polygon], { selectable: false })
|
||||||
|
|
||||||
this.fontSize = options.fontSize
|
this.fontSize = options.fontSize
|
||||||
this.points = sortPoints
|
this.points = sortPoints
|
||||||
@ -115,7 +116,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.addWithUpdate()
|
this.canvas.add()
|
||||||
}
|
}
|
||||||
|
|
||||||
addLengthText() {
|
addLengthText() {
|
||||||
@ -144,7 +145,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.texts.push(text)
|
this.texts.push(text)
|
||||||
this.addWithUpdate(text)
|
this.canvas.add(text)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.canvas.renderAll()
|
this.canvas.renderAll()
|
||||||
@ -199,7 +200,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
const isInside = rectPoints.every((rectPoint) => this.inPolygon(rectPoint) && this.distanceFromEdge(rectPoint) >= cell.padding)
|
const isInside = rectPoints.every((rectPoint) => this.inPolygon(rectPoint) && this.distanceFromEdge(rectPoint) >= cell.padding)
|
||||||
|
|
||||||
if (isInside) {
|
if (isInside) {
|
||||||
this.addWithUpdate(rect)
|
this.canvas.add(rect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -328,7 +329,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
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각형
|
||||||
this.drawHelpLineInHexagon2(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)
|
||||||
@ -523,12 +524,12 @@ export default class QPolygon extends fabric.Group {
|
|||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
this.addWithUpdate(realLine1)
|
this.canvas.add(realLine1)
|
||||||
this.addWithUpdate(realLine2)
|
this.canvas.add(realLine2)
|
||||||
this.addWithUpdate(realLine3)
|
this.canvas.add(realLine3)
|
||||||
this.addWithUpdate(realLine4)
|
this.canvas.add(realLine4)
|
||||||
this.addWithUpdate(realLine5)
|
this.canvas.add(realLine5)
|
||||||
this.addWithUpdate(realLine6)
|
this.canvas.add(realLine6)
|
||||||
if (smallestLength !== maxLength) {
|
if (smallestLength !== maxLength) {
|
||||||
// 정사각형이 아닌경우에만 용마루를 추가한다.
|
// 정사각형이 아닌경우에만 용마루를 추가한다.
|
||||||
this.canvas.add(ridge)
|
this.canvas.add(ridge)
|
||||||
@ -763,133 +764,146 @@ export default class QPolygon extends fabric.Group {
|
|||||||
const y1 = point.y
|
const y1 = point.y
|
||||||
const x2 = wallPoint.x
|
const x2 = wallPoint.x
|
||||||
const y2 = wallPoint.y
|
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
|
let newX2, newY2
|
||||||
|
|
||||||
// x1, y1을 기준으로 x2, y2와의 거리를 유지한 새로운 직선 생성
|
// x1, y1을 기준으로 x2, y2와의 거리를 유지한 새로운 직선 생성
|
||||||
const angle = Math.atan2(y2 - y1, x2 - x1)
|
const angle = Math.atan2(y2 - y1, x2 - x1)
|
||||||
|
|
||||||
newX2 = x1 + (maxLength / 2) * Math.cos(angle)
|
newX2 = x1 + (maxLength / 2) * Math.cos(angle)
|
||||||
newY2 = y1 + (maxLength / 2) * Math.sin(angle)
|
newY2 = y1 + (maxLength / 2) * Math.sin(angle)
|
||||||
|
|
||||||
const line = new QLine([x1, y1, newX2, newY2], {
|
const line = new QLine([x1, y1, newX2, newY2], {
|
||||||
fontSize: this.fontSize,
|
fontSize: this.fontSize,
|
||||||
stroke: 'blue',
|
stroke: 'blue',
|
||||||
idx: index,
|
idx: index,
|
||||||
|
})
|
||||||
|
historyLines.push(line)
|
||||||
|
this.canvas.add(line)
|
||||||
|
|
||||||
|
this.canvas.renderAll()
|
||||||
})
|
})
|
||||||
historyLines.push(line)
|
|
||||||
this.addWithUpdate(line)
|
/**
|
||||||
|
* 삼각 지붕
|
||||||
|
*/
|
||||||
|
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()
|
this.canvas.renderAll()
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
|
||||||
* 삼각 지붕
|
|
||||||
*/
|
|
||||||
historyLines.forEach((line, index) => {
|
|
||||||
const prevLine = historyLines[(index - 1 + historyLines.length) % historyLines.length]
|
|
||||||
|
|
||||||
let intersectionPoint = calculateIntersection(line, prevLine)
|
|
||||||
|
|
||||||
if (!intersectionPoint) {
|
|
||||||
notInterSectionLines.push(line)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const helpLine1 = new QLine([prevLine.x1, prevLine.y1, intersectionPoint.x, intersectionPoint.y], {
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'red',
|
|
||||||
})
|
|
||||||
|
|
||||||
const helpLine2 = new QLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], {
|
|
||||||
fontSize: this.fontSize,
|
|
||||||
stroke: 'red',
|
|
||||||
})
|
|
||||||
notInterSectionLines.pop()
|
|
||||||
helpPoints.push(intersectionPoint)
|
|
||||||
|
|
||||||
this.addWithUpdate(helpLine1)
|
|
||||||
this.addWithUpdate(helpLine2)
|
|
||||||
this.removeWithUpdate(prevLine)
|
|
||||||
this.removeWithUpdate(line)
|
|
||||||
this.canvas.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.addWithUpdate(ridge)
|
|
||||||
this.canvas.renderAll()
|
|
||||||
|
|
||||||
this.addWithUpdate(ridgeHelpLine)
|
|
||||||
this.removeWithUpdate(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.addWithUpdate(ridgeConnectLine)
|
|
||||||
this.canvas.renderAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.canvas.renderAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawHelpLineInOctagon(chon) {}
|
drawHelpLineInOctagon(chon) {}
|
||||||
@ -897,6 +911,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
getObject() {
|
getObject() {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
sou
|
||||||
|
|
||||||
toObject(propertiesToInclude) {
|
toObject(propertiesToInclude) {
|
||||||
return fabric.util.object.extend(this.callSuper('toObject'), {
|
return fabric.util.object.extend(this.callSuper('toObject'), {
|
||||||
@ -909,6 +924,7 @@ export default class QPolygon extends fabric.Group {
|
|||||||
wall: this.wall,
|
wall: this.wall,
|
||||||
initPoints: this.initPoints,
|
initPoints: this.initPoints,
|
||||||
initOption: this.initOption,
|
initOption: this.initOption,
|
||||||
|
objects: this.getObjects().map((obj) => obj.toObject(propertiesToInclude)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -569,21 +569,23 @@ export function useCanvas(id) {
|
|||||||
console.log(JSON.parse(str))
|
console.log(JSON.parse(str))
|
||||||
|
|
||||||
// 역직렬화하여 캔버스에 객체를 다시 추가합니다.
|
// 역직렬화하여 캔버스에 객체를 다시 추가합니다.
|
||||||
canvas?.loadFromJSON(
|
setTimeout(() => {
|
||||||
JSON.parse(str),
|
canvas?.loadFromJSON(
|
||||||
function () {
|
JSON.parse(str),
|
||||||
// 모든 객체가 로드되고 캔버스에 추가된 후 호출됩니다.
|
function () {
|
||||||
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
// 모든 객체가 로드되고 캔버스에 추가된 후 호출됩니다.
|
||||||
console.log('Objects are reloaded and rendered on canvas.')
|
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
||||||
},
|
console.log('Objects are reloaded and rendered on canvas.')
|
||||||
function (o, object) {
|
},
|
||||||
// 각 객체가 로드될 때마다 호출됩니다.
|
function (o, object) {
|
||||||
console.log('Object loaded: ', o, object)
|
// 각 객체가 로드될 때마다 호출됩니다.
|
||||||
|
console.log('Object loaded: ', o, object)
|
||||||
|
|
||||||
canvas?.add(object)
|
canvas?.add(object)
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
/*canvas?.loadFromJSON(JSON.parse(str), () => {
|
/*canvas?.loadFromJSON(JSON.parse(str), () => {
|
||||||
console.log('load done')
|
console.log('load done')
|
||||||
|
|||||||
@ -848,6 +848,7 @@ export function useMode() {
|
|||||||
const roof = makePolygon(offsetPoints)
|
const roof = makePolygon(offsetPoints)
|
||||||
roof.setWall(polygon)
|
roof.setWall(polygon)
|
||||||
setRoof(roof)
|
setRoof(roof)
|
||||||
|
|
||||||
roof.drawHelpLine()
|
roof.drawHelpLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export function actionHandler(eventData, transform, x, y) {
|
|||||||
|
|
||||||
// define a function that can keep the polygon in the same position when we change its width/height/top/left
|
// define a function that can keep the polygon in the same position when we change its width/height/top/left
|
||||||
export function anchorWrapper(anchorIndex, fn) {
|
export function anchorWrapper(anchorIndex, fn) {
|
||||||
return function(eventData, transform, x, y) {
|
return function (eventData, transform, x, y) {
|
||||||
let fabricObject = transform.target
|
let fabricObject = transform.target
|
||||||
let originX = fabricObject?.points[anchorIndex].x - fabricObject.pathOffset.x
|
let originX = fabricObject?.points[anchorIndex].x - fabricObject.pathOffset.x
|
||||||
let originY = fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y
|
let originY = fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y
|
||||||
@ -318,15 +318,50 @@ export function calculateIntersection(line1, line2) {
|
|||||||
return null // 교차점이 선분의 범위 내에 없음
|
return null // 교차점이 선분의 범위 내에 없음
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const findIntersection1 = (line1, line2) => {
|
||||||
|
const { x1, y1, x2, y2 } = line1 // 첫 번째 선의 두 점
|
||||||
|
|
||||||
|
const x3 = line2.x1
|
||||||
|
const y3 = line2.y1
|
||||||
|
const x4 = line2.x2
|
||||||
|
const y4 = line2.y2
|
||||||
|
|
||||||
|
// 선의 방정식의 계수 계산
|
||||||
|
const A1 = y2 - y1
|
||||||
|
const B1 = x1 - x2
|
||||||
|
const C1 = A1 * x1 + B1 * y1
|
||||||
|
|
||||||
|
const A2 = y4 - y3
|
||||||
|
const B2 = x3 - x4
|
||||||
|
const C2 = A2 * x3 + B2 * y3
|
||||||
|
|
||||||
|
const determinant = A1 * B2 - A2 * B1
|
||||||
|
|
||||||
|
if (determinant === 0) {
|
||||||
|
// 두 선이 평행하거나 일직선일 경우
|
||||||
|
console.log('두 직선은 평행하거나 일직선입니다.')
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = (B1 * C2 - B2 * C1) / determinant
|
||||||
|
const y = (A1 * C2 - A2 * C1) / determinant
|
||||||
|
|
||||||
|
return { x, y }
|
||||||
|
}
|
||||||
|
|
||||||
export const calculateIntersection2 = (line1, line2) => {
|
export const calculateIntersection2 = (line1, line2) => {
|
||||||
const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2])
|
const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2])
|
||||||
return { x: Math.round(result[0]), y: Math.round(result[1]) }
|
return { x: Math.round(result[0]), y: Math.round(result[1]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
function findOrthogonalPoint(x1, y1, x2, y2, x3, y3, x4, y4) {
|
export function findOrthogonalPoint(line1, line2) {
|
||||||
// Calculate the intersection point of two lines
|
// Calculate the intersection point of two lines
|
||||||
const intersectionX = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
const intersectionX =
|
||||||
const intersectionY = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4))
|
((line1.x1 * line2.y1 - line1.y1 * line2.x1) * (line2.x2 - line2.x1) - (line1.x1 - line1.x2) * (line2.x2 * line2.y2 - line2.y1 * line2.x1)) /
|
||||||
|
((line1.x1 - line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x2 - line2.x1))
|
||||||
|
const intersectionY =
|
||||||
|
((line1.x1 * line2.y1 - line1.y1 * line2.x1) * (line2.y2 - line2.y1) - (line1.y1 - line1.y2) * (line2.x2 * line2.y2 - line2.y1 * line2.x1)) /
|
||||||
|
((line1.x1 - line1.x2) * (line2.y1 - line2.y2) - (line1.y1 - line1.y2) * (line2.x2 - line2.x1))
|
||||||
|
|
||||||
return { x: intersectionX, y: intersectionY }
|
return { x: intersectionX, y: intersectionY }
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/util/qline-utils.js
Normal file
12
src/util/qline-utils.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { fabric } from 'fabric'
|
||||||
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
|
||||||
|
export const defineQLine = () => {
|
||||||
|
fabric.QLine = fabric.util.createClass(fabric.Group, {})
|
||||||
|
fabric.QLine.fromObject = function (object, callback) {
|
||||||
|
const { initOption, initPoints, initLengthTxt } = object
|
||||||
|
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
|
||||||
|
return callback(new QLine(initPoints, initOption, initLengthTxt))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
251
src/util/qpolygon-utils.js
Normal file
251
src/util/qpolygon-utils.js
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
import { fabric } from 'fabric'
|
||||||
|
import QPolygon from '@/components/fabric/QPolygon'
|
||||||
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
import { calculateIntersection, calculateIntersection2, distanceBetweenPoints, findIntersection1 } from '@/util/canvas-util'
|
||||||
|
|
||||||
|
export const defineQPloygon = () => {
|
||||||
|
fabric.QPolygon = fabric.util.createClass(fabric.Group, {})
|
||||||
|
// fromObject 메서드를 QLine 클래스에 직접 추가
|
||||||
|
fabric.QPolygon.fromObject = function (object, callback) {
|
||||||
|
const { initOption, initPoints, initLengthTxt } = object
|
||||||
|
fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
|
||||||
|
return callback(new QPolygon(initPoints, initOption, initLengthTxt))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const drawHelpLineInHexagon2 = (polygon, chon) => {
|
||||||
|
const oneSideLines = [...polygon.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')
|
||||||
|
|
||||||
|
// horizontalLines 를 y1 좌표 기준으로 정렬한다.
|
||||||
|
horizontalLines.sort((a, b) => a.y1 - b.y1)
|
||||||
|
// verticalLines 를 x1 좌표 기준으로 정렬한다.
|
||||||
|
verticalLines.sort((a, b) => a.x1 - b.x1)
|
||||||
|
|
||||||
|
const horizontalMaxLength = horizontalLines.reduce((max, obj) => Math.max(max, obj.length), 0)
|
||||||
|
|
||||||
|
const verticalMaxLength = verticalLines.reduce((max, obj) => Math.max(max, obj.length), 0)
|
||||||
|
// 모든 가로선의 중심선을 긋는다.
|
||||||
|
debugger
|
||||||
|
horizontalLines.forEach((line, index) => {
|
||||||
|
const nextLine = horizontalLines[(index + 1) % horizontalLines.length]
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
const maxLength = horizontalMaxLength < verticalMaxLength ? horizontalMaxLength : verticalMaxLength
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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: polygon.fontSize,
|
||||||
|
stroke: 'green',
|
||||||
|
idx: index,
|
||||||
|
})
|
||||||
|
polygon.canvas.add(line)
|
||||||
|
helpLines.push(line)
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
})
|
||||||
|
|
||||||
|
helpLines.forEach((line, index) => {
|
||||||
|
if (line.isAlreadyInterSection) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const nextLine = helpLines[(index + 1 + helpLines.length) % helpLines.length]
|
||||||
|
polygon.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: 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 = []
|
||||||
|
const interSectionPoints = []
|
||||||
|
|
||||||
|
notInterSectionLines.forEach((line, index) => {
|
||||||
|
line.line.set({ strokeWidth: (index + 1) * 5 })
|
||||||
|
|
||||||
|
centerLines.forEach((centerLine) => {
|
||||||
|
const interSectionPoint = findIntersection1(line, centerLine)
|
||||||
|
console.log('interSectionPoint', interSectionPoint)
|
||||||
|
|
||||||
|
if (!polygon.inPolygon(interSectionPoint) || !interSectionPoint) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
line.interSectionPoints.push(interSectionPoint)
|
||||||
|
interSectionPoints.push(interSectionPoint)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
interSectionPoints.forEach((point) => {
|
||||||
|
const circle = new fabric.Circle({
|
||||||
|
radius: 3,
|
||||||
|
fill: 'red',
|
||||||
|
left: point.x,
|
||||||
|
top: point.y,
|
||||||
|
})
|
||||||
|
|
||||||
|
polygon.canvas.add(circle)
|
||||||
|
polygon.canvas.renderAll()
|
||||||
|
})
|
||||||
|
|
||||||
|
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: 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()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
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