중간 저장(반박공지붕 추가)
This commit is contained in:
parent
a201d65ebe
commit
6c0cc73cb8
@ -2426,9 +2426,20 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
intersections.sort((a, b) => a.distance - b.distance)
|
intersections.sort((a, b) => a.distance - b.distance)
|
||||||
if (intersections.length > 0) {
|
if (intersections.length > 0) {
|
||||||
const intersect = intersections[0].intersect
|
const intersect = intersections[0].intersect
|
||||||
|
const point = [midPoint.x, midPoint.y, intersect.x, intersect.y]
|
||||||
|
|
||||||
|
//마루가 최대로 뻗어나갈수 있는 포인트. null일때는 맞은편 지붕선 까지로 판단한다.
|
||||||
|
const drivePoint = getRidgeDrivePoints(point, prevLine, nextLine, baseLines, canvas)
|
||||||
|
|
||||||
|
console.log('drivePoint : ', drivePoint)
|
||||||
|
if (drivePoint) {
|
||||||
|
point[2] = drivePoint.x
|
||||||
|
point[3] = drivePoint.y
|
||||||
|
}
|
||||||
|
|
||||||
linesAnalysis.push({
|
linesAnalysis.push({
|
||||||
start: { x: midPoint.x, y: midPoint.y },
|
start: { x: point[0], y: point[1] },
|
||||||
end: { x: intersect.x, y: intersect.y },
|
end: { x: point[2], y: point[3] },
|
||||||
left: baseLines.findIndex((line) => line === prevLine),
|
left: baseLines.findIndex((line) => line === prevLine),
|
||||||
right: baseLines.findIndex((line) => line === nextLine),
|
right: baseLines.findIndex((line) => line === nextLine),
|
||||||
type: 'ridge',
|
type: 'ridge',
|
||||||
@ -2559,7 +2570,169 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
//4. 반절처(반절마루) 판단, 반절마루는 양옆이 처마여야 한다.
|
//4. 반절처(반절마루) 판단, 반절마루는 양옆이 처마여야 한다.
|
||||||
|
jerkinHeads.forEach((currentLine) => {
|
||||||
|
let prevLine, nextLine
|
||||||
|
baseLines.forEach((baseLine, index) => {
|
||||||
|
if (baseLine === currentLine) {
|
||||||
|
nextLine = baseLines[(index + 1) % baseLines.length]
|
||||||
|
prevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//양옆이 처마가 아닐때 패스
|
||||||
|
if (prevLine.attributes.type !== LINE_TYPE.WALLLINE.EAVES || nextLine.attributes.type !== LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const analyze = analyzeLine(currentLine)
|
||||||
|
const roofPoints = [analyze.roofLine.x1, analyze.roofLine.y1, analyze.roofLine.x2, analyze.roofLine.y2]
|
||||||
|
|
||||||
|
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) {
|
||||||
|
//반절마루 생성불가이므로 지붕선만 추가하고 끝냄
|
||||||
|
innerLines.push(drawRoofLine(roofPoints, canvas, roof, textMode))
|
||||||
|
} else {
|
||||||
|
const midX = (roofPoints[0] + roofPoints[2]) / 2
|
||||||
|
const midY = (roofPoints[1] + roofPoints[3]) / 2
|
||||||
|
|
||||||
|
const currentDegree = getDegreeByChon(currentLine.attributes.pitch)
|
||||||
|
const prevDegree = getDegreeByChon(prevLine.attributes.pitch)
|
||||||
|
const nextDegree = getDegreeByChon(nextLine.attributes.pitch)
|
||||||
|
const gableWidth = currentLine.attributes.width
|
||||||
|
|
||||||
|
const roofVector = { x: Math.sign(roofPoints[2] - roofPoints[0]), y: Math.sign(roofPoints[3] - roofPoints[1]) }
|
||||||
|
const roofDx = roofPoints[0] - roofPoints[2]
|
||||||
|
const roofDy = roofPoints[1] - roofPoints[3]
|
||||||
|
const roofLength = Math.sqrt(roofDx * roofDx + roofDy * roofDy)
|
||||||
|
const lineLength = (roofLength - gableWidth) / 2
|
||||||
|
const jerkinPoints = []
|
||||||
|
jerkinPoints.push(
|
||||||
|
{ x: roofPoints[0], y: roofPoints[1] },
|
||||||
|
{ x: roofPoints[0] + roofVector.x * lineLength, y: roofPoints[1] + roofVector.y * lineLength },
|
||||||
|
)
|
||||||
|
jerkinPoints.push({ x: jerkinPoints[1].x + roofVector.x * gableWidth, y: jerkinPoints[1].y + roofVector.y * gableWidth })
|
||||||
|
jerkinPoints.push({ x: jerkinPoints[2].x + roofVector.x * lineLength, y: jerkinPoints[2].y + roofVector.y * lineLength })
|
||||||
|
|
||||||
|
if (gableWidth >= roofLength) {
|
||||||
|
innerLines.push(drawRoofLine(roofPoints, canvas, roof, textMode))
|
||||||
|
} else if (jerkinPoints.length === 4) {
|
||||||
|
const gablePoint1 = [jerkinPoints[0].x, jerkinPoints[0].y, jerkinPoints[1].x, jerkinPoints[1].y]
|
||||||
|
const gablePoint2 = [jerkinPoints[1].x, jerkinPoints[1].y, jerkinPoints[2].x, jerkinPoints[2].y]
|
||||||
|
const gablePoint3 = [jerkinPoints[2].x, jerkinPoints[2].y, jerkinPoints[3].x, jerkinPoints[3].y]
|
||||||
|
const gableLength1 = Math.sqrt(Math.pow(gablePoint1[2] - gablePoint1[0], 2) + Math.pow(gablePoint1[3] - gablePoint1[1], 2))
|
||||||
|
const gableLength2 = Math.sqrt(Math.pow(gablePoint2[2] - gablePoint2[0], 2) + Math.pow(gablePoint2[3] - gablePoint2[1], 2))
|
||||||
|
const gableLength3 = Math.sqrt(Math.pow(gablePoint3[2] - gablePoint3[0], 2) + Math.pow(gablePoint3[3] - gablePoint3[1], 2))
|
||||||
|
if (gableLength1 >= 1) {
|
||||||
|
innerLines.push(drawHipLine(gablePoint1, canvas, roof, textMode, null, prevDegree, prevDegree))
|
||||||
|
}
|
||||||
|
if (gableLength2 >= 1) {
|
||||||
|
innerLines.push(drawRoofLine(gablePoint2, canvas, roof, textMode))
|
||||||
|
}
|
||||||
|
if (gableLength3 >= 1) {
|
||||||
|
innerLines.push(drawHipLine(gablePoint3, canvas, roof, textMode, null, nextDegree, nextDegree))
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentRoofLine = analyze.roofLine
|
||||||
|
let prevRoofLine, nextRoofLine
|
||||||
|
roof.lines.forEach((roofLine, index) => {
|
||||||
|
if (roofLine === currentRoofLine) {
|
||||||
|
nextRoofLine = roof.lines[(index + 1) % roof.lines.length]
|
||||||
|
prevRoofLine = roof.lines[(index - 1 + roof.lines.length) % roof.lines.length]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/** 이전, 다음라인의 사잇각의 vector를 구한다. */
|
||||||
|
let prevVector = getHalfAngleVector(prevRoofLine, currentRoofLine)
|
||||||
|
let nextVector = getHalfAngleVector(currentRoofLine, nextRoofLine)
|
||||||
|
|
||||||
|
/** 이전 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
|
||||||
|
const prevCheckPoint = {
|
||||||
|
x: currentRoofLine.x1 + prevVector.x * 10,
|
||||||
|
y: currentRoofLine.y1 + prevVector.y * 10,
|
||||||
|
}
|
||||||
|
/** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
|
||||||
|
const nextCheckPoint = {
|
||||||
|
x: currentRoofLine.x2 + nextVector.x * 10,
|
||||||
|
y: currentRoofLine.y2 + nextVector.y * 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
let prevHipVector, nextHipVector
|
||||||
|
|
||||||
|
if (roof.inPolygon(prevCheckPoint)) {
|
||||||
|
prevHipVector = { x: prevVector.x, y: prevVector.y }
|
||||||
|
} else {
|
||||||
|
prevHipVector = { x: -prevVector.x, y: -prevVector.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 다음 라인과의 사이 추녀마루의 각도를 확인한다, 각도가 지붕안쪽으로 향하지 않을때 반대로 처리한다.*/
|
||||||
|
if (roof.inPolygon(nextCheckPoint)) {
|
||||||
|
nextHipVector = { x: nextVector.x, y: nextVector.y }
|
||||||
|
} else {
|
||||||
|
nextHipVector = { x: -nextVector.x, y: -nextVector.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevHipEdge = {
|
||||||
|
vertex1: { x: gablePoint2[0], y: gablePoint2[1] },
|
||||||
|
vertex2: { x: gablePoint2[0] + prevHipVector.x * gableWidth, y: gablePoint2[1] + prevHipVector.y * gableWidth },
|
||||||
|
}
|
||||||
|
const nextHipEdge = {
|
||||||
|
vertex1: { x: gablePoint2[2], y: gablePoint2[3] },
|
||||||
|
vertex2: { x: gablePoint2[2] + nextHipVector.x * gableWidth, y: gablePoint2[3] + nextHipVector.y * gableWidth },
|
||||||
|
}
|
||||||
|
|
||||||
|
const hipIntersection = edgesIntersection(prevHipEdge, nextHipEdge)
|
||||||
|
if (hipIntersection) {
|
||||||
|
const prevHipPoint = [prevHipEdge.vertex1.x, prevHipEdge.vertex1.y, hipIntersection.x, hipIntersection.y]
|
||||||
|
const nextHipPoint = [nextHipEdge.vertex1.x, nextHipEdge.vertex1.y, hipIntersection.x, hipIntersection.y]
|
||||||
|
innerLines.push(drawHipLine(prevHipPoint, canvas, roof, textMode, null, currentDegree, currentDegree))
|
||||||
|
innerLines.push(drawHipLine(nextHipPoint, canvas, roof, textMode, null, currentDegree, currentDegree))
|
||||||
|
|
||||||
|
const midPoint = { x: hipIntersection.x, y: hipIntersection.y }
|
||||||
|
const checkEdge = {
|
||||||
|
vertex1: { x: midPoint.x, y: midPoint.y },
|
||||||
|
vertex2: { x: midPoint.x + -analyze.roofVector.x * 10000, y: midPoint.y + -analyze.roofVector.y * 10000 },
|
||||||
|
}
|
||||||
|
const intersections = []
|
||||||
|
roof.lines
|
||||||
|
.filter((line) => line !== currentRoofLine)
|
||||||
|
.forEach((line) => {
|
||||||
|
const lineEdge = { vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } }
|
||||||
|
const intersect = edgesIntersection(lineEdge, checkEdge)
|
||||||
|
if (intersect && isPointOnLineNew(line, intersect)) {
|
||||||
|
const distance = Math.sqrt(Math.pow(midPoint.x - intersect.x, 2) + Math.pow(midPoint.y - intersect.y, 2))
|
||||||
|
intersections.push({ intersect, distance })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
intersections.sort((a, b) => a.distance - b.distance)
|
||||||
|
if (intersections.length > 0) {
|
||||||
|
const intersect = intersections[0].intersect
|
||||||
|
const point = [midPoint.x, midPoint.y, intersect.x, intersect.y]
|
||||||
|
|
||||||
|
//마루가 최대로 뻗어나갈수 있는 포인트. null일때는 맞은편 지붕선 까지로 판단한다.
|
||||||
|
const drivePoint = getRidgeDrivePoints(point, prevLine, nextLine, baseLines, canvas)
|
||||||
|
|
||||||
|
console.log('drivePoint : ', drivePoint)
|
||||||
|
if (drivePoint) {
|
||||||
|
point[2] = drivePoint.x
|
||||||
|
point[3] = drivePoint.y
|
||||||
|
}
|
||||||
|
|
||||||
|
linesAnalysis.push({
|
||||||
|
start: { x: point[0], y: point[1] },
|
||||||
|
end: { x: point[2], y: point[3] },
|
||||||
|
left: baseLines.findIndex((line) => line === prevLine),
|
||||||
|
right: baseLines.findIndex((line) => line === nextLine),
|
||||||
|
type: 'ridge',
|
||||||
|
degree: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
//5. 케라바 판단, 케라바는 양옆이 처마여야 한다.
|
//5. 케라바 판단, 케라바는 양옆이 처마여야 한다.
|
||||||
|
gables.forEach((currentLine) => {})
|
||||||
|
|
||||||
//각 선분의 교차점을 찾아 선을 그린다.
|
//각 선분의 교차점을 찾아 선을 그린다.
|
||||||
const MAX_ITERATIONS = 1000 //무한루프 방지
|
const MAX_ITERATIONS = 1000 //무한루프 방지
|
||||||
@ -2878,17 +3051,19 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
if (count === 1) points.push(point)
|
if (count === 1) points.push(point)
|
||||||
})
|
})
|
||||||
|
|
||||||
const length = Math.sqrt((points[0].x - points[1].x) ** 2 + (points[0].y - points[1].y) ** 2)
|
if (points.length === 2) {
|
||||||
if (length < EPSILON) return
|
const length = Math.sqrt((points[0].x - points[1].x) ** 2 + (points[0].y - points[1].y) ** 2)
|
||||||
const isDiagonal = Math.abs(points[0].x - points[1].x) >= 1 && Math.abs(points[0].y - points[1].y) >= 1
|
if (length < EPSILON) return
|
||||||
if (isDiagonal) {
|
const isDiagonal = Math.abs(points[0].x - points[1].x) >= 1 && Math.abs(points[0].y - points[1].y) >= 1
|
||||||
innerLines.push(
|
if (isDiagonal) {
|
||||||
drawHipLine([points[0].x, points[0].y, points[1].x, points[1].y], canvas, roof, textMode, null, currentDegree, currentDegree),
|
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))
|
} else {
|
||||||
|
innerLines.push(drawRidgeLine([points[0].x, points[0].y, points[1].x, points[1].y], canvas, roof, textMode))
|
||||||
|
}
|
||||||
|
proceedAnalysis.push(currentLine, partnerLine)
|
||||||
}
|
}
|
||||||
proceedAnalysis.push(currentLine, partnerLine)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -2903,6 +3078,106 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
|||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param testPoint
|
||||||
|
* @param prevLine
|
||||||
|
* @param nextLine
|
||||||
|
* @param baseLines
|
||||||
|
* @param canvas
|
||||||
|
*/
|
||||||
|
const getRidgeDrivePoints = (testPoint = [], prevLine, nextLine, baseLines, canvas) => {
|
||||||
|
if (prevLine.attributes.type !== LINE_TYPE.WALLLINE.EAVES && nextLine.attributes.type !== LINE_TYPE.WALLLINE.EAVES) return null
|
||||||
|
let prevPoint = null,
|
||||||
|
nextPoint = null
|
||||||
|
|
||||||
|
const baseLinePoints = baseLines.map((line) => ({ x: line.x1, y: line.y1 }))
|
||||||
|
const checkWallPolygon = new QPolygon(baseLinePoints, {})
|
||||||
|
const checkEdge = { vertex1: { x: testPoint[0], y: testPoint[1] }, vertex2: { x: testPoint[2], y: testPoint[3] } }
|
||||||
|
|
||||||
|
if (prevLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
const index = baseLines.findIndex((line) => line === prevLine)
|
||||||
|
const beforePrevLine = baseLines[(index - 1 + baseLines.length) % baseLines.length]
|
||||||
|
if (!beforePrevLine || beforePrevLine.attributes.type !== LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
prevPoint = null
|
||||||
|
} else {
|
||||||
|
let prevVector = getHalfAngleVector(beforePrevLine, prevLine)
|
||||||
|
|
||||||
|
const prevCheckPoint = {
|
||||||
|
x: prevLine.x1 + prevVector.x * 10,
|
||||||
|
y: prevLine.y1 + prevVector.y * 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
let prevHipVector
|
||||||
|
|
||||||
|
if (checkWallPolygon.inPolygon(prevCheckPoint)) {
|
||||||
|
prevHipVector = { x: prevVector.x, y: prevVector.y }
|
||||||
|
} else {
|
||||||
|
prevHipVector = { x: -prevVector.x, y: -prevVector.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevHipEdge = {
|
||||||
|
vertex1: { x: prevLine.x1, y: prevLine.y1 },
|
||||||
|
vertex2: { x: prevLine.x1 + prevHipVector.x * 10, y: prevLine.y1 + prevHipVector.y * 10 },
|
||||||
|
}
|
||||||
|
|
||||||
|
const intersection = edgesIntersection(prevHipEdge, checkEdge)
|
||||||
|
if (intersection) {
|
||||||
|
const checkVector = { x: Math.sign(prevLine.x1 - testPoint[0]), y: Math.sign(prevLine.y1 - testPoint[1]) }
|
||||||
|
const intersectVector = { x: Math.sign(prevLine.x1 - intersection.x), y: Math.sign(prevLine.y1 - intersection.y) }
|
||||||
|
if (checkVector.x === intersectVector.x && checkVector.y === intersectVector.y) {
|
||||||
|
const distance = Math.sqrt((intersection.x - testPoint[0]) ** 2 + (intersection.y - testPoint[1]) ** 2)
|
||||||
|
prevPoint = { intersection, distance }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextLine.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
const index = baseLines.findIndex((line) => line === nextLine)
|
||||||
|
const afterNextLine = baseLines[(index + 1) % baseLines.length]
|
||||||
|
if (!afterNextLine || afterNextLine.attributes.type !== LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
nextPoint = null
|
||||||
|
} else {
|
||||||
|
let nextVector = getHalfAngleVector(nextLine, afterNextLine)
|
||||||
|
const nextCheckPoint = {
|
||||||
|
x: nextLine.x2 + nextVector.x * 10,
|
||||||
|
y: nextLine.y2 + nextVector.y * 10,
|
||||||
|
}
|
||||||
|
let nextHipVector
|
||||||
|
if (checkWallPolygon.inPolygon(nextCheckPoint)) {
|
||||||
|
nextHipVector = { x: nextVector.x, y: nextVector.y }
|
||||||
|
} else {
|
||||||
|
nextHipVector = { x: -nextVector.x, y: -nextVector.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextHipEdge = {
|
||||||
|
vertex1: { x: nextLine.x2, y: nextLine.y2 },
|
||||||
|
vertex2: { x: nextLine.x2 + nextHipVector.x * 10, y: nextLine.y2 + nextHipVector.y * 10 },
|
||||||
|
}
|
||||||
|
const intersection = edgesIntersection(nextHipEdge, checkEdge)
|
||||||
|
if (intersection) {
|
||||||
|
const checkVector = { x: Math.sign(nextLine.x2 - testPoint[0]), y: Math.sign(nextLine.y2 - testPoint[1]) }
|
||||||
|
const intersectVector = { x: Math.sign(nextLine.x2 - intersection.x), y: Math.sign(nextLine.y2 - intersection.y) }
|
||||||
|
if (checkVector.x === intersectVector.x && checkVector.y === intersectVector.y) {
|
||||||
|
const distance = Math.sqrt((intersection.x - testPoint[0]) ** 2 + (intersection.y - testPoint[1]) ** 2)
|
||||||
|
nextPoint = { intersection, distance }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevPoint && nextPoint) {
|
||||||
|
return prevPoint.distance < nextPoint.distance ? prevPoint.intersection : nextPoint.intersection
|
||||||
|
} else if (prevPoint) {
|
||||||
|
return prevPoint.intersection
|
||||||
|
} else if (nextPoint) {
|
||||||
|
return nextPoint.intersection
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 선분과 선분의 교점을 구한다.
|
* 선분과 선분의 교점을 구한다.
|
||||||
* @param line1Start
|
* @param line1Start
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user