a,b 패턴 지붕 수정
용마루 생성 끝, 지붕면 생성 중
This commit is contained in:
parent
8c153430cd
commit
e35cacf520
@ -2,7 +2,7 @@ import { fabric } from 'fabric'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
|
||||
import { calculateAngle, drawRidgeRoof, drawShedRoof, toGeoJSON } from '@/util/qpolygon-utils'
|
||||
import { calculateAngle, drawGableRoof, drawRidgeRoof, drawShedRoof, toGeoJSON } from '@/util/qpolygon-utils'
|
||||
import * as turf from '@turf/turf'
|
||||
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||
import Big from 'big.js'
|
||||
@ -330,6 +330,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
} else if (isGableRoof(types)) {
|
||||
// A형, B형 박공 지붕
|
||||
console.log('패턴 지붕')
|
||||
drawGableRoof(this.id, this.canvas, textMode)
|
||||
} else if (isShedRoof(types, this.lines)) {
|
||||
console.log('한쪽흐름 지붕')
|
||||
drawShedRoof(this.id, this.canvas, textMode)
|
||||
|
||||
@ -495,9 +495,7 @@ export const isSamePoint = (a, b) => {
|
||||
* @param canvas
|
||||
* @param textMode
|
||||
*/
|
||||
export const drawEavesRoof = (roofId, canvas, textMode) => {
|
||||
|
||||
}
|
||||
export const drawEavesRoof = (roofId, canvas, textMode) => {}
|
||||
|
||||
/**
|
||||
* 박공지붕(A,B 패턴)
|
||||
@ -506,7 +504,578 @@ export const drawEavesRoof = (roofId, canvas, textMode) => {
|
||||
* @param textMode
|
||||
*/
|
||||
export const drawGableRoof = (roofId, canvas, textMode) => {
|
||||
const roof = canvas?.getObjects().find((object) => object.id === roofId)
|
||||
const wall = canvas.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roofId)
|
||||
|
||||
const baseLines = wall.baseLines.filter((line) => line.attributes.planeSize > 0)
|
||||
const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 }))
|
||||
|
||||
/** baseLine을 기준으로 확인용 polygon 작성 */
|
||||
const checkWallPolygon = new QPolygon(baseLinePoints, {})
|
||||
|
||||
const eavesLines = baseLines.filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
||||
const gableLines = baseLines.filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.GABLE)
|
||||
|
||||
const ridgeLines = []
|
||||
const innerLines = []
|
||||
|
||||
/**
|
||||
* 처마 라인 속성 판단
|
||||
* @param line
|
||||
* @returns {{startPoint: {x, y}, endPoint: {x, y}, length: number, angleDegree: number, normalizedAngle: number, isHorizontal: boolean, isVertical: boolean, isDiagonal: boolean, directionVector: {x: number, y: number}, roofLine}}
|
||||
*/
|
||||
const analyzeEavesLine = (line) => {
|
||||
const tolerance = 1
|
||||
const dx = Big(line.x2).minus(Big(line.x1)).toNumber()
|
||||
const dy = Big(line.y2).minus(Big(line.y1)).toNumber()
|
||||
const length = Math.sqrt(dx * dx + dy * dy)
|
||||
const angleDegree = (Math.atan2(dy, dx) * 180) / Math.PI
|
||||
const normalizedAngle = Math.abs((Math.atan2(dy, dx) * 180) / Math.PI) % 180
|
||||
const directionVector = { x: dx / length, y: dy / length }
|
||||
let isHorizontal = false,
|
||||
isVertical = false,
|
||||
isDiagonal = false
|
||||
if (normalizedAngle < tolerance || normalizedAngle >= 180 - tolerance) {
|
||||
isHorizontal = true
|
||||
} else if (Math.abs(normalizedAngle - 90) <= tolerance) {
|
||||
isVertical = true
|
||||
} else {
|
||||
isDiagonal = true
|
||||
}
|
||||
|
||||
const originPoint = line.attributes.originPoint
|
||||
const midX = (originPoint.x1 + originPoint.x2) / 2
|
||||
const midY = (originPoint.y1 + originPoint.y2) / 2
|
||||
const offset = line.attributes.offset
|
||||
|
||||
const checkRoofLines = roof.lines.filter((roof) => {
|
||||
const roofDx = Big(roof.x2).minus(Big(roof.x1)).toNumber()
|
||||
const roofDy = Big(roof.y2).minus(Big(roof.y1)).toNumber()
|
||||
const roofLength = Math.sqrt(roofDx * roofDx + roofDy * roofDy)
|
||||
const roofVector = { x: roofDx / roofLength, y: roofDy / roofLength }
|
||||
return directionVector.x === roofVector.x && directionVector.y === roofVector.y
|
||||
})
|
||||
|
||||
let roofVector = { x: 0, y: 0 }
|
||||
if (isHorizontal) {
|
||||
const checkPoint = { x: midX, y: midY + offset }
|
||||
if (wall.inPolygon(checkPoint)) {
|
||||
roofVector = { x: 0, y: -1 }
|
||||
} else {
|
||||
roofVector = { x: 0, y: 1 }
|
||||
}
|
||||
}
|
||||
if (isVertical) {
|
||||
const checkPoint = { x: midX + offset, y: midY }
|
||||
if (wall.inPolygon(checkPoint)) {
|
||||
roofVector = { x: -1, y: 0 }
|
||||
} else {
|
||||
roofVector = { x: 1, y: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
const findEdge = { vertex1: { x: midX, y: midY }, vertex2: { x: midX + roofVector.x * offset, y: midY + roofVector.y * offset } }
|
||||
const edgeDx = Big(findEdge.vertex2.x).minus(Big(findEdge.vertex1.x)).toNumber()
|
||||
const edgeDy = Big(findEdge.vertex2.y).minus(Big(findEdge.vertex1.y)).toNumber()
|
||||
const edgeLength = Math.sqrt(edgeDx * edgeDx + edgeDy * edgeDy)
|
||||
const edgeVector = { x: edgeDx / edgeLength, y: edgeDy / edgeLength }
|
||||
|
||||
const intersectRoofLines = []
|
||||
checkRoofLines.forEach((roofLine) => {
|
||||
const lineEdge = { vertex1: { x: roofLine.x1, y: roofLine.y1 }, vertex2: { x: roofLine.x2, y: roofLine.y2 } }
|
||||
const intersect = edgesIntersection(lineEdge, findEdge)
|
||||
if (intersect) {
|
||||
const intersectDx = Big(intersect.x).minus(Big(findEdge.vertex1.x)).toNumber()
|
||||
const intersectDy = Big(intersect.y).minus(Big(findEdge.vertex1.y)).toNumber()
|
||||
const intersectLength = Math.sqrt(intersectDx * intersectDx + intersectDy * intersectDy)
|
||||
const intersectVector = { x: intersectDx / intersectLength, y: intersectDy / intersectLength }
|
||||
if (edgeVector.x === intersectVector.x && edgeVector.y === intersectVector.y) {
|
||||
intersectRoofLines.push({ roofLine, intersect, length: intersectLength })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let currentRoof = intersectRoofLines.find((roof) => isPointOnLineNew(roof.roofLine, roof.intersect))
|
||||
if (!currentRoof) {
|
||||
currentRoof = intersectRoofLines.sort((a, b) => a.length - b.length)[0]
|
||||
}
|
||||
|
||||
let startPoint, endPoint
|
||||
if (isHorizontal) {
|
||||
startPoint = { x: Math.min(line.x1, line.x2, currentRoof.roofLine.x1, currentRoof.roofLine.x2), y: line.y1 }
|
||||
endPoint = { x: Math.max(line.x1, line.x2, currentRoof.roofLine.x1, currentRoof.roofLine.x2), y: line.y2 }
|
||||
}
|
||||
if (isVertical) {
|
||||
startPoint = { x: line.x1, y: Math.min(line.y1, line.y2, currentRoof.roofLine.y1, currentRoof.roofLine.y2) }
|
||||
endPoint = { x: line.x2, y: Math.max(line.y1, line.y2, currentRoof.roofLine.y1, currentRoof.roofLine.y2) }
|
||||
}
|
||||
if (isDiagonal) {
|
||||
startPoint = { x: line.x1, y: line.y1 }
|
||||
endPoint = { x: line.x2, y: line.y2 }
|
||||
}
|
||||
|
||||
return {
|
||||
startPoint,
|
||||
endPoint,
|
||||
length,
|
||||
angleDegree,
|
||||
normalizedAngle,
|
||||
isHorizontal,
|
||||
isVertical,
|
||||
isDiagonal,
|
||||
directionVector: { x: dx / length, y: dy / length },
|
||||
roofLine: currentRoof.roofLine,
|
||||
}
|
||||
}
|
||||
|
||||
const isOverlapLine = (currAnalyze, checkAnalyze) => {
|
||||
// 허용 오차
|
||||
const tolerance = 1
|
||||
|
||||
// 같은 방향인지 확인
|
||||
if (
|
||||
currAnalyze.isHorizontal !== checkAnalyze.isHorizontal ||
|
||||
currAnalyze.isVertical !== checkAnalyze.isVertical ||
|
||||
currAnalyze.isDiagonal !== checkAnalyze.isDiagonal
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (currAnalyze.isHorizontal && !(Math.abs(currAnalyze.startPoint.y - checkAnalyze.startPoint.y) < tolerance)) {
|
||||
// 수평선: y좌표가 다른경우 false
|
||||
return false
|
||||
} else if (currAnalyze.isVertical && !(Math.abs(currAnalyze.startPoint.x - checkAnalyze.startPoint.x) < tolerance)) {
|
||||
// 수직선: x좌표가 다른경우 false
|
||||
return false
|
||||
}
|
||||
|
||||
// 3. 선분 구간 겹침 확인
|
||||
let range1, range2
|
||||
|
||||
if (currAnalyze.isHorizontal) {
|
||||
// 수평선: x 범위로 비교
|
||||
range1 = {
|
||||
min: Math.min(currAnalyze.startPoint.x, currAnalyze.endPoint.x),
|
||||
max: Math.max(currAnalyze.startPoint.x, currAnalyze.endPoint.x),
|
||||
}
|
||||
range2 = {
|
||||
min: Math.min(checkAnalyze.startPoint.x, checkAnalyze.endPoint.x),
|
||||
max: Math.max(checkAnalyze.startPoint.x, checkAnalyze.endPoint.x),
|
||||
}
|
||||
} else {
|
||||
// 수직선: y 범위로 비교
|
||||
range1 = {
|
||||
min: Math.min(currAnalyze.startPoint.y, currAnalyze.endPoint.y),
|
||||
max: Math.max(currAnalyze.startPoint.y, currAnalyze.endPoint.y),
|
||||
}
|
||||
range2 = {
|
||||
min: Math.min(checkAnalyze.startPoint.y, checkAnalyze.endPoint.y),
|
||||
max: Math.max(checkAnalyze.startPoint.y, checkAnalyze.endPoint.y),
|
||||
}
|
||||
}
|
||||
// 구간 겹침 확인
|
||||
const overlapStart = Math.max(range1.min, range2.min)
|
||||
const overlapEnd = Math.min(range1.max, range2.max)
|
||||
|
||||
return Math.max(0, overlapEnd - overlapStart) > 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 처마 라인의 속성 확인 및 정리
|
||||
* @param lines
|
||||
* @returns {{forwardLines: Array, backwardLines: Array}}
|
||||
*/
|
||||
const analyzeAllEavesLines = (lines) => {
|
||||
let forwardLines = []
|
||||
let backwardLines = []
|
||||
lines.forEach((line) => {
|
||||
const analyze = analyzeEavesLine(line)
|
||||
if (analyze.isHorizontal) {
|
||||
if (analyze.directionVector.x > 0) {
|
||||
const overlapLines = forwardLines.filter((forwardLine) => forwardLine !== line && isOverlapLine(analyze, forwardLine.analyze))
|
||||
if (overlapLines.length > 0) {
|
||||
overlapLines.forEach((overlap) => {
|
||||
const overlapAnalyze = overlap.analyze
|
||||
const startPoint = {
|
||||
x: Math.min(analyze.startPoint.x, analyze.endPoint.x, overlapAnalyze.startPoint.x, overlapAnalyze.endPoint.x),
|
||||
y: analyze.startPoint.y,
|
||||
}
|
||||
const endPoint = {
|
||||
x: Math.max(analyze.startPoint.x, analyze.endPoint.x, overlapAnalyze.startPoint.x, overlapAnalyze.endPoint.x),
|
||||
y: analyze.endPoint.y,
|
||||
}
|
||||
analyze.startPoint = startPoint
|
||||
analyze.endPoint = endPoint
|
||||
forwardLines = forwardLines.filter((forwardLine) => forwardLine !== overlap)
|
||||
})
|
||||
}
|
||||
forwardLines.push({ eaves: line, analyze })
|
||||
}
|
||||
if (analyze.directionVector.x < 0) {
|
||||
const overlapLines = backwardLines.filter((backwardLine) => backwardLine !== line && isOverlapLine(analyze, backwardLine.analyze))
|
||||
if (overlapLines.length > 0) {
|
||||
overlapLines.forEach((overlap) => {
|
||||
const overlapAnalyze = overlap.analyze
|
||||
const startPoint = {
|
||||
x: Math.min(analyze.startPoint.x, analyze.endPoint.x, overlapAnalyze.startPoint.x, overlapAnalyze.endPoint.x),
|
||||
y: analyze.startPoint.y,
|
||||
}
|
||||
const endPoint = {
|
||||
x: Math.max(analyze.startPoint.x, analyze.endPoint.x, overlapAnalyze.startPoint.x, overlapAnalyze.endPoint.x),
|
||||
y: analyze.endPoint.y,
|
||||
}
|
||||
analyze.startPoint = startPoint
|
||||
analyze.endPoint = endPoint
|
||||
backwardLines = backwardLines.filter((backwardLine) => backwardLine !== overlap)
|
||||
})
|
||||
}
|
||||
backwardLines.push({ eaves: line, analyze })
|
||||
}
|
||||
}
|
||||
if (analyze.isVertical) {
|
||||
if (analyze.directionVector.y > 0) {
|
||||
const overlapLines = forwardLines.filter((forwardLine) => forwardLine !== line && isOverlapLine(analyze, forwardLine.analyze))
|
||||
if (overlapLines.length > 0) {
|
||||
overlapLines.forEach((overlap) => {
|
||||
const overlapAnalyze = overlap.analyze
|
||||
const startPoint = {
|
||||
x: analyze.startPoint.x,
|
||||
y: Math.min(analyze.startPoint.y, analyze.endPoint.y, overlapAnalyze.startPoint.y, overlapAnalyze.endPoint.y),
|
||||
}
|
||||
const endPoint = {
|
||||
x: analyze.endPoint.x,
|
||||
y: Math.max(analyze.startPoint.y, analyze.endPoint.y, overlapAnalyze.startPoint.y, overlapAnalyze.endPoint.y),
|
||||
}
|
||||
analyze.startPoint = startPoint
|
||||
analyze.endPoint = endPoint
|
||||
forwardLines = forwardLines.filter((forwardLine) => forwardLine !== overlap)
|
||||
})
|
||||
}
|
||||
forwardLines.push({ eaves: line, analyze })
|
||||
}
|
||||
if (analyze.directionVector.y < 0) {
|
||||
const overlapLines = backwardLines.filter((backwardLine) => backwardLine !== line && isOverlapLine(analyze, backwardLine.analyze))
|
||||
if (overlapLines.length > 0) {
|
||||
overlapLines.forEach((overlap) => {
|
||||
const overlapAnalyze = overlap.analyze
|
||||
const startPoint = {
|
||||
x: analyze.startPoint.x,
|
||||
y: Math.min(analyze.startPoint.y, analyze.endPoint.y, overlapAnalyze.startPoint.y, overlapAnalyze.endPoint.y),
|
||||
}
|
||||
const endPoint = {
|
||||
x: analyze.endPoint.x,
|
||||
y: Math.max(analyze.startPoint.y, analyze.endPoint.y, overlapAnalyze.startPoint.y, overlapAnalyze.endPoint.y),
|
||||
}
|
||||
analyze.startPoint = startPoint
|
||||
analyze.endPoint = endPoint
|
||||
backwardLines = backwardLines.filter((backwardLine) => backwardLine !== overlap)
|
||||
})
|
||||
}
|
||||
backwardLines.push({ eaves: line, analyze })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
forwardLines.sort((a, b) => {
|
||||
if (a.analyze.isHorizontal && b.analyze.isHorizontal) {
|
||||
return a.analyze.startPoint.x - b.analyze.startPoint.x
|
||||
} else if (a.analyze.isVertical && b.analyze.isVertical) {
|
||||
return a.analyze.startPoint.y - b.analyze.startPoint.y
|
||||
}
|
||||
})
|
||||
backwardLines.sort((a, b) => {
|
||||
if (a.analyze.isHorizontal && b.analyze.isHorizontal) {
|
||||
return a.analyze.startPoint.x - b.analyze.startPoint.x
|
||||
} else if (a.analyze.isVertical && b.analyze.isVertical) {
|
||||
return a.analyze.startPoint.y - b.analyze.startPoint.y
|
||||
}
|
||||
})
|
||||
|
||||
return { forwardLines, backwardLines }
|
||||
}
|
||||
|
||||
/**
|
||||
* 라인의 지붕 면을 찾는다.
|
||||
* @param currentLine
|
||||
* @returns {*}
|
||||
*/
|
||||
const findCurrentRoof = (currentLine) => {
|
||||
const analyze = analyzeEavesLine(currentLine)
|
||||
const originPoint = currentLine.attributes.originPoint
|
||||
const midX = (originPoint.x1 + originPoint.x2) / 2
|
||||
const midY = (originPoint.y1 + originPoint.y2) / 2
|
||||
const offset = currentLine.attributes.offset
|
||||
|
||||
let currentRoof
|
||||
let roofFindVector = { x: 0, y: 0 }
|
||||
const checkRoofLines = roof.lines.filter((roof) => {
|
||||
const dx = Big(roof.x2).minus(Big(roof.x1)).toNumber()
|
||||
const dy = Big(roof.y2).minus(Big(roof.y1)).toNumber()
|
||||
const length = Math.sqrt(dx * dx + dy * dy)
|
||||
const directionVector = { x: dx / length, y: dy / length }
|
||||
return analyze.directionVector.x === directionVector.x && analyze.directionVector.y === directionVector.y
|
||||
})
|
||||
|
||||
if (analyze.isHorizontal) {
|
||||
const checkPoint = { x: midX, y: midY + offset }
|
||||
if (wall.inPolygon(checkPoint)) {
|
||||
roofFindVector = { x: 0, y: -1 }
|
||||
} else {
|
||||
roofFindVector = { x: 0, y: 1 }
|
||||
}
|
||||
}
|
||||
if (analyze.isVertical) {
|
||||
const checkPoint = { x: midX + offset, y: midY }
|
||||
if (wall.inPolygon(checkPoint)) {
|
||||
roofFindVector = { x: -1, y: 0 }
|
||||
} else {
|
||||
roofFindVector = { x: 1, y: 0 }
|
||||
}
|
||||
}
|
||||
const findEdge = { vertex1: { x: midX, y: midY }, vertex2: { x: midX + roofFindVector.x * offset, y: midY + roofFindVector.y * offset } }
|
||||
const edgeDx = Big(findEdge.vertex2.x).minus(Big(findEdge.vertex1.x)).toNumber()
|
||||
const edgeDy = Big(findEdge.vertex2.y).minus(Big(findEdge.vertex1.y)).toNumber()
|
||||
const edgeLength = Math.sqrt(edgeDx * edgeDx + edgeDy * edgeDy)
|
||||
const edgeVector = { x: edgeDx / edgeLength, y: edgeDy / edgeLength }
|
||||
|
||||
const intersectRoofLines = []
|
||||
checkRoofLines.forEach((roofLine) => {
|
||||
const lineEdge = { vertex1: { x: roofLine.x1, y: roofLine.y1 }, vertex2: { x: roofLine.x2, y: roofLine.y2 } }
|
||||
const intersect = edgesIntersection(lineEdge, findEdge)
|
||||
if (intersect) {
|
||||
const intersectDx = Big(intersect.x).minus(Big(findEdge.vertex1.x)).toNumber()
|
||||
const intersectDy = Big(intersect.y).minus(Big(findEdge.vertex1.y)).toNumber()
|
||||
const intersectLength = Math.sqrt(intersectDx * intersectDx + intersectDy * intersectDy)
|
||||
const intersectVector = { x: intersectDx / intersectLength, y: intersectDy / intersectLength }
|
||||
if (edgeVector.x === intersectVector.x && edgeVector.y === intersectVector.y) {
|
||||
intersectRoofLines.push({ roofLine, intersect, length: intersectLength })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
currentRoof = intersectRoofLines.find((roof) => isPointOnLineNew(roof.roofLine, roof.intersect))
|
||||
if (!currentRoof) {
|
||||
currentRoof = intersectRoofLines.sort((a, b) => a.length - b.length)[0]
|
||||
}
|
||||
|
||||
return currentRoof
|
||||
}
|
||||
|
||||
/**
|
||||
* 지점 사이의 길이와 지점별 각도에 따라서 교점까지의 길이를 구한다.
|
||||
* @param distance
|
||||
* @param angleA
|
||||
* @param angleB
|
||||
* @returns {{a: number, b: number}}
|
||||
*/
|
||||
const calculateIntersection = (distance, angleA, angleB) => {
|
||||
// A에서 B방향으로의 각도 (0도가 B방향)
|
||||
const tanA = Math.tan((angleA * Math.PI) / 180)
|
||||
// B에서 A방향으로의 각도 (180도가 A방향, 실제 계산에서는 180-angleB)
|
||||
const tanB = Math.tan(((180 - angleB) * Math.PI) / 180)
|
||||
|
||||
const a = Math.round(((distance * tanB) / (tanB - tanA)) * 10) / 10
|
||||
const b = Math.round(Math.abs(distance - a) * 10) / 10
|
||||
return { a, b }
|
||||
}
|
||||
|
||||
const { forwardLines, backwardLines } = analyzeAllEavesLines(eavesLines)
|
||||
forwardLines.forEach((current) => {
|
||||
const currentLine = current.eaves
|
||||
const analyze = current.analyze
|
||||
const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
|
||||
const currentX1 = Math.min(currentLine.x1, currentLine.x2)
|
||||
const currentX2 = Math.max(currentLine.x1, currentLine.x2)
|
||||
const currentY1 = Math.min(currentLine.y1, currentLine.y2)
|
||||
const currentY2 = Math.max(currentLine.y1, currentLine.y2)
|
||||
|
||||
const x1 = analyze.startPoint.x
|
||||
const x2 = analyze.endPoint.x
|
||||
const y1 = analyze.startPoint.y
|
||||
const y2 = analyze.endPoint.y
|
||||
|
||||
const checkLine = new fabric.Line([analyze.startPoint.x, analyze.startPoint.y, analyze.endPoint.x, analyze.endPoint.y], {
|
||||
stroke: 'red',
|
||||
strokeWidth: 4,
|
||||
parentId: roofId,
|
||||
name: 'check',
|
||||
})
|
||||
canvas.add(checkLine)
|
||||
canvas.renderAll()
|
||||
|
||||
const overlapLines = []
|
||||
backwardLines.forEach((backward) => {
|
||||
const backX1 = Math.min(backward.eaves.x1, backward.eaves.x2)
|
||||
const backX2 = Math.max(backward.eaves.x1, backward.eaves.x2)
|
||||
const backY1 = Math.min(backward.eaves.y1, backward.eaves.y2)
|
||||
const backY2 = Math.max(backward.eaves.y1, backward.eaves.y2)
|
||||
|
||||
if (
|
||||
analyze.isHorizontal &&
|
||||
((currentX1 <= backX1 && currentX2 >= backX1) ||
|
||||
(currentX1 <= backX2 && currentX2 >= backX2) ||
|
||||
(backX1 < currentX1 && backX1 < currentX2 && backX2 > currentX1 && backX2 > currentX2))
|
||||
) {
|
||||
overlapLines.push(backward)
|
||||
}
|
||||
if (
|
||||
analyze.isVertical &&
|
||||
((currentY1 <= backY1 && currentY2 >= backY1) ||
|
||||
(currentY1 <= backY2 && currentY2 >= backY2) ||
|
||||
(backY1 < currentY1 && backY1 < currentY2 && backY2 > currentY1 && backY2 > currentY2))
|
||||
) {
|
||||
overlapLines.push(backward)
|
||||
}
|
||||
})
|
||||
|
||||
overlapLines.forEach((overlap) => {
|
||||
const overlapAnalyze = overlap.analyze
|
||||
const overlapDegree = getDegreeByChon(overlap.eaves.attributes.pitch)
|
||||
const ridgePoint = []
|
||||
if (analyze.isHorizontal) {
|
||||
const overlapX1 = Math.min(overlapAnalyze.startPoint.x, overlapAnalyze.endPoint.x)
|
||||
const overlapX2 = Math.max(overlapAnalyze.startPoint.x, overlapAnalyze.endPoint.x)
|
||||
|
||||
// 각 라인 사이의 길이를 구해서 각도에 대한 중간 지점으로 마루를 생성.
|
||||
const currentMidY = (currentLine.y1 + currentLine.y2) / 2
|
||||
const overlapMidY = (overlap.eaves.y1 + overlap.eaves.y2) / 2
|
||||
const distance = calculateIntersection(Math.abs(currentMidY - overlapMidY), currentDegree, overlapDegree)
|
||||
const vectorToOverlap = Math.sign(overlap.eaves.y1 - currentLine.y1)
|
||||
const pointY = currentLine.y1 + vectorToOverlap * distance.a
|
||||
|
||||
if (x1 <= overlapX1 && overlapX1 <= x2) {
|
||||
ridgePoint.push({ x: overlapX1, y: pointY })
|
||||
} else {
|
||||
ridgePoint.push({ x: x1, y: pointY })
|
||||
}
|
||||
if (x1 <= overlapX2 && overlapX2 <= x2) {
|
||||
ridgePoint.push({ x: overlapX2, y: pointY })
|
||||
} else {
|
||||
ridgePoint.push({ x: x2, y: pointY })
|
||||
}
|
||||
}
|
||||
if (analyze.isVertical) {
|
||||
const overlapY1 = Math.min(overlapAnalyze.startPoint.y, overlapAnalyze.endPoint.y)
|
||||
const overlapY2 = (overlapAnalyze.startPoint.y, overlapAnalyze.endPoint.y)
|
||||
|
||||
// 각 라인 사이의 길이를 구해서 각도에 대한 중간 지점으로 마루를 생성.
|
||||
const currentMidX = (currentLine.x1 + currentLine.x2) / 2
|
||||
const overlapMidX = (overlap.eaves.x1 + overlap.eaves.x2) / 2
|
||||
const distance = calculateIntersection(Math.abs(currentMidX - overlapMidX), currentDegree, overlapDegree)
|
||||
const vectorToOverlap = Math.sign(overlap.eaves.x1 - currentLine.x1)
|
||||
const pointX = currentLine.x1 + vectorToOverlap * distance.a
|
||||
|
||||
if (y1 <= overlapY1 && overlapY1 <= y2) {
|
||||
ridgePoint.push({ x: pointX, y: overlapY1 })
|
||||
} else {
|
||||
ridgePoint.push({ x: pointX, y: y1 })
|
||||
}
|
||||
if (y1 <= overlapY2 && overlapY2 <= y2) {
|
||||
ridgePoint.push({ x: pointX, y: overlapY2 })
|
||||
} else {
|
||||
ridgePoint.push({ x: pointX, y: y2 })
|
||||
}
|
||||
}
|
||||
ridgeLines.push(drawRidgeLine([ridgePoint[0].x, ridgePoint[0].y, ridgePoint[1].x, ridgePoint[1].y], canvas, roof, textMode))
|
||||
})
|
||||
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((object) => object.name === 'check')
|
||||
.forEach((object) => canvas.remove(object))
|
||||
canvas.renderAll()
|
||||
})
|
||||
|
||||
/**
|
||||
* 지붕면을 그린다.
|
||||
* @param currentLine
|
||||
*/
|
||||
const drawRoofPlane = (currentLine) => {
|
||||
const analyze = currentLine.analyze
|
||||
const checkLine = new fabric.Line([analyze.startPoint.x, analyze.startPoint.y, analyze.endPoint.x, analyze.endPoint.y], {
|
||||
stroke: 'red',
|
||||
strokeWidth: 4,
|
||||
parentId: roofId,
|
||||
name: 'check',
|
||||
})
|
||||
canvas.add(checkLine)
|
||||
canvas.renderAll()
|
||||
|
||||
const innerRidgeLines = []
|
||||
if (analyze.isHorizontal) {
|
||||
ridgeLines
|
||||
.filter((ridgeLine) => {
|
||||
const tolerance = 1
|
||||
const dx = Big(ridgeLine.x2).minus(Big(ridgeLine.x1)).toNumber()
|
||||
const dy = Big(ridgeLine.y2).minus(Big(ridgeLine.y1)).toNumber()
|
||||
const normalizedAngle = Math.abs((Math.atan2(dy, dx) * 180) / Math.PI) % 180
|
||||
return normalizedAngle < tolerance || normalizedAngle >= 180 - tolerance
|
||||
})
|
||||
.filter((ridgeLine) => {
|
||||
const minX = Math.min(analyze.startPoint.x, analyze.endPoint.x)
|
||||
const maxX = Math.max(analyze.startPoint.x, analyze.endPoint.x)
|
||||
const ridgeLineX = (ridgeLine.x1 + ridgeLine.x2) / 2
|
||||
return ridgeLineX >= minX && ridgeLineX <= maxX
|
||||
})
|
||||
.forEach((ridgeLine) => innerRidgeLines.push(ridgeLine))
|
||||
}
|
||||
if (analyze.isVertical) {
|
||||
ridgeLines
|
||||
.filter((ridgeLine) => {
|
||||
const tolerance = 1
|
||||
const dx = Big(ridgeLine.x2).minus(Big(ridgeLine.x1)).toNumber()
|
||||
const dy = Big(ridgeLine.y2).minus(Big(ridgeLine.y1)).toNumber()
|
||||
const normalizedAngle = Math.abs((Math.atan2(dy, dx) * 180) / Math.PI) % 180
|
||||
return Math.abs(normalizedAngle - 90) <= tolerance
|
||||
})
|
||||
.filter((ridgeLine) => {
|
||||
const minY = Math.min(analyze.startPoint.y, analyze.endPoint.y)
|
||||
const maxY = Math.max(analyze.startPoint.y, analyze.endPoint.y)
|
||||
const ridgeLineY = (ridgeLine.y1 + ridgeLine.y2) / 2
|
||||
return ridgeLineY >= minY && ridgeLineY <= maxY
|
||||
})
|
||||
.forEach((ridgeLine) => innerRidgeLines.push(ridgeLine))
|
||||
}
|
||||
|
||||
innerRidgeLines.forEach((ridgeLine) => {
|
||||
const checkLine = new fabric.Line([ridgeLine.x1, ridgeLine.y1, ridgeLine.x2, ridgeLine.y2], {
|
||||
stroke: 'red',
|
||||
strokeWidth: 4,
|
||||
parentId: roofId,
|
||||
name: 'check',
|
||||
})
|
||||
canvas.add(checkLine)
|
||||
canvas.renderAll()
|
||||
})
|
||||
|
||||
if (innerRidgeLines.length === 1) {
|
||||
const innerRidgeLine = innerRidgeLines[0]
|
||||
if (analyze.isHorizontal) {
|
||||
}
|
||||
if (analyze.isVertical) {
|
||||
}
|
||||
}
|
||||
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((object) => object.name === 'check')
|
||||
.forEach((object) => canvas.remove(object))
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
forwardLines.forEach((forward) => {
|
||||
const analyze = forward.analyze
|
||||
drawRoofPlane(forward)
|
||||
})
|
||||
backwardLines.forEach((backward) => {
|
||||
const analyze = backward.analyze
|
||||
drawRoofPlane(backward)
|
||||
})
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((object) => object.name === 'check')
|
||||
.forEach((object) => canvas.remove(object))
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user