qpolygon 방향 line 추가 및 함수 추가
This commit is contained in:
parent
68cb952b70
commit
446f5ba093
@ -46,6 +46,7 @@ export default function Roof2() {
|
||||
zoomOut,
|
||||
zoom,
|
||||
togglePolygonLine,
|
||||
handleOuterlinesTest2,
|
||||
} = useMode()
|
||||
|
||||
useEffect(() => {
|
||||
@ -135,12 +136,14 @@ export default function Roof2() {
|
||||
if (canvas) {
|
||||
const polygon = new QPolygon(
|
||||
[
|
||||
{ x: 100, y: 100 },
|
||||
{ x: 800, y: 100 },
|
||||
{ x: 800, y: 800 },
|
||||
{ x: 500, y: 800 },
|
||||
{ x: 500, y: 400 },
|
||||
{ x: 100, y: 400 },
|
||||
{ x: 198.5, y: 735 },
|
||||
{ x: 698.5, y: 735 },
|
||||
{ x: 698.5, y: 585 },
|
||||
{ x: 448.5, y: 585 },
|
||||
{ x: 448.5, y: 435 },
|
||||
{ x: 698.5, y: 435 },
|
||||
{ x: 698.5, y: 235 },
|
||||
{ x: 198.5, y: 235 },
|
||||
],
|
||||
{
|
||||
fill: 'transparent',
|
||||
@ -155,10 +158,10 @@ export default function Roof2() {
|
||||
|
||||
canvas?.add(polygon)
|
||||
|
||||
addBackgroundInPolygon(polygon)
|
||||
handleOuterlinesTest2(polygon)
|
||||
|
||||
const lines = togglePolygonLine(polygon)
|
||||
togglePolygonLine(lines[0])
|
||||
// const lines = togglePolygonLine(polygon)
|
||||
// togglePolygonLine(lines[0])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
getDirectionByPoint,
|
||||
getRoofHeight,
|
||||
getRoofHypotenuse,
|
||||
sortedPoints,
|
||||
} from '@/util/canvas-util'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
|
||||
@ -26,15 +27,14 @@ export default class QPolygon extends fabric.Group {
|
||||
throw new Error('Canvas is required.')
|
||||
}
|
||||
|
||||
const polygon = new fabric.Polygon(points, options)
|
||||
const sortPoints = sortedPoints(points)
|
||||
const polygon = new fabric.Polygon(sortPoints, options)
|
||||
|
||||
super([polygon], {})
|
||||
|
||||
this.fontSize = options.fontSize
|
||||
this.points = points
|
||||
this.points = sortPoints
|
||||
this.polygon = polygon
|
||||
this.name = options.name
|
||||
|
||||
this.#init()
|
||||
this.#addEvent()
|
||||
this.#initLines()
|
||||
|
||||
@ -723,7 +723,7 @@ export function useMode() {
|
||||
*/
|
||||
const handleOuterlinesTest = (offset = 71) => {
|
||||
var offsetPoints = []
|
||||
|
||||
|
||||
const sortedIndex = getStartIndex(historyLines.current)
|
||||
let tmpArraySorted = rearrangeArray(historyLines.current, sortedIndex)
|
||||
|
||||
@ -789,6 +789,76 @@ export function useMode() {
|
||||
roof.drawHelpLine()
|
||||
}
|
||||
|
||||
/**
|
||||
*벽 지붕 외곽선 생성 polygon을 입력받아 만들기
|
||||
*/
|
||||
const handleOuterlinesTest2 = (polygon, offset = 71) => {
|
||||
const offsetPoints = []
|
||||
const sortedIndex = getStartIndex(polygon.lines)
|
||||
let tmpArraySorted = rearrangeArray(polygon.lines, sortedIndex)
|
||||
|
||||
if (tmpArraySorted[0].direction === 'right') {
|
||||
//시계방향
|
||||
tmpArraySorted = tmpArraySorted.reverse() //그럼 배열을 거꾸로 만들어서 무조건 반시계방향으로 배열 보정
|
||||
}
|
||||
|
||||
setSortedArray(tmpArraySorted) //recoil에 넣음
|
||||
|
||||
const points = tmpArraySorted.map((line) => ({
|
||||
x: line.x1,
|
||||
y: line.y1,
|
||||
}))
|
||||
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
const prev = points[(i - 1 + points.length) % points.length]
|
||||
const current = points[i]
|
||||
const next = points[(i + 1) % points.length]
|
||||
|
||||
// 두 벡터 계산 (prev -> current, current -> next)
|
||||
const vector1 = { x: current.x - prev.x, y: current.y - prev.y }
|
||||
const vector2 = { x: next.x - current.x, y: next.y - current.y }
|
||||
|
||||
// 벡터의 길이 계산
|
||||
const length1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y)
|
||||
const length2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y)
|
||||
|
||||
// 벡터를 단위 벡터로 정규화
|
||||
const unitVector1 = { x: vector1.x / length1, y: vector1.y / length1 }
|
||||
const unitVector2 = { x: vector2.x / length2, y: vector2.y / length2 }
|
||||
|
||||
// 법선 벡터 계산 (왼쪽 방향)
|
||||
const normal1 = { x: -unitVector1.y, y: unitVector1.x }
|
||||
const normal2 = { x: -unitVector2.y, y: unitVector2.x }
|
||||
|
||||
// 법선 벡터 평균 계산
|
||||
const averageNormal = {
|
||||
x: (normal1.x + normal2.x) / 2,
|
||||
y: (normal1.y + normal2.y) / 2,
|
||||
}
|
||||
|
||||
// 평균 법선 벡터를 단위 벡터로 정규화
|
||||
const lengthNormal = Math.sqrt(
|
||||
averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y,
|
||||
)
|
||||
const unitNormal = {
|
||||
x: averageNormal.x / lengthNormal,
|
||||
y: averageNormal.y / lengthNormal,
|
||||
}
|
||||
|
||||
// 오프셋 적용
|
||||
const offsetPoint = {
|
||||
x1: current.x + unitNormal.x * offset,
|
||||
y1: current.y + unitNormal.y * offset,
|
||||
}
|
||||
|
||||
offsetPoints.push(offsetPoint)
|
||||
}
|
||||
|
||||
const roof = makePolygon(offsetPoints)
|
||||
setRoof(roof)
|
||||
// roof.drawHelpLine()
|
||||
}
|
||||
|
||||
const togglePolygonLine = (obj) => {
|
||||
const rtnLines = []
|
||||
if (obj.type === 'QPolygon') {
|
||||
@ -834,5 +904,6 @@ export function useMode() {
|
||||
zoomOut,
|
||||
zoom,
|
||||
togglePolygonLine,
|
||||
handleOuterlinesTest2,
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,6 +155,30 @@ export const getStartIndex = (lines) => {
|
||||
return smallestIndex
|
||||
}
|
||||
|
||||
/**
|
||||
* points 배열에서 시작점을 찾는 함수
|
||||
* @param points
|
||||
* @returns {number}
|
||||
*/
|
||||
export const getStartIndexPoint = (points) => {
|
||||
let smallestIndex = 0
|
||||
let smallestX1 = points[0].x
|
||||
let smallestY1 = points[0].y
|
||||
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
if (
|
||||
points[i].x < smallestX1 ||
|
||||
(points[i].x === smallestX1 && points[i].y < smallestY1)
|
||||
) {
|
||||
smallestIndex = i
|
||||
smallestX1 = points[i].x
|
||||
smallestY1 = points[i].y
|
||||
}
|
||||
}
|
||||
|
||||
return smallestIndex
|
||||
}
|
||||
|
||||
/**
|
||||
* 이 함수는 두 개의 매개변수를 받습니다: array와 index.
|
||||
* array는 재배열할 대상 배열입니다.
|
||||
@ -309,3 +333,69 @@ export function calculateIntersection(line1, line2) {
|
||||
|
||||
return { x: intersectX, y: intersectY }
|
||||
}
|
||||
|
||||
/**
|
||||
* points배열을 입력받아 반시계방향으로 정렬된 points를 반환합니다.
|
||||
* @param points
|
||||
*/
|
||||
export const sortedPoints = (points) => {
|
||||
const copyPoints = [...points]
|
||||
//points를 x,y좌표를 기준으로 정렬합니다.
|
||||
|
||||
copyPoints.sort((a, b) => {
|
||||
if (a.x === b.x) {
|
||||
return a.y - b.y
|
||||
}
|
||||
return a.x - b.x
|
||||
})
|
||||
|
||||
// 이때 copyPoints를 순회하며 최초엔 x값을 비교하여 같은 점을 찾는다. 이때 이 점이 2번째 점이 된다.
|
||||
// 그 다음점은 2번째 점과 y값이 같은 점이 된다.
|
||||
// 또 그다음 점은 3번째 점과 x값이 같은 점이 된다.
|
||||
// 이를 반복하여 copyPoints를 재배열한다.
|
||||
const resultPoints = [copyPoints[0]]
|
||||
let index = 1
|
||||
let currentPoint = { ...copyPoints[0] }
|
||||
copyPoints.splice(0, 1)
|
||||
|
||||
while (index < points.length) {
|
||||
if (index === points.length - 1) {
|
||||
resultPoints.push(copyPoints[0])
|
||||
index++
|
||||
break
|
||||
} else if (index % 2 === 0) {
|
||||
// 짝수번째는 y값이 같은 점을 찾는다.
|
||||
for (let i = 0; i < copyPoints.length; i++) {
|
||||
// y값이 같은 point가 많은 경우 그 중 x값이 가장 큰걸 찾는다.
|
||||
const temp = copyPoints.filter((point) => point.y === currentPoint.y)
|
||||
// temp중 x값이 가장 큰 값
|
||||
const max = temp.reduce((prev, current) =>
|
||||
prev.x >= current.x ? prev : current,
|
||||
)
|
||||
resultPoints.push(max)
|
||||
currentPoint = max
|
||||
copyPoints.splice(copyPoints.indexOf(max), 1)
|
||||
index++
|
||||
break
|
||||
}
|
||||
} else {
|
||||
// 홀수번째는 x값이 같은 점을 찾는다.
|
||||
for (let i = 0; i < copyPoints.length; i++) {
|
||||
// x값이 같은 point가 많은 경우 그 중 y값이 가장 큰걸 찾는다.
|
||||
const temp = copyPoints.filter((point) => point.x === currentPoint.x)
|
||||
// temp중 y값이 가장 큰 값
|
||||
const max = temp.reduce((prev, current) =>
|
||||
prev.y >= current.y ? prev : current,
|
||||
)
|
||||
|
||||
resultPoints.push(max)
|
||||
currentPoint = max
|
||||
copyPoints.splice(copyPoints.indexOf(max), 1)
|
||||
index++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resultPoints
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user