refactor: 처마변 split 로직 splitRoofLinesToInnerLines 공용 함수 추출
[작업내용] : - drawRoofByAttribute 의 인라인 split 블록을 splitRoofLinesToInnerLines 공용 함수로 추출 (변별/용마루 경로 공용) - 분할점 거리순 정렬 버그 수정 (a[1] → a.distance — 분할점 2개 이상에서 정렬이 no-op 이던 문제) - 분할점 끝점 판정을 almostEqual(1e-10) → 끝점과의 유클리드 거리 1px 이내 제외로 변경 (SK 추녀 연장의 부동소수 오차 흡수, 0 길이 조각 생성 방지) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
18abbeb902
commit
1bf5f45b63
@ -5429,7 +5429,35 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
||||
//추가된 하단 지붕 라인 innerLines에 추가.
|
||||
innerLines.push(...downRoofLines)
|
||||
|
||||
//지붕선에 따라 라인추가 작업 처리.
|
||||
//지붕선에 따라 라인추가 작업 처리. (split 공용 함수 — docs §3-1)
|
||||
splitRoofLinesToInnerLines(roof, innerLines, canvas, textMode)
|
||||
|
||||
//지붕 innerLines에 추가.
|
||||
roof.innerLines = innerLines
|
||||
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((object) => object.name === 'check')
|
||||
.forEach((object) => canvas.remove(object))
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
/**
|
||||
* roof.lines(처마 외곽선)를 innerLine 끝점 기준으로 split 해 편집 가능한 innerLine(hip/roofLine)으로 만든다.
|
||||
* 변별/용마루 경로 공용. innerLines 에 결과를 in-place push 하고 반환한다.
|
||||
* (용마루 경로는 추녀 연장 후 호출해야 종점이 처마변 위에 있어 분할점이 잡힌다 — docs §9)
|
||||
* @param {fabric.Object} roof - 대상 지붕 (roof.lines 사용)
|
||||
* @param {Array<QLine>} innerLines - 내부선 배열 (split 결과가 여기에 in-place 추가됨)
|
||||
* @param {fabric.Canvas} canvas
|
||||
* @param {string} textMode
|
||||
* @returns {Array<QLine>} innerLines
|
||||
*/
|
||||
export const splitRoofLinesToInnerLines = (roof, innerLines, canvas, textMode) => {
|
||||
// 분할점이 처마변 끝점(코너)과 이 거리(px) 이내면 분할에서 제외.
|
||||
// SK 추녀 연장이 처마 코너에 닿을 때 ray cast 부동소수 오차(관측 0.02px)로 코너와 미세하게
|
||||
// 어긋나면, 기존 almostEqual(1e-10)은 "끝점 아님"으로 오판 → 0 길이 조각 생성. END_EPS 로 흡수.
|
||||
// 변별 경로의 진짜 분할점은 끝점에서 수백 px 떨어져 있어 영향 없음.
|
||||
const END_EPS = 1.0
|
||||
const innerLinesPoints = []
|
||||
innerLines.forEach((line) => {
|
||||
const hasCoord1 = innerLinesPoints.find((p) => p.x === line.x1 && p.y === line.y1)
|
||||
@ -5464,17 +5492,15 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
||||
if (hasOverlapLine) return
|
||||
|
||||
innerLinesPoints.forEach((point) => {
|
||||
if (
|
||||
isPointOnLineNew(currentLine, point) &&
|
||||
!(almostEqual(currentLine.x1, point.x) && almostEqual(currentLine.y1, point.y)) &&
|
||||
!(almostEqual(currentLine.x2, point.x) && almostEqual(currentLine.y2, point.y))
|
||||
) {
|
||||
const distance = Math.sqrt((point.x - currentLine.x1) ** 2 + (point.y - currentLine.y1) ** 2)
|
||||
splitPoint.push({ point, distance })
|
||||
const distToStart = Math.hypot(point.x - currentLine.x1, point.y - currentLine.y1)
|
||||
const distToEnd = Math.hypot(point.x - currentLine.x2, point.y - currentLine.y2)
|
||||
// 변 위 점이면서 양 끝점(코너)에서 END_EPS 보다 멀 때만 진짜 분할점으로 채택.
|
||||
if (isPointOnLineNew(currentLine, point) && distToStart > END_EPS && distToEnd > END_EPS) {
|
||||
splitPoint.push({ point, distance: distToStart })
|
||||
}
|
||||
})
|
||||
if (splitPoint.length > 0) {
|
||||
splitPoint.sort((a, b) => a[1] - b[1])
|
||||
splitPoint.sort((a, b) => a.distance - b.distance)
|
||||
let startPoint = { x: currentLine.x1, y: currentLine.y1 }
|
||||
for (let i = 0; i < splitPoint.length; i++) {
|
||||
const point = splitPoint[i].point
|
||||
@ -5495,14 +5521,7 @@ export const drawRoofByAttribute = (roofId, canvas, textMode) => {
|
||||
}
|
||||
})
|
||||
|
||||
//지붕 innerLines에 추가.
|
||||
roof.innerLines = innerLines
|
||||
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((object) => object.name === 'check')
|
||||
.forEach((object) => canvas.remove(object))
|
||||
canvas.renderAll()
|
||||
return innerLines
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user