셀추가 작업

This commit is contained in:
yjnoh 2024-08-06 17:56:37 +09:00
parent 78f77e8c6e
commit 69568966ba
2 changed files with 164 additions and 56 deletions

View File

@ -204,7 +204,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.canvas = canvas
},
fillCell(cell = { width: 50, height: 100, padding: 10 }) {
const points = this.getCurrentPoints()
const points = this.points
const minX = Math.min(...points.map((p) => p.x))
const maxX = Math.max(...points.map((p) => p.x))
@ -231,8 +231,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
const rectLeft = minX + i * (rectWidth + cell.padding) + tmpWidth
const rectTop = minY + j * (rectHeight + cell.padding) + tmpHeight
const rectLeft = minX + i * (rectWidth + cell.padding)
const rectTop = minY + j * (rectHeight + cell.padding)
const rectPoints = [
{ x: rectLeft, y: rectTop },
@ -240,6 +240,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
{ x: rectLeft, y: rectTop + rectHeight },
{ x: rectLeft + rectWidth, y: rectTop + rectHeight },
]
const allPointsInside = rectPoints.every((point) => this.inPolygon(point))
if (allPointsInside) {
@ -272,6 +273,102 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.cells = drawCellsArray
return drawCellsArray
},
fillCellABTemplate(cell = { width: 50, height: 100, padding: 5, parallelPoint: undefined, startX: 0, startY: 0 }) {
const points = this.points
const minX = Math.min(...points.map((p) => p.x)) //왼쪽
const maxX = Math.max(...points.map((p) => p.x)) //오른쪽
const minY = Math.min(...points.map((p) => p.y)) //위
const maxY = Math.max(...points.map((p) => p.y)) //아래
const boundingBoxWidth = maxX - minX
const boundingBoxHeight = maxY - minY
const rectWidth = cell.width
const rectHeight = cell.height
const cols = Math.floor((boundingBoxWidth + cell.padding) / (rectWidth + cell.padding))
const rows = Math.floor((boundingBoxHeight + cell.padding) / (rectHeight + cell.padding))
//전체 높이에서 패딩을 포함하고 rows를 곱해서 여백길이를 계산 후에 2로 나누면 반높이를 넣어서 중간으로 정렬
const tmpHeight = (boundingBoxHeight - (rectHeight + cell.padding) * rows) / 2
//센터 정렬시에 쓴다 체크박스가 존재함 TODO: if문 추가해서 정렬해야함
const tmpWidth = (boundingBoxWidth - (rectWidth + cell.padding) * cols) / 2
const drawCellsArray = [] //그려진 셀의 배열
let idx = 1
if (cell.parallelPoint > -1) {
//4각형 이상이면 각 꼭지점에서 위, 아래로 이동하면서 채움
//앞에서 -1로 선언함
if (cell.parallelPoint === 1 || cell.parallelPoint === 2) {
//ㄴ자 역ㄱ자
//밑에서 위로 올라가야하면
cell.startY = cell.startY - (rectHeight + cell.padding) * rows
if (cell.parallelPoint === 2) {
cell.startX = cell.startX - (rectWidth + cell.padding) * cols
}
} else {
if (cell.parallelPoint === 5) {
cell.startX = cell.startX - (rectWidth + cell.padding) * cols
}
}
}
let startXPos, startYPos
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
if (cell.parallelPoint > -1) {
startXPos = cell.startX + i * (rectWidth + cell.padding)
startYPos = cell.startY + j * (rectHeight + cell.padding)
} else {
startXPos = minX + i * (rectWidth + cell.padding)
startYPos = minY + j * (rectHeight + cell.padding)
}
const rectPoints = []
rectPoints.push(
{ x: startXPos, y: startYPos },
{ x: startXPos + rectWidth, y: startYPos },
{ x: startXPos, y: startYPos + rectHeight },
{ x: startXPos + rectWidth, y: startYPos + rectHeight },
)
const allPointsInside = rectPoints.every((point) => this.inPolygon(point))
if (allPointsInside) {
const rect = new fabric.Rect({
left: startXPos,
top: startYPos,
width: rectWidth,
height: rectHeight,
fill: '#BFFD9F',
stroke: 'black',
selectable: true, // 선택 가능하게 설정
// lockMovementX: true, // X 축 이동 잠금
// lockMovementY: true, // Y 축 이동 잠금
// lockRotation: true, // 회전 잠금
// lockScalingX: true, // X 축 크기 조정 잠금
// lockScalingY: true, // Y 축 크기 조정 잠금
opacity: 0.8,
name: 'cell',
idx: idx,
})
idx++
drawCellsArray.push(rect) //배열에 넣어서 반환한다
this.canvas.add(rect)
}
}
}
this.canvas?.renderAll()
this.cells = drawCellsArray
return drawCellsArray
},
inPolygon(point) {
const vertices = this.points
let intersects = 0
@ -295,7 +392,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
}
let xInt = ((point.y - vertex1.y) * (vertex2.x - vertex1.x)) / (vertex2.y - vertex1.y) + vertex1.x
if (xInt < point.x) {
if (xInt <= point.x) {
intersects++
}
}

View File

@ -510,7 +510,7 @@ export function useMode() {
* 마우스로 그린 기준으로 외벽선을 완성시켜준다.
* makePolygon 함수에 포함되어있던 내용을 다른 템플릿 적용에서도 사용할수 있도록 함수로 대체
*/
const drawWallPolygon = () => {
const drawWallPolygon = (sort = true) => {
const firstPoint = historyPoints.current[0]
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
historyPoints.current.forEach((point) => {
@ -521,7 +521,7 @@ export function useMode() {
historyPoints.current = []
// handleOuterlines()
const wall = makePolygon()
const wall = makePolygon(null, sort)
wall.set({ name: 'wall' })
setWall(wall)
@ -638,7 +638,7 @@ export function useMode() {
canvas?.renderAll()
}
const makePolygon = (otherLines) => {
const makePolygon = (otherLines, sort = true) => {
// 캔버스에서 모든 라인 객체를 찾습니다.
const lines = otherLines || historyLines.current
@ -685,6 +685,7 @@ export function useMode() {
fill: 'transparent',
viewLengthText: true,
fontSize: fontSize,
sort: sort,
},
canvas,
)
@ -1087,7 +1088,7 @@ export function useMode() {
offsetPoints.push(offsetPoint)
}
return makePolygon(offsetPoints)
return makePolygon(offsetPoints, false)
}
/**
@ -1146,7 +1147,7 @@ export function useMode() {
const applyTemplateA = () => {
changeMode(canvas, Mode.EDIT)
const polygon = drawWallPolygon()
const polygon = drawWallPolygon(false)
handleClear()
if (polygon.lines.length === 4) {
@ -1895,12 +1896,7 @@ export function useMode() {
//작은 지붕쪽 높이 길이를 구하는 로직
let secondVertCenterPoint = (lastLine.x1 + lastLine.x2) / 2
secondVertCenterLine = new QLine([secondVertCenterPoint, middleSubLine.y1, secondVertCenterPoint, middleSubLine.y2 + edge], {
stroke: 'blue',
strokeWidth: 4,
property: 'centerLine',
fontSize: 14,
})
secondVertCenterLine = new QLine([secondVertCenterPoint, middleSubLine.y1, secondVertCenterPoint, middleSubLine.y2 + edge], centerLineOpt)
canvas.add(secondVertCenterLine)
outLines.push(secondVertCenterLine)
@ -2085,38 +2081,10 @@ export function useMode() {
return tmpArray
}
// 외적을 계산하는 함수
function crossProduct(p1, p2, p3) {
const dx1 = p2.x - p1.x
const dy1 = p2.y - p1.y
const dx2 = p3.x - p2.x
const dy2 = p3.y - p2.y
return dx1 * dy2 - dy1 * dx2
}
let concaveIndices = [] //볼록한 부분 인덱스 배열
let concavePointIndices = [] //오목한 부분 인덱스 배열
// 오목한 부분 찾기
function findConcavePointIndices(points) {
let concaveIndices = []
for (let i = 0; i < points.length; i++) {
const p1 = points[i]
const p2 = points[(i + 1) % points.length]
const p3 = points[(i + 2) % points.length]
const cross = crossProduct(p1, p2, p3)
if (cross < 0) {
concaveIndices.push((i + 1) % points.length)
} else {
concavePointIndices.push((i + 1) % points.length)
}
}
return concaveIndices
}
// 오목한 부분 인덱스 찾기
concaveIndices = findConcavePointIndices(points) //오목한 부분을 제외한 인덱스
const concavePoints = concaveIndices.map((index) => points[index])
const concaveIndicesObj = findConcavePointIndices(points) //오목한 부분을 제외한 인덱스
let concavePointIndices = concaveIndicesObj.concavePointIndices
const concaveLine = {
index: concavePointIndices[0],
line: lines[concavePointIndices[0]],
@ -2168,7 +2136,7 @@ export function useMode() {
offsetPoints.push(offsetPoint)
}
const outlinePolygon = makePolygon(offsetPoints)
const outlinePolygon = makePolygon(offsetPoints, false)
outlinePolygon.setViewLengthText(false)
// 아웃라인 폴리곤의 각 변을 선으로 생성
@ -2178,7 +2146,7 @@ export function useMode() {
const line = new QLine([start.x, start.y, end.x, end.y], {
stroke: 'blue',
strokeWidth: 2,
strokeWidth: 1,
property: 'normal',
fontSize: 14,
idx: i,
@ -2607,7 +2575,7 @@ export function useMode() {
*/
const applyTemplateB = () => {
changeMode(canvas, Mode.EDIT)
const polygon = drawWallPolygon()
const polygon = drawWallPolygon(false)
const params = {
eaves: 50,
edge: 20,
@ -3149,7 +3117,7 @@ export function useMode() {
ctx.scale(ratio, ratio)
if (mode === 'cell') {
ctx.fillStyle = 'rgba(0, 0, 0, 0.3)'
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'
ctx.fillRect(0, 0, patternSize.width * 2, patternSize.height * 2)
}
@ -3286,7 +3254,9 @@ export function useMode() {
canvas?.renderAll()
}
const pattern = getRoofPattern(roofStyle, 'cell')
const pattern = getRoofPattern(roofStyle, 'cell') //셀모드 배경색을 칠한다
polygons.sort((a, b) => a.lines.length > b.lines.length) //무조건 잴 긴거 정렬
// 외각선을 안쪽으로 그려 가대선을 그린다.
polygons.forEach((polygon, index) => {
@ -3312,9 +3282,6 @@ export function useMode() {
trestlePolygon.on('mousedown', function () {
toggleSelection(trestlePolygon)
})
console.log('polygon', polygon)
polygon.set({ fill: pattern })
})
@ -3349,7 +3316,7 @@ export function useMode() {
}
}
const inputCellSize = { width: 172, height: 113 }
const inputCellSize = { width: 172, height: 113 } //추후 입력받는 값으로 변경
const cellSize = { ...inputCellSize } //기본으로 가로형으로 넣고
if (templateType === 2) {
@ -3357,7 +3324,25 @@ export function useMode() {
}
selectedCellRoofArray.forEach((polygon, index) => {
const drawCells = polygon.fillCell({ width: cellSize.width, height: cellSize.height, padding: 10 })
let parallelPoint = -1 //오목한 부분의 반대 꼭지점 //없는 애들도 있어서 -1
const startPoint = {} //도형의 시작점을 찾기 위해
if (polygon.lines.length > 4) {
const concave = findConcavePointIndices(polygon.points) //오목한 부분기준으로 시작점을 찾으려 계산
parallelPoint = parseInt(concave.concavePointIndices[0] + 3) % polygon.points.length //시작점을 찾기 위해 적용
startPoint.x = polygon.points[parallelPoint].x
startPoint.y = polygon.points[parallelPoint].y
}
const drawCells = polygon.fillCellABTemplate({
width: cellSize.width,
height: cellSize.height,
padding: 10,
parallelPoint: parallelPoint,
startX: startPoint.x,
startY: startPoint.y,
})
// const drawCells = polygon.fillCell({ width: cellSize.width, height: cellSize.height, padding: 10 })
drawCellsArray.push({ roofIndex: polygon.customIndex, drawCells: drawCells })
})
@ -3411,6 +3396,32 @@ export function useMode() {
setDrewRoofCells(roofCells)
}
// 외적을 계산하는 함수
const crossProduct = (p1, p2, p3) => {
const dx1 = p2.x - p1.x
const dy1 = p2.y - p1.y
const dx2 = p3.x - p2.x
const dy2 = p3.y - p2.y
return dx1 * dy2 - dy1 * dx2
}
// 오목한 부분 찾기
const findConcavePointIndices = (points) => {
let concaveIndices = []
let concavePointIndices = []
for (let i = 0; i < points.length; i++) {
const p1 = points[i]
const p2 = points[(i + 1) % points.length]
const p3 = points[(i + 2) % points.length]
const cross = crossProduct(p1, p2, p3)
if (cross < 0) {
concaveIndices.push((i + 1) % points.length)
} else {
concavePointIndices.push((i + 1) % points.length)
}
}
return { concaveIndices: concaveIndices, concavePointIndices: concavePointIndices }
}
return {
mode,
setMode,