dev #494
@ -2426,9 +2426,20 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
||||
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: midPoint.x, y: midPoint.y },
|
||||
end: { x: intersect.x, y: intersect.y },
|
||||
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',
|
||||
@ -2559,7 +2570,169 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
||||
})
|
||||
})
|
||||
//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. 케라바 판단, 케라바는 양옆이 처마여야 한다.
|
||||
gables.forEach((currentLine) => {})
|
||||
|
||||
//각 선분의 교차점을 찾아 선을 그린다.
|
||||
const MAX_ITERATIONS = 1000 //무한루프 방지
|
||||
@ -2878,17 +3051,19 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
||||
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 (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))
|
||||
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)
|
||||
}
|
||||
proceedAnalysis.push(currentLine, partnerLine)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -2903,6 +3078,106 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
||||
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user