|
|
|
|
@ -360,336 +360,6 @@ export const isSamePoint = (a, b) => {
|
|
|
|
|
return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 2 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 박공지붕(templateA, templateB)을 그린다.
|
|
|
|
|
* @param roofId
|
|
|
|
|
* @param canvas
|
|
|
|
|
* @param textMode
|
|
|
|
|
*/
|
|
|
|
|
export const drawGabledRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
const roof = canvas?.getObjects().find((object) => object.id === roofId)
|
|
|
|
|
const roofLines = roof.lines
|
|
|
|
|
const wallLines = canvas?.getObjects().find((object) => object.name === POLYGON_TYPE.WALL && object.attributes.roofId === roof.id).lines
|
|
|
|
|
const hasNonParallelLines = roofLines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
|
|
|
|
|
if (hasNonParallelLines.length > 0) {
|
|
|
|
|
// alert('대각선이 존재합니다.')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 처마라인의 기본속성 입력
|
|
|
|
|
const eaves = []
|
|
|
|
|
roofLines.forEach((currentRoof, index) => {
|
|
|
|
|
if (currentRoof.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
|
|
|
|
|
eaves.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize })
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
const ridges = []
|
|
|
|
|
eaves.sort((a, b) => a.length - b.length)
|
|
|
|
|
|
|
|
|
|
eaves.forEach((eave) => {
|
|
|
|
|
const index = eave.index,
|
|
|
|
|
currentRoof = eave.roof
|
|
|
|
|
const currentWall = wallLines[index]
|
|
|
|
|
|
|
|
|
|
const oppositeLine = roofLines
|
|
|
|
|
.filter((line) => line !== currentRoof) // 현재 벽라인을 제외한 나머지 벽라인
|
|
|
|
|
.filter((line) => {
|
|
|
|
|
if (currentRoof.x1 === currentRoof.x2) {
|
|
|
|
|
const vector = Math.sign(currentRoof.y1 - currentRoof.y2)
|
|
|
|
|
const vector2 = Math.sign(currentRoof.x1 - currentWall.x1)
|
|
|
|
|
return line.x1 === line.x2 && Math.sign(line.y1 - line.y2) === -vector && Math.sign(currentRoof.x1 - line.x1) === vector2
|
|
|
|
|
}
|
|
|
|
|
if (currentRoof.y1 === currentRoof.y2) {
|
|
|
|
|
const vector = Math.sign(currentRoof.x1 - currentRoof.x2)
|
|
|
|
|
const vector2 = Math.sign(currentRoof.y1 - currentWall.y1)
|
|
|
|
|
return line.y1 === line.y2 && Math.sign(line.x1 - line.x2) === -vector && Math.sign(currentRoof.y1 - line.y1) === vector2
|
|
|
|
|
}
|
|
|
|
|
}) // 현재 벽라인과 직교하는 벽라인
|
|
|
|
|
|
|
|
|
|
// 현재 벽라인과 직교하는 벽라인 사이에 마루를 그린다.
|
|
|
|
|
oppositeLine.forEach((line) => {
|
|
|
|
|
let points // 마루의 시작점과 끝점
|
|
|
|
|
if (currentRoof.x1 === currentRoof.x2) {
|
|
|
|
|
const currentRoofYRange = [Math.min(currentRoof.y1, currentRoof.y2), Math.max(currentRoof.y1, currentRoof.y2)]
|
|
|
|
|
const lineYRange = [Math.min(line.y1, line.y2), Math.max(line.y1, line.y2)]
|
|
|
|
|
const overlapYRange = [Math.max(currentRoofYRange[0], lineYRange[0]), Math.min(currentRoofYRange[1], lineYRange[1])]
|
|
|
|
|
if (overlapYRange[1] - overlapYRange[0] > 0) {
|
|
|
|
|
const centerX = Math.round(((currentRoof.x1 + line.x1) / 2) * 10) / 10
|
|
|
|
|
points = [centerX, overlapYRange[0], centerX, overlapYRange[1]]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (currentRoof.y1 === currentRoof.y2) {
|
|
|
|
|
const currentRoofXRange = [Math.min(currentRoof.x1, currentRoof.x2), Math.max(currentRoof.x1, currentRoof.x2)]
|
|
|
|
|
const lineXRange = [Math.min(line.x1, line.x2), Math.max(line.x1, line.x2)]
|
|
|
|
|
const overlapXRange = [Math.max(currentRoofXRange[0], lineXRange[0]), Math.min(currentRoofXRange[1], lineXRange[1])]
|
|
|
|
|
if (overlapXRange[1] - overlapXRange[0] > 0) {
|
|
|
|
|
const centerY = Math.round(((currentRoof.y1 + line.y1) / 2) * 10) / 10
|
|
|
|
|
points = [overlapXRange[0], centerY, overlapXRange[1], centerY]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 마루를 그린다.
|
|
|
|
|
if (points) {
|
|
|
|
|
const ridge = new QLine(points, {
|
|
|
|
|
parentId: roof.id,
|
|
|
|
|
fontSize: roof.fontSize,
|
|
|
|
|
stroke: '#1083E3',
|
|
|
|
|
strokeWidth: 1,
|
|
|
|
|
name: LINE_TYPE.SUBLINE.RIDGE,
|
|
|
|
|
attributes: { roofId: roof.id, currentRoofId: [currentRoof.id] },
|
|
|
|
|
visible: false,
|
|
|
|
|
})
|
|
|
|
|
const duplicateRidge = ridges.find(
|
|
|
|
|
(ridge) => ridge.x1 === points[0] && ridge.y1 === points[1] && ridge.x2 === points[2] && ridge.y2 === points[3],
|
|
|
|
|
)
|
|
|
|
|
// 중복된 마루는 제외한다.
|
|
|
|
|
if (duplicateRidge) {
|
|
|
|
|
duplicateRidge.attributes.currentRoofId.push(currentRoof.id)
|
|
|
|
|
} else {
|
|
|
|
|
canvas.add(ridge)
|
|
|
|
|
canvas.renderAll()
|
|
|
|
|
ridges.push(ridge)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
// 처마마다 지붕 polygon 을 그린다.
|
|
|
|
|
eaves.forEach((eave) => {
|
|
|
|
|
const index = eave.index,
|
|
|
|
|
currentRoof = eave.roof
|
|
|
|
|
const currentWall = wallLines[index]
|
|
|
|
|
const currentRidges = ridges.filter((ridge) => ridge.attributes.currentRoofId.includes(eave.roof.id))
|
|
|
|
|
let points = []
|
|
|
|
|
const signX = Math.sign(currentRoof.x1 - currentRoof.x2)
|
|
|
|
|
let currentX1 = currentRoof.x1,
|
|
|
|
|
currentY1 = currentRoof.y1,
|
|
|
|
|
currentX2 = currentRoof.x2,
|
|
|
|
|
currentY2 = currentRoof.y2
|
|
|
|
|
let changeX1 = [Math.min(currentRoof.x1, currentRoof.x2), Math.min(currentRoof.x1, currentRoof.x2)],
|
|
|
|
|
changeY1 = [Math.min(currentRoof.y1, currentRoof.y2), Math.min(currentRoof.y1, currentRoof.y2)],
|
|
|
|
|
changeX2 = [Math.max(currentRoof.x2, currentRoof.x1), Math.max(currentRoof.x2, currentRoof.x1)],
|
|
|
|
|
changeY2 = [Math.max(currentRoof.y2, currentRoof.y1), Math.max(currentRoof.y2, currentRoof.y1)]
|
|
|
|
|
|
|
|
|
|
if (signX === 0) {
|
|
|
|
|
currentY1 = Math.min(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
|
|
|
|
changeY1[1] = currentY1
|
|
|
|
|
currentY2 = Math.max(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
|
|
|
|
changeY2[1] = currentY2
|
|
|
|
|
} else {
|
|
|
|
|
currentX1 = Math.min(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
|
|
|
|
changeX1[1] = currentX1
|
|
|
|
|
currentX2 = Math.max(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
|
|
|
|
changeX2[1] = currentX2
|
|
|
|
|
}
|
|
|
|
|
points.push({ x: currentX1, y: currentY1 }, { x: currentX2, y: currentY2 })
|
|
|
|
|
|
|
|
|
|
currentRidges.forEach((ridge) => {
|
|
|
|
|
let ridgeX1 = ridge.x1,
|
|
|
|
|
ridgeY1 = ridge.y1,
|
|
|
|
|
ridgeX2 = ridge.x2,
|
|
|
|
|
ridgeY2 = ridge.y2
|
|
|
|
|
if (signX === 0) {
|
|
|
|
|
ridgeY1 = Math.min(ridge.y1, ridge.y2)
|
|
|
|
|
ridgeY2 = Math.max(ridge.y1, ridge.y2)
|
|
|
|
|
} else {
|
|
|
|
|
ridgeX1 = Math.min(ridge.x1, ridge.x2)
|
|
|
|
|
ridgeX2 = Math.max(ridge.x1, ridge.x2)
|
|
|
|
|
}
|
|
|
|
|
points.push({ x: ridgeX1, y: ridgeY1 }, { x: ridgeX2, y: ridgeY2 })
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
points.forEach((point) => {
|
|
|
|
|
if (point.x === changeX1[0] && changeX1[0] !== changeX1[1]) {
|
|
|
|
|
point.x = changeX1[1]
|
|
|
|
|
}
|
|
|
|
|
if (point.x === changeX2[0] && changeX2[0] !== changeX2[1]) {
|
|
|
|
|
point.x = changeX2[1]
|
|
|
|
|
}
|
|
|
|
|
if (point.y === changeY1[0] && changeY1[0] !== changeY1[1]) {
|
|
|
|
|
point.y = changeY1[1]
|
|
|
|
|
}
|
|
|
|
|
if (point.y === changeY2[0] && changeY2[0] !== changeY2[1]) {
|
|
|
|
|
point.y = changeY2[1]
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
//중복된 point 제거
|
|
|
|
|
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
|
|
|
|
|
//point 정렬 (가장 좌측, 최상단의 점을 기준으로 삼는다.)
|
|
|
|
|
const startPoint = points
|
|
|
|
|
.filter((point) => point.x === Math.min(...points.map((point) => point.x)))
|
|
|
|
|
.reduce((prev, current) => {
|
|
|
|
|
return prev.y < current.y ? prev : current
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const sortedPoints = []
|
|
|
|
|
sortedPoints.push(startPoint)
|
|
|
|
|
|
|
|
|
|
points.forEach((p, index) => {
|
|
|
|
|
if (index === 0) {
|
|
|
|
|
//시작점 다음 점 찾기, y좌표가 startPoint.y 보다 큰 점 중 x좌표가 가까운 점
|
|
|
|
|
const underStartPoint = points.filter((point) => point.y > startPoint.y)
|
|
|
|
|
const nextPoint = underStartPoint
|
|
|
|
|
.filter((point) => point.x === startPoint.x)
|
|
|
|
|
.reduce((prev, current) => {
|
|
|
|
|
if (prev === undefined) {
|
|
|
|
|
return current
|
|
|
|
|
}
|
|
|
|
|
return Math.abs(prev.y - startPoint.y) < Math.abs(current.y - startPoint.y) ? prev : current
|
|
|
|
|
}, undefined)
|
|
|
|
|
if (nextPoint) {
|
|
|
|
|
sortedPoints.push(nextPoint)
|
|
|
|
|
} else {
|
|
|
|
|
const nextPoint = underStartPoint.reduce((prev, current) => {
|
|
|
|
|
const prevHypos = Math.sqrt(Math.abs(Math.pow(prev.x - startPoint.x, 2)) + Math.abs(Math.pow(prev.y - startPoint.y, 2)))
|
|
|
|
|
const currentHypos = Math.sqrt(Math.abs(Math.pow(current.x - startPoint.x, 2)) + Math.abs(Math.pow(current.y - startPoint.y, 2)))
|
|
|
|
|
return prevHypos < currentHypos ? prev : current
|
|
|
|
|
}, undefined)
|
|
|
|
|
sortedPoints.push(nextPoint)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const lastPoint = sortedPoints[sortedPoints.length - 1]
|
|
|
|
|
const prevPoint = sortedPoints[sortedPoints.length - 2]
|
|
|
|
|
const otherPoints = points.filter((point) => sortedPoints.includes(point) === false)
|
|
|
|
|
const nextPoint = otherPoints.reduce((prev, current) => {
|
|
|
|
|
if (prev === undefined) {
|
|
|
|
|
const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))))
|
|
|
|
|
const adjacent = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
|
|
|
|
const hypotenuse = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))))
|
|
|
|
|
|
|
|
|
|
const angle = Math.round(
|
|
|
|
|
Math.acos((Math.pow(adjacent, 2) + Math.pow(height, 2) - Math.pow(hypotenuse, 2)) / (2 * adjacent * height)) * (180 / Math.PI),
|
|
|
|
|
)
|
|
|
|
|
if (angle === 90) {
|
|
|
|
|
return current
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return prev
|
|
|
|
|
}
|
|
|
|
|
}, undefined)
|
|
|
|
|
if (nextPoint) {
|
|
|
|
|
sortedPoints.push(nextPoint)
|
|
|
|
|
} else {
|
|
|
|
|
const nextPoint = otherPoints.reduce((prev, current) => {
|
|
|
|
|
if (prev !== undefined) {
|
|
|
|
|
const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))))
|
|
|
|
|
const adjacentC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
|
|
|
|
const hypotenuseC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))))
|
|
|
|
|
const angleC = Math.round(
|
|
|
|
|
Math.acos((Math.pow(adjacentC, 2) + Math.pow(height, 2) - Math.pow(hypotenuseC, 2)) / (2 * adjacentC * height)) * (180 / Math.PI),
|
|
|
|
|
)
|
|
|
|
|
const adjacentP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - lastPoint.x, 2)) + Math.abs(Math.pow(prev.y - lastPoint.y, 2))))
|
|
|
|
|
const hypotenuseP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - prevPoint.x, 2)) + Math.abs(Math.pow(prev.y - prevPoint.y, 2))))
|
|
|
|
|
const angleP = Math.round(
|
|
|
|
|
Math.acos((Math.pow(adjacentP, 2) + Math.pow(height, 2) - Math.pow(hypotenuseP, 2)) / (2 * adjacentP * height)) * (180 / Math.PI),
|
|
|
|
|
)
|
|
|
|
|
if (Math.abs(90 - angleC) < Math.abs(90 - angleP)) {
|
|
|
|
|
return current
|
|
|
|
|
} else {
|
|
|
|
|
return prev
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return current
|
|
|
|
|
}
|
|
|
|
|
}, undefined)
|
|
|
|
|
if (nextPoint) {
|
|
|
|
|
sortedPoints.push(nextPoint)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (sortedPoints.length > 0) {
|
|
|
|
|
const roofPolygon = new QPolygon(sortedPoints, {
|
|
|
|
|
parentId: roof.id,
|
|
|
|
|
fill: 'transparent',
|
|
|
|
|
stroke: '#1083E3',
|
|
|
|
|
strokeWidth: 2,
|
|
|
|
|
selectable: false,
|
|
|
|
|
fontSize: roof.fontSize,
|
|
|
|
|
name: 'roofPolygon',
|
|
|
|
|
attributes: {
|
|
|
|
|
roofId: roof.id,
|
|
|
|
|
currentRoofId: currentRoof.id,
|
|
|
|
|
pitch: currentRoof.attributes.pitch,
|
|
|
|
|
degree: currentRoof.attributes.degree,
|
|
|
|
|
direction: currentRoof.direction,
|
|
|
|
|
},
|
|
|
|
|
originX: 'center',
|
|
|
|
|
originY: 'center',
|
|
|
|
|
})
|
|
|
|
|
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
|
|
|
|
|
//지붕 각도에 따른 실측치 조정
|
|
|
|
|
roofPolygon.lines.forEach((line) => {
|
|
|
|
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
|
|
|
|
|
const slope = (line) => (line.x2 - line.x1 === 0 ? Infinity : (line.y2 - line.y1) / (line.x2 - line.x1))
|
|
|
|
|
|
|
|
|
|
if (currentDegree > 0 && slope(line) !== slope(currentRoof)) {
|
|
|
|
|
const height = Math.tan(currentDegree * (Math.PI / 180)) * line.attributes.planeSize
|
|
|
|
|
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2)))
|
|
|
|
|
} else {
|
|
|
|
|
line.attributes.actualSize = line.attributes.planeSize
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
roof.separatePolygon.push(roofPolygon)
|
|
|
|
|
canvas.add(roofPolygon)
|
|
|
|
|
canvas.renderAll()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
if (ridges.length > 0) {
|
|
|
|
|
ridges.forEach((ridge) => roof.innerLines.push(ridge))
|
|
|
|
|
}
|
|
|
|
|
//기준선 제거
|
|
|
|
|
// ridges.forEach((ridge) => canvas.remove(ridge))
|
|
|
|
|
|
|
|
|
|
eaves.forEach((eave) => {
|
|
|
|
|
const currentRoof = eave.roof
|
|
|
|
|
let currentRidges = ridges.filter((ridge) => ridge.attributes.currentRoofId.includes(currentRoof.id))
|
|
|
|
|
if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) {
|
|
|
|
|
currentRidges = currentRidges.reduce((farthest, ridge) => {
|
|
|
|
|
const currentDistance = Math.abs(ridge.x1 - currentRoof.x1)
|
|
|
|
|
const farthestDistance = farthest ? Math.abs(farthest.x1 - currentRoof.x1) : 0
|
|
|
|
|
return currentDistance > farthestDistance ? ridge : farthest
|
|
|
|
|
}, null)
|
|
|
|
|
} else {
|
|
|
|
|
currentRidges = currentRidges.reduce((farthest, ridge) => {
|
|
|
|
|
const currentDistance = Math.abs(ridge.y1 - currentRoof.y1)
|
|
|
|
|
const farthestDistance = farthest ? Math.abs(farthest.y1 - currentRoof.y1) : 0
|
|
|
|
|
return currentDistance > farthestDistance ? ridge : farthest
|
|
|
|
|
}, null)
|
|
|
|
|
}
|
|
|
|
|
if (currentRidges) {
|
|
|
|
|
const ridgeMidX = (currentRidges.x1 + currentRidges.x2) / 2
|
|
|
|
|
const ridgeMidY = (currentRidges.y1 + currentRidges.y2) / 2
|
|
|
|
|
const x2 = Math.sign(currentRidges.x1 - currentRidges.x2) === 0 ? currentRoof.x1 : ridgeMidX
|
|
|
|
|
const y2 = Math.sign(currentRidges.x1 - currentRidges.x2) === 0 ? ridgeMidY : currentRoof.y1
|
|
|
|
|
|
|
|
|
|
const pitchSizeLine = new QLine([ridgeMidX, ridgeMidY, x2, y2], {
|
|
|
|
|
parentId: roof.id,
|
|
|
|
|
stroke: '#000000',
|
|
|
|
|
strokeWidth: 2,
|
|
|
|
|
strokeDashArray: [5, 5],
|
|
|
|
|
selectable: false,
|
|
|
|
|
fontSize: roof.fontSize,
|
|
|
|
|
attributes: {
|
|
|
|
|
roofId: roof.id,
|
|
|
|
|
type: 'pitchSizeLine',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
canvas.add(pitchSizeLine)
|
|
|
|
|
canvas.renderAll()
|
|
|
|
|
|
|
|
|
|
const adjust = Math.sqrt(
|
|
|
|
|
Math.pow(Math.round(Math.abs(pitchSizeLine.x1 - pitchSizeLine.x2) * 10), 2) +
|
|
|
|
|
Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2),
|
|
|
|
|
)
|
|
|
|
|
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
|
|
|
|
|
const height = Math.tan(currentDegree * (Math.PI / 180)) * adjust
|
|
|
|
|
const lengthText = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2)))
|
|
|
|
|
pitchSizeLine.setLengthText(lengthText)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 한쪽흐름 지붕
|
|
|
|
|
* @param roofId
|
|
|
|
|
@ -798,6 +468,9 @@ export const drawRidgeRoof = (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)
|
|
|
|
|
|
|
|
|
|
console.log('wall.lines : ', wall.lines)
|
|
|
|
|
console.log('wall.baseLines : ', wall.baseLines)
|
|
|
|
|
|
|
|
|
|
const hasNonParallelLines = roof.lines.filter((line) => Big(line.x1).minus(Big(line.x2)).gt(1) && Big(line.y1).minus(Big(line.y2)).gt(1))
|
|
|
|
|
if (hasNonParallelLines.length > 0) {
|
|
|
|
|
return
|
|
|
|
|
@ -867,6 +540,8 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
const drawGableRidgeSecond = []
|
|
|
|
|
const drawGablePolygonFirst = []
|
|
|
|
|
const drawGablePolygonSecond = []
|
|
|
|
|
const drawHipAndGableFirst = []
|
|
|
|
|
|
|
|
|
|
/** 모양을 판단한다. */
|
|
|
|
|
drawBaseLines.forEach((currentBaseLine, index) => {
|
|
|
|
|
let prevBaseLine = drawBaseLines[(index - 1 + drawBaseLines.length) % drawBaseLines.length]
|
|
|
|
|
@ -890,27 +565,25 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 현재 라인이 처마유형일 경우 */
|
|
|
|
|
if (eavesType.includes(currentLine.attributes?.type)) {
|
|
|
|
|
if (eavesType.includes(nextLine.attributes?.type)) {
|
|
|
|
|
if (currentLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
|
|
|
|
|
if (nextLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
|
|
|
|
|
/**
|
|
|
|
|
* 이전, 다음 라인이 처마일때 라인의 방향이 반대면 ㄷ 모양으로 판단한다.
|
|
|
|
|
*/
|
|
|
|
|
if (
|
|
|
|
|
eavesType.includes(prevLine.attributes?.type) &&
|
|
|
|
|
eavesType.includes(nextLine.attributes?.type) &&
|
|
|
|
|
Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)
|
|
|
|
|
) {
|
|
|
|
|
/**
|
|
|
|
|
* 다음라인 방향에 포인트를 확인해서 역방향 ㄷ 모양인지 판단한다.
|
|
|
|
|
* @type {{x: *, y: *}}
|
|
|
|
|
*/
|
|
|
|
|
if (checkWallPolygon.inPolygon(checkPoints)) {
|
|
|
|
|
drawEavesFirstLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
|
|
|
|
|
if (prevLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES && nextLine.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
|
|
|
|
|
if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) {
|
|
|
|
|
/**
|
|
|
|
|
* 다음라인 방향에 포인트를 확인해서 역방향 ㄷ 모양인지 판단한다.
|
|
|
|
|
* @type {{x: *, y: *}}
|
|
|
|
|
*/
|
|
|
|
|
if (checkWallPolygon.inPolygon(checkPoints)) {
|
|
|
|
|
drawEavesFirstLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
|
|
|
|
|
} else {
|
|
|
|
|
drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
drawEavesSecondLines.push({ currentBaseLine, prevBaseLine, nextBaseLine })
|
|
|
|
|
}
|
|
|
|
|
} else if (gableType.includes(nextLine.attributes?.type) && gableType.includes(prevLine.attributes?.type)) {
|
|
|
|
|
if (Big(prevAngle).minus(Big(nextAngle)).abs().eq(180)) {
|
|
|
|
|
@ -950,6 +623,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LINE_TYPE.WALLLINE.HIPANDGABLE === currentLine.attributes?.type) {
|
|
|
|
|
drawHipAndGableFirst.push({ currentBaseLine, prevBaseLine, nextBaseLine })
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
drawEavesFirstLines.sort((a, b) => a.currentBaseLine.size - b.currentBaseLine.size)
|
|
|
|
|
@ -968,14 +645,12 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
/** 용마루의 갯수*/
|
|
|
|
|
let baseRidgeCount = 0
|
|
|
|
|
|
|
|
|
|
// console.log('drawGableFirstLines :', drawGableFirstLines)
|
|
|
|
|
// console.log('drawGableSecondLines :', drawGableSecondLines)
|
|
|
|
|
// console.log('drawEavesFirstLines :', drawEavesFirstLines)
|
|
|
|
|
// console.log('drawEavesSecondLines :', drawEavesSecondLines)
|
|
|
|
|
// console.log('drawGableRidgeFirst : ', drawGableRidgeFirst)
|
|
|
|
|
// console.log('drawGableRidgeSecond : ', drawGableRidgeSecond)
|
|
|
|
|
// console.log('drawGablePolygonFirst :', drawGablePolygonFirst)
|
|
|
|
|
// console.log('drawGablePolygonSecond :', drawGablePolygonSecond)
|
|
|
|
|
console.log('drawEavesFirstLines :', drawEavesFirstLines)
|
|
|
|
|
console.log('drawEavesSecondLines :', drawEavesSecondLines)
|
|
|
|
|
console.log('drawGableRidgeFirst: ', drawGableRidgeFirst)
|
|
|
|
|
console.log('drawGableRidgeSecond:', drawGableRidgeSecond)
|
|
|
|
|
console.log('drawGablePolygonFirst :', drawGablePolygonFirst)
|
|
|
|
|
console.log('drawGablePolygonSecond :', drawGablePolygonSecond)
|
|
|
|
|
|
|
|
|
|
/** 박공지붕에서 파생되는 마루를 그린다. ㄷ 형태*/
|
|
|
|
|
drawGableRidgeFirst.forEach((current) => {
|
|
|
|
|
@ -1345,7 +1020,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidX.toNumber() })) {
|
|
|
|
|
if (!roof.inPolygon({ x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() })) {
|
|
|
|
|
const checkEdge = {
|
|
|
|
|
vertex1: { x: oppositeMidX.toNumber(), y: oppositeMidY.toNumber() },
|
|
|
|
|
vertex2: { x: currentMidX.toNumber(), y: currentMidY.toNumber() },
|
|
|
|
|
@ -2210,12 +1885,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
|
|
|
|
const intersection = edgesIntersection(checkEdge, lineEdge)
|
|
|
|
|
if (intersection) {
|
|
|
|
|
intersection.x = Math.round(intersection.x)
|
|
|
|
|
intersection.y = Math.round(intersection.y)
|
|
|
|
|
if (
|
|
|
|
|
(line.x1 <= intersection.x && intersection.x <= line.x2 && line.y1 <= intersection.y && intersection.y <= line.y2) ||
|
|
|
|
|
(line.x2 <= intersection.x && intersection.x <= line.x1 && line.y2 <= intersection.y && intersection.y <= line.y1)
|
|
|
|
|
) {
|
|
|
|
|
if (isPointOnLine(line, intersection)) {
|
|
|
|
|
intersectionRoofs.push({
|
|
|
|
|
line,
|
|
|
|
|
intersection,
|
|
|
|
|
@ -2235,12 +1905,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
|
|
|
|
const intersection = edgesIntersection(checkEdge, lineEdge)
|
|
|
|
|
if (intersection) {
|
|
|
|
|
intersection.x = Math.round(intersection.x)
|
|
|
|
|
intersection.y = Math.round(intersection.y)
|
|
|
|
|
if (
|
|
|
|
|
(line.x1 <= intersection.x && intersection.x <= line.x2 && line.y1 <= intersection.y && intersection.y <= line.y2) ||
|
|
|
|
|
(line.x2 <= intersection.x && intersection.x <= line.x1 && line.y2 <= intersection.y && intersection.y <= line.y1)
|
|
|
|
|
) {
|
|
|
|
|
if (isPointOnLine(line, intersection)) {
|
|
|
|
|
intersectionRoofs.push({
|
|
|
|
|
line,
|
|
|
|
|
intersection,
|
|
|
|
|
@ -2259,29 +1924,21 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let prevRoofLine, nextRoofLine
|
|
|
|
|
const roofEdge = {
|
|
|
|
|
vertex1: { x: roofX1.toNumber(), y: roofY1.toNumber() },
|
|
|
|
|
vertex2: { x: roofX2.toNumber(), y: roofY2.toNumber() },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
roof.lines
|
|
|
|
|
.filter((line) => (currentVectorX === 0 ? line.y1 === line.y2 : line.x1 === line.x2))
|
|
|
|
|
.forEach((line) => {
|
|
|
|
|
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
|
|
|
|
const intersection = edgesIntersection(roofEdge, lineEdge)
|
|
|
|
|
if (intersection) {
|
|
|
|
|
intersection.x = Math.round(intersection.x)
|
|
|
|
|
intersection.y = Math.round(intersection.y)
|
|
|
|
|
if (
|
|
|
|
|
(line.x1 <= intersection.x && intersection.x <= line.x2 && line.y1 <= intersection.y && intersection.y <= line.y2) ||
|
|
|
|
|
(line.x2 <= intersection.x && intersection.x <= line.x1 && line.y2 <= intersection.y && intersection.y <= line.y1)
|
|
|
|
|
) {
|
|
|
|
|
if (roofX1.eq(intersection.x) && roofY1.eq(intersection.y)) {
|
|
|
|
|
prevRoofLine = line
|
|
|
|
|
}
|
|
|
|
|
if (roofX2.eq(intersection.x) && roofY2.eq(intersection.y)) {
|
|
|
|
|
nextRoofLine = line
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
(roofX1.minus(line.x1).abs().lte(1) && roofY1.minus(line.y1).abs().lte(1)) ||
|
|
|
|
|
(roofX1.minus(line.x2).abs().lte(1) && roofY1.minus(line.y2).abs().lte(1))
|
|
|
|
|
) {
|
|
|
|
|
prevRoofLine = line
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
(roofX2.minus(line.x1).abs().lte(1) && roofY2.minus(line.y1).abs().lte(1)) ||
|
|
|
|
|
(roofX2.minus(line.x2).abs().lte(1) && roofY2.minus(line.y2).abs().lte(1))
|
|
|
|
|
) {
|
|
|
|
|
nextRoofLine = line
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
const prevRoofEdge = {
|
|
|
|
|
@ -2299,18 +1956,19 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
const nextIs = edgesIntersection(nextRoofEdge, ridgeEdge)
|
|
|
|
|
if (
|
|
|
|
|
prevIs &&
|
|
|
|
|
((ridgeEdge.vertex1.x === prevIs.x && ridgeEdge.vertex1.y === prevIs.y) ||
|
|
|
|
|
(ridgeEdge.vertex2.x === prevIs.x && ridgeEdge.vertex2.y === prevIs.y))
|
|
|
|
|
((Math.abs(ridgeEdge.vertex1.x - prevIs.x) < 1 && Math.abs(ridgeEdge.vertex1.y - prevIs.y) < 1) ||
|
|
|
|
|
(Math.abs(ridgeEdge.vertex2.x - prevIs.x) < 1 && Math.abs(ridgeEdge.vertex2.y - prevIs.y) < 1))
|
|
|
|
|
) {
|
|
|
|
|
prevLineRidges.push({
|
|
|
|
|
ridge,
|
|
|
|
|
size: calcLinePlaneSize({ x1: roofX1, y1: roofY1, x2: prevIs.x, y2: prevIs.y }),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
nextIs &&
|
|
|
|
|
((ridgeEdge.vertex1.x === nextIs.x && ridgeEdge.vertex1.y === nextIs.y) ||
|
|
|
|
|
(ridgeEdge.vertex2.x === nextIs.x && ridgeEdge.vertex2.y === nextIs.y))
|
|
|
|
|
((Math.abs(ridgeEdge.vertex1.x - nextIs.x) < 1 && Math.abs(ridgeEdge.vertex1.y - nextIs.y) < 1) ||
|
|
|
|
|
(Math.abs(ridgeEdge.vertex2.x - nextIs.x) < 1 && Math.abs(ridgeEdge.vertex2.y - nextIs.y) < 1))
|
|
|
|
|
) {
|
|
|
|
|
nextLineRidges.push({
|
|
|
|
|
ridge,
|
|
|
|
|
@ -3858,7 +3516,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/** baseLines에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산*/
|
|
|
|
|
/** baseLines 에서 가장 작은 x1과 가장 큰 x1, 가장 작은 y1과 가장 큰 y1을 계산*/
|
|
|
|
|
let minX = Infinity
|
|
|
|
|
let maxX = -Infinity
|
|
|
|
|
let minY = Infinity
|
|
|
|
|
@ -5669,7 +5327,7 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
) {
|
|
|
|
|
checkRidgeLine = { x1: current.x, y1: current.y, x2: point.x, y2: point.y }
|
|
|
|
|
}
|
|
|
|
|
/** 대각선인 경우 hip확인*/
|
|
|
|
|
/** 대각선인 경우 hip 확인*/
|
|
|
|
|
const hipX = Big(current.x).minus(Big(point.x)).abs()
|
|
|
|
|
const hipY = Big(current.y).minus(Big(point.y)).abs()
|
|
|
|
|
if (hipX.eq(hipY) && hipX.gt(0) && hipY.gt(0)) {
|
|
|
|
|
@ -5822,11 +5480,10 @@ export const drawRidgeRoof = (roofId, canvas, textMode) => {
|
|
|
|
|
canvas.renderAll()
|
|
|
|
|
roof.innerLines = uniqueInnerLines
|
|
|
|
|
|
|
|
|
|
/*drawRidge(roof, canvas, textMode)
|
|
|
|
|
drawHips(roof, canvas, textMode)
|
|
|
|
|
connectLinePoint(roof, canvas, textMode)
|
|
|
|
|
modifyRidge(roof, canvas, textMode)
|
|
|
|
|
drawCenterLine(roof, canvas, textMode)*/
|
|
|
|
|
// modifyRidge(roof, canvas, textMode)
|
|
|
|
|
/*
|
|
|
|
|
drawCenterLine(roof, canvas, textMode)
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|