하단지붕선 작성 로직 추가.
This commit is contained in:
parent
fd024cf30b
commit
494b06bfe3
@ -4676,8 +4676,8 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const checkNewLine = new fabric.Line(linePoint, { stroke: 'cyan', strokeWidth: 4, parentId: roofId, name: 'check' })
|
// const checkNewLine = new fabric.Line(linePoint, { stroke: 'cyan', strokeWidth: 4, parentId: roofId, name: 'check' })
|
||||||
canvas.add(checkNewLine).renderAll()
|
// canvas.add(checkNewLine).renderAll()
|
||||||
|
|
||||||
newAnalysis.push({
|
newAnalysis.push({
|
||||||
start: { x: linePoint[0], y: linePoint[1] },
|
start: { x: linePoint[0], y: linePoint[1] },
|
||||||
@ -4839,8 +4839,8 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//하단 지붕 라인처리
|
//케라바에서 파생된 하단 지붕 라인처리
|
||||||
const downRoofLines = []
|
const downRoofGable = []
|
||||||
baseLines.forEach((baseLine, index) => {
|
baseLines.forEach((baseLine, index) => {
|
||||||
const nextLine = baseLines[(index + 1) % baseLines.length]
|
const nextLine = baseLines[(index + 1) % baseLines.length]
|
||||||
const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
|
const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
|
||||||
@ -4852,12 +4852,205 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
if (
|
if (
|
||||||
prevLineVector.x === nextLineVector.x &&
|
prevLineVector.x === nextLineVector.x &&
|
||||||
prevLineVector.y === nextLineVector.y &&
|
prevLineVector.y === nextLineVector.y &&
|
||||||
|
baseLine.attributes.type === LINE_TYPE.WALLLINE.EAVES &&
|
||||||
(prevLine.attributes.type === LINE_TYPE.WALLLINE.GABLE || nextLine.attributes.type === LINE_TYPE.WALLLINE.GABLE)
|
(prevLine.attributes.type === LINE_TYPE.WALLLINE.GABLE || nextLine.attributes.type === LINE_TYPE.WALLLINE.GABLE)
|
||||||
) {
|
) {
|
||||||
downRoofLines.push(index)
|
downRoofGable.push({ currLine: baseLine, currIndex: index })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const downRoofLines = [] // 하단지붕 파생 라인 처리후 innerLines에 추가.
|
||||||
|
downRoofGable.forEach(({ currLine, currIndex }) => {
|
||||||
|
// 라인의 방향
|
||||||
|
const currVector = { x: Math.sign(clamp01(currLine.x1 - currLine.x2)), y: Math.sign(clamp01(currLine.y1 - currLine.y2)) }
|
||||||
|
|
||||||
|
//어느쪽이 기준인지 확인.
|
||||||
|
//대각선 제외
|
||||||
|
if (currVector.x !== 0 && currVector.y !== 0) return
|
||||||
|
|
||||||
|
const prevLine = baseLines[(currIndex - 1 + baseLines.length) % baseLines.length]
|
||||||
|
const nextLine = baseLines[(currIndex + 1) % baseLines.length]
|
||||||
|
|
||||||
|
const prevVector = { x: Math.sign(clamp01(prevLine.x1 - prevLine.x2)), y: Math.sign(clamp01(prevLine.y1 - prevLine.y2)) }
|
||||||
|
const nextVector = { x: Math.sign(clamp01(nextLine.x1 - nextLine.x2)), y: Math.sign(clamp01(nextLine.y1 - nextLine.y2)) }
|
||||||
|
|
||||||
|
let gableLine
|
||||||
|
//가로선
|
||||||
|
if (currVector.y === 0) {
|
||||||
|
if (currVector.x === 1) {
|
||||||
|
if (prevVector.y === 1 && nextVector.y === 1) {
|
||||||
|
gableLine = nextLine
|
||||||
|
}
|
||||||
|
if (prevVector.y === -1 && nextVector.y === -1) {
|
||||||
|
gableLine = prevLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currVector.x === -1) {
|
||||||
|
if (prevVector.y === 1 && nextVector.y === 1) {
|
||||||
|
gableLine = prevLine
|
||||||
|
}
|
||||||
|
if (prevVector.y === -1 && nextVector.y === -1) {
|
||||||
|
gableLine = nextLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//세로선
|
||||||
|
if (currVector.x === 0) {
|
||||||
|
if (currVector.y === 1) {
|
||||||
|
if (prevVector.x === 1 && nextVector.x === 1) {
|
||||||
|
gableLine = prevLine
|
||||||
|
}
|
||||||
|
if (prevVector.x === -1 && nextVector.x === -1) {
|
||||||
|
gableLine = nextLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currVector.y === -1) {
|
||||||
|
if (prevVector.x === 1 && nextVector.x === 1) {
|
||||||
|
gableLine = nextLine
|
||||||
|
}
|
||||||
|
if (prevVector.x === -1 && nextVector.x === -1) {
|
||||||
|
gableLine = prevLine
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//기준점
|
||||||
|
let stdPoint = []
|
||||||
|
//반대쪽 라인을 찾기위한 vector
|
||||||
|
let oppFindVector
|
||||||
|
if (gableLine === prevLine) {
|
||||||
|
stdPoint.push(currLine.x1, currLine.y1)
|
||||||
|
stdPoint.push(currLine.x2 + -currVector.x * nextLine.attributes.offset, currLine.y2 + -currVector.y * nextLine.attributes.offset)
|
||||||
|
oppFindVector = { x: Math.sign(clamp01(nextLine.x2 - nextLine.x1)), y: Math.sign(clamp01(nextLine.y2 - nextLine.y1)) }
|
||||||
|
} else {
|
||||||
|
stdPoint.push(currLine.x2, currLine.y2)
|
||||||
|
stdPoint.push(currLine.x1 + currVector.x * prevLine.attributes.offset, currLine.y1 + currVector.y * prevLine.attributes.offset)
|
||||||
|
oppFindVector = { x: Math.sign(clamp01(prevLine.x1 - prevLine.x2)), y: Math.sign(clamp01(prevLine.y1 - prevLine.y2)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
//반대쪽 라인들 (마루선을 위함)
|
||||||
|
const oppLines = baseLines.filter((line) => {
|
||||||
|
const lineVector = { x: Math.sign(clamp01(line.x1 - line.x2)), y: Math.sign(clamp01(line.y1 - line.y2)) }
|
||||||
|
const oppVector =
|
||||||
|
lineVector.x === 0 ? { x: Math.sign(clamp01(line.x1 - stdPoint[0])), y: 0 } : { x: 0, y: Math.sign(clamp01(line.y1 - stdPoint[1])) }
|
||||||
|
|
||||||
|
const rightDirection =
|
||||||
|
(currVector.x === lineVector.x && currVector.y !== lineVector.y) || (currVector.x !== lineVector.x && currVector.y === lineVector.y)
|
||||||
|
const rightOpp = oppFindVector.x === oppVector.x && oppFindVector.y === oppVector.y
|
||||||
|
return rightDirection && rightOpp
|
||||||
|
})
|
||||||
|
|
||||||
|
const innerRidge = innerLines
|
||||||
|
.filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE)
|
||||||
|
.filter((line) => {
|
||||||
|
const lineVector = { x: Math.sign(clamp01(line.x1 - line.x2)), y: Math.sign(clamp01(line.y1 - line.y2)) }
|
||||||
|
//마루선을 찾는다.
|
||||||
|
if ((currVector.x === 0 && lineVector.x === 0) || (currVector.y === 0 && lineVector.y === 0)) {
|
||||||
|
//세로선
|
||||||
|
if (lineVector.x === 0) {
|
||||||
|
const minY = Math.min(line.y1, line.y2)
|
||||||
|
const maxY = Math.max(line.y1, line.y2)
|
||||||
|
// 기준 라인 안에 들어있는 경우에만 처리.
|
||||||
|
if (
|
||||||
|
Math.min(stdPoint[1], stdPoint[3]) <= minY &&
|
||||||
|
maxY <= Math.max(stdPoint[1], stdPoint[3]) &&
|
||||||
|
Math.min(stdPoint[0], ...oppLines.map((line) => line.x1)) <= line.x1 &&
|
||||||
|
line.x1 <= Math.max(stdPoint[0], ...oppLines.map((line) => line.x1))
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//가로선
|
||||||
|
if (lineVector.y === 0) {
|
||||||
|
const minX = Math.min(line.x1, line.x2)
|
||||||
|
const maxX = Math.max(line.x1, line.x2)
|
||||||
|
// 기준 라인 안에 들어있는 경우에만 처리
|
||||||
|
if (
|
||||||
|
Math.min(stdPoint[0], stdPoint[2]) <= minX &&
|
||||||
|
maxX <= Math.max(stdPoint[0], stdPoint[2]) &&
|
||||||
|
Math.min(stdPoint[1], ...oppLines.map((line) => line.y1)) <= line.y1 &&
|
||||||
|
line.y1 <= Math.max(stdPoint[1], ...oppLines.map((line) => line.y1))
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//1. 현재 라인을 기준으로 지붕선 추가.
|
||||||
|
//1-1 stdPoint을 현재라인의 지붕 출폭 만큼 조정
|
||||||
|
const currOffset = currLine.attributes.offset
|
||||||
|
const noGableLine = gableLine === prevLine ? nextLine : prevLine
|
||||||
|
|
||||||
|
let roofLinePoint = stdPoint
|
||||||
|
if (currVector.x === 0) {
|
||||||
|
//세로일때
|
||||||
|
//x축 조정
|
||||||
|
roofLinePoint[0] = roofLinePoint[0] + currVector.y * currOffset
|
||||||
|
roofLinePoint[2] = roofLinePoint[2] + currVector.y * currOffset
|
||||||
|
} else if (currVector.y === 0) {
|
||||||
|
//가로일때
|
||||||
|
//y축 조정
|
||||||
|
roofLinePoint[1] = roofLinePoint[1] - currVector.x * currOffset
|
||||||
|
roofLinePoint[3] = roofLinePoint[3] - currVector.x * currOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
//지붕선추가.
|
||||||
|
downRoofLines.push(drawRoofLine(roofLinePoint, canvas, roof, textMode))
|
||||||
|
|
||||||
|
//1-2 지붕선에서 oppLine으로 향하는 중 가장 가까운 마루선까지의 연결선 생성
|
||||||
|
const findRidgeEdge = {
|
||||||
|
vertex1: { x: roofLinePoint[0], y: roofLinePoint[1] },
|
||||||
|
vertex2: { x: roofLinePoint[0] + oppFindVector.x, y: roofLinePoint[1] + oppFindVector.y },
|
||||||
|
}
|
||||||
|
let minDistance = Infinity
|
||||||
|
let minPoint
|
||||||
|
let isLine
|
||||||
|
innerRidge.forEach((line) => {
|
||||||
|
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
||||||
|
const intersect = edgesIntersection(lineEdge, findRidgeEdge)
|
||||||
|
if (intersect) {
|
||||||
|
let distance = Infinity
|
||||||
|
if (currVector.x === 0) {
|
||||||
|
const lineDistance1 = Math.abs(line.y1 - roofLinePoint[1])
|
||||||
|
const lineDistance2 = Math.abs(line.y2 - roofLinePoint[1])
|
||||||
|
distance = Math.min(lineDistance1, lineDistance2)
|
||||||
|
} else if (currVector.y === 0) {
|
||||||
|
const lineDistance1 = Math.abs(line.x1 - roofLinePoint[0])
|
||||||
|
const lineDistance2 = Math.abs(line.x2 - roofLinePoint[0])
|
||||||
|
distance = Math.min(lineDistance1, lineDistance2)
|
||||||
|
}
|
||||||
|
if (distance < minDistance) {
|
||||||
|
minDistance = distance
|
||||||
|
minPoint = intersect
|
||||||
|
isLine = line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (minPoint) {
|
||||||
|
const hipPoint = [roofLinePoint[0], roofLinePoint[1], minPoint.x, minPoint.y]
|
||||||
|
downRoofLines.push(
|
||||||
|
drawHipLine(hipPoint, canvas, roof, textMode, null, getDegreeByChon(currLine.attributes.pitch), getDegreeByChon(currLine.attributes.pitch)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isLine) {
|
||||||
|
const newRidgePoint = [minPoint.x, minPoint.y]
|
||||||
|
const distance1 = Math.sqrt(Math.pow(minPoint.x - isLine.x1, 2) + Math.pow(minPoint.y - isLine.y1, 2))
|
||||||
|
const distance2 = Math.sqrt(Math.pow(minPoint.x - isLine.x2, 2) + Math.pow(minPoint.y - isLine.y2, 2))
|
||||||
|
if (distance2 < distance1) {
|
||||||
|
newRidgePoint.push(isLine.x1, isLine.y1)
|
||||||
|
} else {
|
||||||
|
newRidgePoint.push(isLine.x2, isLine.y2)
|
||||||
|
}
|
||||||
|
downRoofLines.push(drawRoofLine(newRidgePoint, canvas, roof, textMode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//추가된 하단 지붕 라인 innerLines에 추가.
|
||||||
|
innerLines.push(...downRoofLines)
|
||||||
|
|
||||||
//지붕선에 따라 라인추가 작업 처리.
|
//지붕선에 따라 라인추가 작업 처리.
|
||||||
const innerLinesPoints = []
|
const innerLinesPoints = []
|
||||||
innerLines.forEach((line) => {
|
innerLines.forEach((line) => {
|
||||||
@ -4869,9 +5062,8 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
roof.lines.forEach((currentLine, index) => {
|
roof.lines.forEach((currentLine, index) => {
|
||||||
const prevLine = roof.lines[(index - 1 + roof.lines.length) % roof.lines.length]
|
const prevLine = roof.lines[(index - 1 + roof.lines.length) % roof.lines.length]
|
||||||
const nextLine = roof.lines[(index + 1) % roof.lines.length]
|
const nextLine = roof.lines[(index + 1) % roof.lines.length]
|
||||||
const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
|
const prevDegree = prevLine.attributes.pitch ? getDegreeByChon(prevLine.attributes.pitch) : 0
|
||||||
const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
|
const nextDegree = nextLine.attributes.pitch ? getDegreeByChon(nextLine.attributes.pitch) : 0
|
||||||
console.log('prevDegree, nextDegree: ', prevDegree, nextDegree)
|
|
||||||
|
|
||||||
const splitPoint = []
|
const splitPoint = []
|
||||||
let hasOverlapLine = false
|
let hasOverlapLine = false
|
||||||
@ -4929,730 +5121,6 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
.filter((object) => object.name === 'check')
|
.filter((object) => object.name === 'check')
|
||||||
.forEach((object) => canvas.remove(object))
|
.forEach((object) => canvas.remove(object))
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
//return
|
|
||||||
/*while (linesAnalysis.length > 0 && iterations < MAX_ITERATIONS) {
|
|
||||||
iterations++
|
|
||||||
|
|
||||||
linesAnalysis.forEach((line) => {
|
|
||||||
const point = [line.start.x, line.start.y, line.end.x, line.end.y]
|
|
||||||
const checkLine = new fabric.Line(point, {
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 2,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
canvas.add(checkLine)
|
|
||||||
canvas.renderAll()
|
|
||||||
})
|
|
||||||
// 각 가선분의 최단 교점 찾기
|
|
||||||
const intersections = []
|
|
||||||
for (let i = 0; i < linesAnalysis.length; i++) {
|
|
||||||
let minDistance = Infinity //최단거리
|
|
||||||
let intersectPoint = null //교점 좌표
|
|
||||||
let partners = new Set() //교점 선분의 index
|
|
||||||
|
|
||||||
const lineI = linesAnalysis[i]
|
|
||||||
const lengthI = Math.sqrt(Math.pow(lineI.end.x - lineI.start.x, 2) + Math.pow(lineI.end.y - lineI.start.y, 2))
|
|
||||||
console.log('lengthI', lengthI)
|
|
||||||
const checkLineI = new fabric.Line([lineI.start.x, lineI.start.y, lineI.end.x, lineI.end.y], {
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 2,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
canvas.add(checkLineI).renderAll()
|
|
||||||
|
|
||||||
if (lineI.type === TYPES.GABLE_LINE && lineI.connectCnt > 1) continue
|
|
||||||
|
|
||||||
if (lengthI > EPSILON) {
|
|
||||||
const otherLines = linesAnalysis.filter((j) => j !== lineI)
|
|
||||||
const zeroLines = linesAnalysis.filter((j) => Math.sqrt(Math.pow(j.end.x - j.start.x, 2) + Math.pow(j.end.y - j.start.y, 2)) < EPSILON)
|
|
||||||
if (otherLines.length === zeroLines.length) {
|
|
||||||
zeroLines.forEach((j) => {
|
|
||||||
const jIndex = linesAnalysis.indexOf(j)
|
|
||||||
if (isPointOnLineNew({ x1: lineI.start.x, y1: lineI.start.y, x2: lineI.end.x, y2: lineI.end.y }, { x: j.start.x, y: j.start.y })) {
|
|
||||||
const distance = Math.sqrt(Math.pow(j.start.x - lineI.start.x, 2) + Math.pow(j.start.y - lineI.start.y, 2))
|
|
||||||
if (distance < minDistance) {
|
|
||||||
minDistance = distance
|
|
||||||
intersectPoint = { x: j.start.x, y: j.start.y }
|
|
||||||
partners = new Set([jIndex])
|
|
||||||
} else if (almostEqual(distance, minDistance)) {
|
|
||||||
partners.add(jIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (intersectPoint) {
|
|
||||||
intersections.push({ index: i, intersectPoint, partners, distance: minDistance })
|
|
||||||
partners.forEach((j) => {
|
|
||||||
const p = new Set([i])
|
|
||||||
intersections.push({ index: j, intersectPoint, partners: p, distance: 0 })
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < linesAnalysis.length; j++) {
|
|
||||||
const lineJ = linesAnalysis[j]
|
|
||||||
if (lineI === lineJ) continue
|
|
||||||
if (lineI.type === TYPES.GABLE_LINE && lineJ.type === TYPES.GABLE_LINE && i.gableId === lineJ.gableId) continue
|
|
||||||
if (lineJ.type === TYPES.GABLE_LINE && lineJ.connectCnt > 1) continue
|
|
||||||
|
|
||||||
const intersection = lineIntersection(lineI.start, lineI.end, lineJ.start, lineJ.end, canvas)
|
|
||||||
if (intersection) {
|
|
||||||
const distance = Math.sqrt((intersection.x - lineI.start.x) ** 2 + (intersection.y - lineI.start.y) ** 2)
|
|
||||||
const distance2 = Math.sqrt((intersection.x - lineJ.start.x) ** 2 + (intersection.y - lineJ.start.y) ** 2)
|
|
||||||
if (lineI.type === TYPES.GABLE_LINE && distance < EPSILON) continue
|
|
||||||
if (distance < minDistance && !almostEqual(distance, minDistance) && !(distance < EPSILON && distance2 < EPSILON)) {
|
|
||||||
minDistance = distance
|
|
||||||
intersectPoint = intersection
|
|
||||||
partners = new Set([j])
|
|
||||||
} else if (almostEqual(distance, minDistance)) {
|
|
||||||
partners.add(j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (intersectPoint) {
|
|
||||||
intersections.push({ index: i, intersectPoint, partners, distance: minDistance })
|
|
||||||
}
|
|
||||||
canvas.remove(checkLineI).renderAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 제일 가까운 교점부터 처리
|
|
||||||
intersections.sort((a, b) => a.distance - b.distance)
|
|
||||||
|
|
||||||
console.log('intersections', intersections)
|
|
||||||
// 교점에 대한 적합 여부 판단 및 처리.
|
|
||||||
let newAnalysis = [] //신규 발생 선
|
|
||||||
const processed = new Set() //처리된 선
|
|
||||||
for (const { index, intersectPoint, partners } of intersections) {
|
|
||||||
canvas
|
|
||||||
.getObjects()
|
|
||||||
.filter((object) => object.name === 'check')
|
|
||||||
.forEach((object) => canvas.remove(object))
|
|
||||||
canvas.renderAll()
|
|
||||||
let isProceed = false
|
|
||||||
for (const pIndex of partners) {
|
|
||||||
console.log('pIndex : ', pIndex)
|
|
||||||
const check1 = linesAnalysis[index]
|
|
||||||
const checkLine1 = new fabric.Line([check1.start.x, check1.start.y, check1.end.x, check1.end.y], {
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 2,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
const checkCircle1 = new fabric.Circle({ left: check1.start.x, top: check1.start.y, radius: 5, fill: 'red', parentId: roofId, name: 'check' })
|
|
||||||
const checkCircle2 = new fabric.Circle({ left: check1.end.x, top: check1.end.y, radius: 5, fill: 'green', parentId: roofId, name: 'check' })
|
|
||||||
canvas.add(checkLine1, checkCircle1, checkCircle2)
|
|
||||||
canvas.renderAll()
|
|
||||||
|
|
||||||
const check2 = linesAnalysis[pIndex]
|
|
||||||
const checkLine2 = new fabric.Line([check2.start.x, check2.start.y, check2.end.x, check2.end.y], {
|
|
||||||
stroke: 'green',
|
|
||||||
strokeWidth: 2,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
|
|
||||||
const checkCircle3 = new fabric.Circle({ left: check2.start.x, top: check2.start.y, radius: 5, fill: 'red', parentId: roofId, name: 'check' })
|
|
||||||
const checkCircle4 = new fabric.Circle({ left: check2.end.x, top: check2.end.y, radius: 5, fill: 'green', parentId: roofId, name: 'check' })
|
|
||||||
canvas.add(checkLine2, checkCircle3, checkCircle4)
|
|
||||||
canvas.renderAll()
|
|
||||||
|
|
||||||
console.log('!intersectPoint || processed.has(index)', !intersectPoint, processed.has(index))
|
|
||||||
//교점이 없거나, 이미 처리된 선분이면 처리하지 않는다.
|
|
||||||
if (!intersectPoint || processed.has(index)) continue
|
|
||||||
|
|
||||||
const partner = intersections.find((p) => p.index === pIndex)
|
|
||||||
//교점이 없거나, 교점 선분이 없으면 처리하지 않는다.
|
|
||||||
if (!partner || !partner.intersectPoint) continue
|
|
||||||
|
|
||||||
//상호 최단 교점 여부 확인.
|
|
||||||
if (partner.partners.has(index)) {
|
|
||||||
const line1 = linesAnalysis[index]
|
|
||||||
const line2 = linesAnalysis[pIndex]
|
|
||||||
|
|
||||||
//좌,우 선 중 공통 선 존재 확인.
|
|
||||||
const isSameLine = line1.left === line2.left || line1.left === line2.right || line1.right === line2.left || line1.right === line2.right
|
|
||||||
if (isSameLine) {
|
|
||||||
// 현재 선이 처리 되었음을 표기
|
|
||||||
let point1 = [line1.start.x, line1.start.y, intersectPoint.x, intersectPoint.y]
|
|
||||||
let point2 = [line2.start.x, line2.start.y, intersectPoint.x, intersectPoint.y]
|
|
||||||
let length1 = Math.sqrt((point1[2] - point1[0]) ** 2 + (point1[3] - point1[1]) ** 2)
|
|
||||||
let length2 = Math.sqrt((point2[2] - point2[0]) ** 2 + (point2[3] - point2[1]) ** 2)
|
|
||||||
if (length1 < EPSILON && length2 < EPSILON) continue
|
|
||||||
isProceed = true
|
|
||||||
|
|
||||||
//gable라인과 붙는경우 length가 0에 가까우면 포인트를 뒤집는다.
|
|
||||||
if (line1.type === TYPES.GABLE_LINE && length2 < EPSILON) {
|
|
||||||
point2 = [line2.end.x, line2.end.y, intersectPoint.x, intersectPoint.y]
|
|
||||||
length2 = Math.sqrt((point2[2] - point2[0]) ** 2 + (point2[3] - point2[1]) ** 2)
|
|
||||||
}
|
|
||||||
if (line2.type === TYPES.GABLE_LINE && length1 < EPSILON) {
|
|
||||||
point1 = [line1.end.x, line1.end.y, intersectPoint.x, intersectPoint.y]
|
|
||||||
length1 = Math.sqrt((point1[2] - point1[0]) ** 2 + (point1[3] - point1[1]) ** 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length1 > 0 && !alreadyPoints(innerLines, point1)) {
|
|
||||||
if (line1.type === TYPES.HIP) {
|
|
||||||
innerLines.push(drawHipLine(point1, canvas, roof, textMode, null, line1.degree, line1.degree))
|
|
||||||
} else if (line1.type === TYPES.RIDGE) {
|
|
||||||
innerLines.push(drawRidgeLine(point1, canvas, roof, textMode))
|
|
||||||
} else if (line1.type === TYPES.NEW) {
|
|
||||||
const isDiagonal = Math.abs(point1[0] - point1[2]) >= 1 && Math.abs(point1[1] - point1[3]) >= 1
|
|
||||||
if (isDiagonal) {
|
|
||||||
innerLines.push(drawHipLine(point1, canvas, roof, textMode, null, line1.degree, line1.degree))
|
|
||||||
} else {
|
|
||||||
innerLines.push(drawRidgeLine(point1, canvas, roof, textMode))
|
|
||||||
}
|
|
||||||
} else if (line1.type === TYPES.GABLE_LINE) {
|
|
||||||
if (line1.degree > 0) {
|
|
||||||
innerLines.push(drawHipLine(point1, canvas, roof, textMode, null, line1.degree, line1.degree))
|
|
||||||
} else {
|
|
||||||
innerLines.push(drawRidgeLine(point1, canvas, roof, textMode))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length2 > 0 && !alreadyPoints(innerLines, point2)) {
|
|
||||||
if (line2.type === TYPES.HIP) {
|
|
||||||
innerLines.push(drawHipLine(point2, canvas, roof, textMode, null, line2.degree, line2.degree))
|
|
||||||
} else if (line2.type === TYPES.RIDGE) {
|
|
||||||
innerLines.push(drawRidgeLine(point2, canvas, roof, textMode))
|
|
||||||
} else if (line2.type === TYPES.NEW) {
|
|
||||||
const isDiagonal = Math.abs(point2[0] - point2[2]) >= 1 && Math.abs(point2[1] - point2[3]) >= 1
|
|
||||||
if (isDiagonal) {
|
|
||||||
innerLines.push(drawHipLine(point2, canvas, roof, textMode, null, line2.degree, line2.degree))
|
|
||||||
} else {
|
|
||||||
innerLines.push(drawRidgeLine(point2, canvas, roof, textMode))
|
|
||||||
}
|
|
||||||
} else if (line2.type === TYPES.GABLE_LINE) {
|
|
||||||
if (line2.degree > 0) {
|
|
||||||
innerLines.push(drawHipLine(point2, canvas, roof, textMode, null, line2.degree, line2.degree))
|
|
||||||
} else {
|
|
||||||
innerLines.push(drawRidgeLine(point2, canvas, roof, textMode))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line1.type === TYPES.GABLE_LINE || line2.type === TYPES.GABLE_LINE) {
|
|
||||||
console.log('gableLine newAnalyze start')
|
|
||||||
const gableLine = line1.type === TYPES.GABLE_LINE ? line1 : line2
|
|
||||||
gableLine.connectCnt++
|
|
||||||
|
|
||||||
const checkLine = new fabric.Line([gableLine.start.x, gableLine.start.y, gableLine.end.x, gableLine.end.y], {
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 4,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
const checkCircle = new fabric.Circle({
|
|
||||||
left: intersectPoint.x,
|
|
||||||
top: intersectPoint.y,
|
|
||||||
radius: 5,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
canvas.add(checkLine, checkCircle)
|
|
||||||
canvas.renderAll()
|
|
||||||
|
|
||||||
const relationBaseLines = [line1.left, line1.right, line2.left, line2.right]
|
|
||||||
const uniqueBaseLines = [...new Set(relationBaseLines)]
|
|
||||||
if (uniqueBaseLines.length === 3) {
|
|
||||||
const linesCounts = new Map()
|
|
||||||
relationBaseLines.forEach((e) => {
|
|
||||||
linesCounts.set(e, (linesCounts.get(e) || 0) + 1)
|
|
||||||
})
|
|
||||||
const uniqueLines = Array.from(linesCounts.entries())
|
|
||||||
.filter(([_, count]) => count === 1)
|
|
||||||
.map(([line, _]) => line)
|
|
||||||
|
|
||||||
if (uniqueLines.length === 2) {
|
|
||||||
if (gableLine.connectCnt < 2) {
|
|
||||||
newAnalysis.push({
|
|
||||||
start: { x: intersectPoint.x, y: intersectPoint.y },
|
|
||||||
end: { x: gableLine.end.x, y: gableLine.end.y },
|
|
||||||
left: gableLine.left,
|
|
||||||
right: gableLine.right,
|
|
||||||
type: TYPES.GABLE_LINE,
|
|
||||||
degree: getDegreeByChon(baseLines[gableLine.right].attributes.pitch),
|
|
||||||
gableId: gableLine.gableId,
|
|
||||||
connectCnt: gableLine.connectCnt,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (gableLine.connectCnt >= 2) {
|
|
||||||
//가선분 발생만 시키는 더미 생성.
|
|
||||||
newAnalysis.push({
|
|
||||||
start: { x: intersectPoint.x, y: intersectPoint.y },
|
|
||||||
end: { x: intersectPoint.x, y: intersectPoint.y },
|
|
||||||
left: gableLine.gableId,
|
|
||||||
right: gableLine.gableId,
|
|
||||||
type: TYPES.HIP,
|
|
||||||
degree: 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log('gableLine newAnalyze end')
|
|
||||||
} else {
|
|
||||||
// 연결점에서 새로운 가선분을 생성
|
|
||||||
const relationBaseLines = [line1.left, line1.right, line2.left, line2.right]
|
|
||||||
const uniqueBaseLines = [...new Set(relationBaseLines)]
|
|
||||||
if (uniqueBaseLines.length === 3) {
|
|
||||||
const linesCounts = new Map()
|
|
||||||
relationBaseLines.forEach((e) => {
|
|
||||||
linesCounts.set(e, (linesCounts.get(e) || 0) + 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
const uniqueLines = Array.from(linesCounts.entries())
|
|
||||||
.filter(([_, count]) => count === 1)
|
|
||||||
.map(([line, _]) => line)
|
|
||||||
|
|
||||||
if (uniqueLines.length === 2) {
|
|
||||||
// 두 변의 이등분선 방향 계산
|
|
||||||
// uniqueLines.sort((a, b) => a - b)
|
|
||||||
console.log('uniqueLines : ', uniqueLines)
|
|
||||||
const baseLine1 = baseLines[uniqueLines[0]]
|
|
||||||
const baseLine2 = baseLines[uniqueLines[1]]
|
|
||||||
|
|
||||||
const checkLine1 = new fabric.Line([baseLine1.x1, baseLine1.y1, baseLine1.x2, baseLine1.y2], {
|
|
||||||
stroke: 'yellow',
|
|
||||||
strokeWidth: 4,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
const checkLine2 = new fabric.Line([baseLine2.x1, baseLine2.y1, baseLine2.x2, baseLine2.y2], {
|
|
||||||
stroke: 'blue',
|
|
||||||
strokeWidth: 4,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
canvas.add(checkLine1, checkLine2)
|
|
||||||
canvas.renderAll()
|
|
||||||
let bisector
|
|
||||||
console.log('isParallel(baseLine1, baseLine2)', isParallel(baseLine1, baseLine2))
|
|
||||||
if (isParallel(baseLine1, baseLine2)) {
|
|
||||||
bisector = getBisectLines(
|
|
||||||
{ x1: line1.start.x, x2: line1.end.x, y1: line1.start.y, y2: line1.end.y },
|
|
||||||
{ x1: line2.start.x, y1: line2.start.y, x2: line2.end.x, y2: line2.end.y },
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
//이등분선
|
|
||||||
bisector = getBisectBaseLines(baseLine1, baseLine2, intersectPoint, canvas)
|
|
||||||
}
|
|
||||||
|
|
||||||
//마주하는 지붕선을 찾는다.
|
|
||||||
const intersectionsByRoof = []
|
|
||||||
const checkEdge = {
|
|
||||||
vertex1: { x: intersectPoint.x, y: intersectPoint.y },
|
|
||||||
vertex2: { x: intersectPoint.x + bisector.x, y: intersectPoint.y + bisector.y },
|
|
||||||
}
|
|
||||||
const checkVector = {
|
|
||||||
x: Math.sign(checkEdge.vertex1.x - checkEdge.vertex2.x),
|
|
||||||
y: Math.sign(checkEdge.vertex1.y - checkEdge.vertex2.y),
|
|
||||||
}
|
|
||||||
roof.lines.forEach((line) => {
|
|
||||||
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
|
||||||
const is = edgesIntersection(lineEdge, checkEdge)
|
|
||||||
if (is && isPointOnLineNew(line, is)) {
|
|
||||||
const distance = Math.sqrt((is.x - intersectPoint.x) ** 2 + (is.y - intersectPoint.y) ** 2)
|
|
||||||
const isVector = { x: Math.sign(intersectPoint.x - is.x), y: Math.sign(intersectPoint.y - is.y) }
|
|
||||||
if (isVector.x === checkVector.x && isVector.y === checkVector.y) {
|
|
||||||
intersectionsByRoof.push({ is, distance })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
intersectionsByRoof.sort((a, b) => a.distance - b.distance)
|
|
||||||
//지붕 선과의 교점이 존재 할때
|
|
||||||
if (intersectionsByRoof.length > 0) {
|
|
||||||
let is = intersectionsByRoof[0].is
|
|
||||||
let linePoint = [intersectPoint.x, intersectPoint.y, is.x, is.y]
|
|
||||||
const isDiagonal = Math.abs(is.x - intersectPoint.x) >= 1 && Math.abs(is.y - intersectPoint.y) >= 1
|
|
||||||
const length = Math.sqrt((linePoint[2] - linePoint[0]) ** 2 + (linePoint[3] - linePoint[1]) ** 2)
|
|
||||||
if (!isDiagonal) {
|
|
||||||
const line1 = baseLines[uniqueLines[0]]
|
|
||||||
const line2 = baseLines[uniqueLines[1]]
|
|
||||||
const vector1 = { x: Math.sign(line1.x1 - line1.x2), y: Math.sign(line1.y1 - line1.y2) }
|
|
||||||
|
|
||||||
const prevLine = checkVector.x === vector1.x && checkVector.y === vector1.y ? line2 : line1
|
|
||||||
const nextLine = checkVector.x === vector1.x && checkVector.y === vector1.y ? line1 : line2
|
|
||||||
const drivePoint = getRidgeDrivePoint(linePoint, prevLine, nextLine, baseLines)
|
|
||||||
if (drivePoint !== null) {
|
|
||||||
const driveLength = Math.sqrt((drivePoint.x - intersectPoint.x) ** 2 + (drivePoint.y - intersectPoint.y) ** 2)
|
|
||||||
|
|
||||||
if (driveLength < length) {
|
|
||||||
linePoint = [intersectPoint.x, intersectPoint.y, drivePoint.x, drivePoint.y]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const checkNewLine = new fabric.Line(linePoint, { stroke: 'cyan', strokeWidth: 4, parentId: roofId, name: 'check' })
|
|
||||||
canvas.add(checkNewLine).renderAll()
|
|
||||||
|
|
||||||
newAnalysis.push({
|
|
||||||
start: { x: linePoint[0], y: linePoint[1] },
|
|
||||||
end: { x: linePoint[2], y: linePoint[3] },
|
|
||||||
left: uniqueLines[0],
|
|
||||||
right: uniqueLines[1],
|
|
||||||
type: TYPES.NEW,
|
|
||||||
degree: isDiagonal ? line1.degree : 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canvas
|
|
||||||
.getObjects()
|
|
||||||
.filter((object) => object.name === 'check')
|
|
||||||
.forEach((object) => canvas.remove(object))
|
|
||||||
canvas.renderAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
processed.add(pIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canvas
|
|
||||||
.getObjects()
|
|
||||||
.filter((object) => object.name === 'check')
|
|
||||||
.forEach((object) => canvas.remove(object))
|
|
||||||
canvas.renderAll()
|
|
||||||
}
|
|
||||||
if (isProceed) {
|
|
||||||
processed.add(index)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 처리된 가선분 제외
|
|
||||||
linesAnalysis = newAnalysis.concat(linesAnalysis.filter((_, index) => !processed.has(index)))
|
|
||||||
console.log('lineAnalysis: ', linesAnalysis)
|
|
||||||
|
|
||||||
canvas
|
|
||||||
.getObjects()
|
|
||||||
.filter((object) => object.name === 'check' || object.name === 'checkAnalysis')
|
|
||||||
.forEach((object) => canvas.remove(object))
|
|
||||||
canvas.renderAll()
|
|
||||||
// 새로운 가선분이 없을때 종료
|
|
||||||
console.log('newAnalysis.length : ', newAnalysis.length)
|
|
||||||
if (newAnalysis.length === 0) break
|
|
||||||
}
|
|
||||||
console.log('lineAnalysis: end ', linesAnalysis)*/
|
|
||||||
|
|
||||||
// 가선분 중 처리가 안되어있는 붙어있는 라인에 대한 예외처리.
|
|
||||||
/* const proceedAnalysis = []
|
|
||||||
linesAnalysis
|
|
||||||
.filter((line) => {
|
|
||||||
const dx = line.end.x - line.start.x
|
|
||||||
const dy = line.end.y - line.start.y
|
|
||||||
const length = Math.sqrt(dx ** 2 + dy ** 2)
|
|
||||||
return length > 0
|
|
||||||
})
|
|
||||||
.forEach((currentLine) => {
|
|
||||||
if (proceedAnalysis.find((p) => p === currentLine)) return
|
|
||||||
//현재와 같으면 제외, 이미 처리된 라인은 제외, 현재와 공통선분이 존재하지 않으면 제외
|
|
||||||
linesAnalysis
|
|
||||||
.filter((line) => {
|
|
||||||
const dx = line.end.x - line.start.x
|
|
||||||
const dy = line.end.y - line.start.y
|
|
||||||
const length = Math.sqrt(dx ** 2 + dy ** 2)
|
|
||||||
return length > 0
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(partnerLine) =>
|
|
||||||
partnerLine !== currentLine &&
|
|
||||||
!proceedAnalysis.find((p) => p === partnerLine) &&
|
|
||||||
(currentLine.left === partnerLine.left ||
|
|
||||||
currentLine.left === partnerLine.right ||
|
|
||||||
partnerLine.left === currentLine.left ||
|
|
||||||
partnerLine.left === currentLine.right),
|
|
||||||
)
|
|
||||||
.forEach((partnerLine) => {
|
|
||||||
const dx1 = currentLine.end.x - currentLine.start.x
|
|
||||||
const dy1 = currentLine.end.y - currentLine.start.y
|
|
||||||
const dx2 = partnerLine.end.x - partnerLine.start.x
|
|
||||||
const dy2 = partnerLine.end.y - partnerLine.start.y
|
|
||||||
const denominator = dy2 * dx1 - dx2 * dy1
|
|
||||||
const isOpposite = dx1 * dx2 + dy1 * dy2 < 0
|
|
||||||
//평행하지 않으면 제외
|
|
||||||
if (Math.abs(denominator) > EPSILON) return
|
|
||||||
|
|
||||||
const currentDegree = getDegreeByChon(baseLines[currentLine.left].attributes.pitch)
|
|
||||||
if (isOpposite) {
|
|
||||||
const points = [currentLine.start.x, currentLine.start.y, partnerLine.start.x, partnerLine.start.y]
|
|
||||||
const length = Math.sqrt((points[0] - points[2]) ** 2 + (points[1] - points[3]) ** 2)
|
|
||||||
|
|
||||||
if (length > 0) {
|
|
||||||
if (currentLine.type === TYPES.HIP) {
|
|
||||||
innerLines.push(drawHipLine(points, canvas, roof, textMode, null, currentDegree, currentDegree))
|
|
||||||
} else if (currentLine.type === TYPES.RIDGE) {
|
|
||||||
innerLines.push(drawRidgeLine(points, canvas, roof, textMode))
|
|
||||||
} else if (currentLine.type === TYPES.NEW) {
|
|
||||||
const isDiagonal = Math.abs(points[0] - points[2]) >= 1 && Math.abs(points[1] - points[3]) >= 1
|
|
||||||
if (isDiagonal && almostEqual(Math.abs(points[0] - points[2]), Math.abs(points[1] - points[3]))) {
|
|
||||||
innerLines.push(drawHipLine(points, canvas, roof, textMode, null, currentDegree, currentDegree))
|
|
||||||
}
|
|
||||||
if (!isDiagonal) {
|
|
||||||
innerLines.push(drawRidgeLine(points, canvas, roof, textMode))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
proceedAnalysis.push(currentLine, partnerLine)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const allPoints = [currentLine.start, currentLine.end, partnerLine.start, partnerLine.end]
|
|
||||||
let points = []
|
|
||||||
allPoints.forEach((point) => {
|
|
||||||
let count = 0
|
|
||||||
allPoints.forEach((p) => {
|
|
||||||
if (almostEqual(point.x, p.x) && almostEqual(point.y, p.y)) count++
|
|
||||||
})
|
|
||||||
if (count === 1) points.push(point)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (points.length === 2) {
|
|
||||||
const length = Math.sqrt((points[0].x - points[1].x) ** 2 + (points[0].y - points[1].y) ** 2)
|
|
||||||
if (length < EPSILON) return
|
|
||||||
const isDiagonal = Math.abs(points[0].x - points[1].x) >= 1 && Math.abs(points[0].y - points[1].y) >= 1
|
|
||||||
if (isDiagonal) {
|
|
||||||
innerLines.push(
|
|
||||||
drawHipLine([points[0].x, points[0].y, points[1].x, points[1].y], canvas, roof, textMode, null, currentDegree, currentDegree),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
innerLines.push(drawRidgeLine([points[0].x, points[0].y, points[1].x, points[1].y], canvas, roof, textMode))
|
|
||||||
}
|
|
||||||
proceedAnalysis.push(currentLine, partnerLine)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
linesAnalysis = linesAnalysis.filter((line) => !proceedAnalysis.find((p) => p === line))*/
|
|
||||||
|
|
||||||
//하단 지붕 라인처리
|
|
||||||
/* const downRoofLines = []
|
|
||||||
baseLines.forEach((baseLine, index) => {
|
|
||||||
const nextLine = baseLines[(index + 1) % baseLines.length]
|
|
||||||
const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
|
|
||||||
|
|
||||||
const prevLineVector = { x: Math.sign(prevLine.x1 - prevLine.x2), y: Math.sign(prevLine.y1 - prevLine.y2) }
|
|
||||||
const nextLineVector = { x: Math.sign(nextLine.x1 - nextLine.x2), y: Math.sign(nextLine.y1 - nextLine.y2) }
|
|
||||||
|
|
||||||
//반절마루 생성불가이므로 지붕선 분기를 해야하는지 확인 후 처리.
|
|
||||||
if (
|
|
||||||
prevLineVector.x === nextLineVector.x &&
|
|
||||||
prevLineVector.y === nextLineVector.y &&
|
|
||||||
(prevLine.attributes.type === LINE_TYPE.WALLLINE.GABLE || nextLine.attributes.type === LINE_TYPE.WALLLINE.GABLE)
|
|
||||||
) {
|
|
||||||
downRoofLines.push(index)
|
|
||||||
}
|
|
||||||
})*/
|
|
||||||
|
|
||||||
/*if (downRoofLines.length > 0) {
|
|
||||||
downRoofLines.forEach((index) => {
|
|
||||||
const currentLine = baseLines[index]
|
|
||||||
// const nextLine = baseLines[(index + 1) % baseLines.length]
|
|
||||||
// const prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
|
|
||||||
|
|
||||||
const analyze = analyzeLine(currentLine)
|
|
||||||
if (analyze.isDiagonal) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const roofLine = analyze.roofLine
|
|
||||||
let roofPoint = [analyze.startPoint.x, analyze.startPoint.y, analyze.endPoint.x, analyze.endPoint.y]
|
|
||||||
|
|
||||||
if (analyze.isVertical) {
|
|
||||||
roofPoint[0] = roofLine.x1
|
|
||||||
roofPoint[2] = roofLine.x2
|
|
||||||
}
|
|
||||||
if (analyze.isHorizontal) {
|
|
||||||
roofPoint[1] = roofLine.y1
|
|
||||||
roofPoint[3] = roofLine.y2
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('analyze: ', analyze)
|
|
||||||
const findRidgeVector = { x: 0, y: 0 }
|
|
||||||
if (analyze.isVertical) {
|
|
||||||
// noinspection JSSuspiciousNameCombination
|
|
||||||
findRidgeVector.x = analyze.directionVector.y
|
|
||||||
}
|
|
||||||
if (analyze.isHorizontal) {
|
|
||||||
// noinspection JSSuspiciousNameCombination
|
|
||||||
findRidgeVector.y = analyze.directionVector.x
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('findRidgeVector: ', findRidgeVector)
|
|
||||||
innerLines
|
|
||||||
.filter((line) => {
|
|
||||||
if (line.name === LINE_TYPE.SUBLINE.RIDGE) {
|
|
||||||
if (analyze.isVertical) {
|
|
||||||
const signX = Math.sign(currentLine.x1 - line.x1)
|
|
||||||
console.log('signX: ', signX)
|
|
||||||
return signX === findRidgeVector.x
|
|
||||||
}
|
|
||||||
if (analyze.isHorizontal) {
|
|
||||||
const signY = Math.sign(currentLine.y1 - line.y1)
|
|
||||||
console.log('signY: ', signY)
|
|
||||||
return signY === findRidgeVector.y
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
.forEach((line) => {
|
|
||||||
if (line.name === LINE_TYPE.SUBLINE.RIDGE) {
|
|
||||||
const checkLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], {
|
|
||||||
stroke: 'red',
|
|
||||||
strokeWidth: 4,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
canvas.add(checkLine)
|
|
||||||
canvas.renderAll()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/!*const oppositeLines = []
|
|
||||||
baseLines
|
|
||||||
.filter((line) => {
|
|
||||||
//평행한 반대방향 라인인지 확인.
|
|
||||||
const lineAnalyze = analyzeLine(line)
|
|
||||||
return (
|
|
||||||
(analyze.isHorizontal &&
|
|
||||||
lineAnalyze.directionVector.x !== analyze.directionVector.x &&
|
|
||||||
lineAnalyze.directionVector.y === analyze.directionVector.y) ||
|
|
||||||
(analyze.isVertical &&
|
|
||||||
lineAnalyze.directionVector.x === analyze.directionVector.x &&
|
|
||||||
lineAnalyze.directionVector.y !== analyze.directionVector.y)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.filter((line) => {
|
|
||||||
//라인이 현재라인에 overlap 되거나, 현재 라인을 full overlap하는지 확인.
|
|
||||||
if (analyze.isHorizontal) {
|
|
||||||
const currentMinX = Math.min(currentLine.x1, currentLine.x2)
|
|
||||||
const currentMaxX = Math.max(currentLine.x1, currentLine.x2)
|
|
||||||
const minX = Math.min(line.x1, line.x2)
|
|
||||||
const maxX = Math.max(line.x1, line.x2)
|
|
||||||
//full overlap
|
|
||||||
if (minX <= currentMinX && maxX >= currentMaxX) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
//라인 포인트중 하나라도 현재 라인의 범위에 들어와있으면 overlap으로 판단.
|
|
||||||
if ((currentMinX <= minX && minX <= currentMaxX) || (currentMinX <= maxX && maxX <= currentMaxX)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (analyze.isVertical) {
|
|
||||||
const currentMinY = Math.min(currentLine.y1, currentLine.y2)
|
|
||||||
const currentMaxY = Math.max(currentLine.y1, currentLine.y2)
|
|
||||||
const minY = Math.min(line.y1, line.y2)
|
|
||||||
const maxY = Math.max(line.y1, line.y2)
|
|
||||||
//full overlap
|
|
||||||
if (minY <= currentMinY && maxY >= currentMaxY) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
//라인 포인트중 하나라도 현재 라인의 범위에 들어와있으면 overlap으로 판단.
|
|
||||||
if ((currentMinY <= minY && minY <= currentMaxY) || (currentMinY <= maxY && maxY <= currentMaxY)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
.forEach((line, i) => {
|
|
||||||
const checkLine = new fabric.Line([line.x1, line.y1, line.x2, line.y2], {
|
|
||||||
stroke: 'green',
|
|
||||||
strokeWidth: 4,
|
|
||||||
parentId: roofId,
|
|
||||||
name: 'check',
|
|
||||||
})
|
|
||||||
canvas.add(checkLine)
|
|
||||||
canvas.renderAll()
|
|
||||||
})*!/
|
|
||||||
|
|
||||||
// innerLines.push(drawRoofLine(roofPoint, canvas, roof, textMode))
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*if (linesAnalysis.length > 0) {
|
|
||||||
linesAnalysis
|
|
||||||
.filter((line) => {
|
|
||||||
const dx = line.end.x - line.start.x
|
|
||||||
const dy = line.end.y - line.start.y
|
|
||||||
const length = Math.sqrt(dx ** 2 + dy ** 2)
|
|
||||||
return length > 0
|
|
||||||
})
|
|
||||||
.forEach((line) => {
|
|
||||||
const startOnLine = roof.lines.find((l) => isPointOnLineNew(l, line.start))
|
|
||||||
const endOnLine = roof.lines.find((l) => isPointOnLineNew(l, line.end))
|
|
||||||
console.log('startOnLine, endOnLine: ', startOnLine, endOnLine)
|
|
||||||
const allLinesPoints = []
|
|
||||||
innerLines.forEach((innerLine) => {
|
|
||||||
allLinesPoints.push({ x: innerLine.x1, y: innerLine.y1 }, { x: innerLine.x2, y: innerLine.y2 })
|
|
||||||
})
|
|
||||||
|
|
||||||
if (
|
|
||||||
allLinesPoints.filter((p) => almostEqual(p.x, line.start.x) && almostEqual(p.y, line.start.y)).length < 3 &&
|
|
||||||
allLinesPoints.filter((p) => almostEqual(p.x, line.end.x) && almostEqual(p.y, line.end.y)).length === 0
|
|
||||||
) {
|
|
||||||
if (startOnLine || endOnLine) {
|
|
||||||
if (line.degree === 0) {
|
|
||||||
innerLines.push(drawRoofLine([line.start.x, line.start.y, line.end.x, line.end.y], canvas, roof, textMode))
|
|
||||||
} else {
|
|
||||||
innerLines.push(
|
|
||||||
drawHipLine([line.start.x, line.start.y, line.end.x, line.end.y], canvas, roof, textMode, null, line.degree, line.degree),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//지붕선에 따라 라인추가 작업 처리.
|
|
||||||
/*const innerLinesPoints = []
|
|
||||||
innerLines.forEach((line) => {
|
|
||||||
const hasCoord1 = innerLinesPoints.find((p) => p.x === line.x1 && p.y === line.y1)
|
|
||||||
const hasCoord2 = innerLinesPoints.find((p) => p.x === line.x2 && p.y === line.y2)
|
|
||||||
if (!hasCoord1) innerLinesPoints.push({ x: line.x1, y: line.y1 })
|
|
||||||
if (!hasCoord2) innerLinesPoints.push({ x: line.x2, y: line.y2 })
|
|
||||||
})
|
|
||||||
roof.lines.forEach((line) => {
|
|
||||||
const splitPoint = []
|
|
||||||
let hasOverlapLine = false
|
|
||||||
const minX = Math.min(line.x1, line.x2)
|
|
||||||
const maxX = Math.max(line.x1, line.x2)
|
|
||||||
const minY = Math.min(line.y1, line.y2)
|
|
||||||
const maxY = Math.max(line.y1, line.y2)
|
|
||||||
innerLines.forEach((innerLine) => {
|
|
||||||
const innerLineMinX = Math.min(innerLine.x1, innerLine.x2)
|
|
||||||
const innerLineMaxX = Math.max(innerLine.x1, innerLine.x2)
|
|
||||||
const innerLineMinY = Math.min(innerLine.y1, innerLine.y2)
|
|
||||||
const innerLineMaxY = Math.max(innerLine.y1, innerLine.y2)
|
|
||||||
if (innerLineMinX <= minX && innerLineMaxX >= maxX && innerLineMinY <= minY && innerLineMaxY >= maxY) {
|
|
||||||
hasOverlapLine = true
|
|
||||||
}
|
|
||||||
if (minX <= innerLineMinX && maxX >= innerLineMaxX && minY <= innerLineMinY && maxY >= innerLineMaxY) {
|
|
||||||
hasOverlapLine = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (hasOverlapLine) return
|
|
||||||
|
|
||||||
innerLinesPoints.forEach((point) => {
|
|
||||||
if (
|
|
||||||
isPointOnLineNew(line, point) &&
|
|
||||||
!(almostEqual(line.x1, point.x) && almostEqual(line.y1, point.y)) &&
|
|
||||||
!(almostEqual(line.x2, point.x) && almostEqual(line.y2, point.y))
|
|
||||||
) {
|
|
||||||
const distance = Math.sqrt((point.x - line.x1) ** 2 + (point.y - line.y1) ** 2)
|
|
||||||
splitPoint.push({ point, distance })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (splitPoint.length > 0) {
|
|
||||||
splitPoint.sort((a, b) => a[1] - b[1])
|
|
||||||
let startPoint = { x: line.x1, y: line.y1 }
|
|
||||||
for (let i = 0; i < splitPoint.length; i++) {
|
|
||||||
const point = splitPoint[i].point
|
|
||||||
innerLines.push(drawRoofLine([startPoint.x, startPoint.y, point.x, point.y], canvas, roof, textMode))
|
|
||||||
startPoint = point
|
|
||||||
}
|
|
||||||
innerLines.push(drawRoofLine([startPoint.x, startPoint.y, line.x2, line.y2], canvas, roof, textMode))
|
|
||||||
} else {
|
|
||||||
innerLines.push(drawRoofLine([line.x1, line.y1, line.x2, line.y2], canvas, roof, textMode))
|
|
||||||
}
|
|
||||||
})*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user