동일라벨
This commit is contained in:
parent
645e8b344d
commit
c221515744
@ -189,9 +189,14 @@ export const useLine = () => {
|
|||||||
actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)),
|
actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)),
|
||||||
}
|
}
|
||||||
} else if (isDiagonal) {
|
} else if (isDiagonal) {
|
||||||
|
// [face 비대칭 보정 2026-04-30] 같은 hip 가 인접 두 face 에서 다른 축(yLength vs xLength)
|
||||||
|
// 으로 계산되어 좌표 round drift 가 actualSize 라벨에 1mm 차로 노출(예: 5048 vs 5049).
|
||||||
|
// axis 평균을 써서 양 face 가 동일값을 산출하도록 통일.
|
||||||
const yLength = Math.abs(y2 - y1) * 10
|
const yLength = Math.abs(y2 - y1) * 10
|
||||||
|
const xLength = Math.abs(x2 - x1) * 10
|
||||||
|
const axisLength = (yLength + xLength) / 2
|
||||||
|
|
||||||
const h = yLength * Math.tan(getDegreeByChon(pitch) * (Math.PI / 180))
|
const h = axisLength * Math.tan(getDegreeByChon(pitch) * (Math.PI / 180))
|
||||||
|
|
||||||
const actualSize = Math.sqrt(h ** 2 + lineLength ** 2)
|
const actualSize = Math.sqrt(h ** 2 + lineLength ** 2)
|
||||||
line.attributes = { ...line.attributes, actualSize: actualSize }
|
line.attributes = { ...line.attributes, actualSize: actualSize }
|
||||||
@ -203,9 +208,12 @@ export const useLine = () => {
|
|||||||
actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)),
|
actualSize: calcLineActualSizeByLineLength(lineLength, getDegreeByChon(pitch)),
|
||||||
}
|
}
|
||||||
} else if (isDiagonal) {
|
} else if (isDiagonal) {
|
||||||
|
// [face 비대칭 보정 2026-04-30] south/north 분기와 동일하게 axis 평균 사용.
|
||||||
|
const yLength = Math.abs(y2 - y1) * 10
|
||||||
const xLength = Math.abs(x2 - x1) * 10
|
const xLength = Math.abs(x2 - x1) * 10
|
||||||
|
const axisLength = (yLength + xLength) / 2
|
||||||
|
|
||||||
const h = xLength * Math.tan(getDegreeByChon(pitch) * (Math.PI / 180))
|
const h = axisLength * Math.tan(getDegreeByChon(pitch) * (Math.PI / 180))
|
||||||
|
|
||||||
const actualSize = Math.sqrt(h ** 2 + lineLength ** 2)
|
const actualSize = Math.sqrt(h ** 2 + lineLength ** 2)
|
||||||
line.attributes = { ...line.attributes, actualSize: actualSize }
|
line.attributes = { ...line.attributes, actualSize: actualSize }
|
||||||
|
|||||||
@ -42,6 +42,90 @@ export function useText() {
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
// [hip 라벨 cross-display 통일 2026-04-30 by Claude]
|
||||||
|
//
|
||||||
|
// 배경:
|
||||||
|
// 좌우대칭 hip(대각선) 라인의 라벨이 0.5mm 차이로 갈리는 케이스 발생
|
||||||
|
// (예: 좌측 5048.5 / 우측 5048).
|
||||||
|
//
|
||||||
|
// 원인:
|
||||||
|
// 1) polygon split / ridge intersection 단계 부동소수점 연산
|
||||||
|
// → QLine.js:23 toFixed(1) 0.1mm 단위 절단 → 좌우 hip 좌표가 0.1mm 차
|
||||||
|
// 2) useLine.js setActualSize 의 axisLength * tan + sqrt 계산에서
|
||||||
|
// 좌표 0.1mm 차가 ×10 으로 1mm 차로 증폭
|
||||||
|
// 3) 마지막 `Math.round(actualSize * 2) / 2` (0.5mm 단위) boundary 에서 갈림
|
||||||
|
// → 한쪽은 5048.0, 한쪽은 5048.5 로 결정
|
||||||
|
// 4) planeSize 도 usePolygon.js 의 _equalizeIfNearSymmetric([avg, avg])
|
||||||
|
// 경로에서 0.5mm 단위 값이 만들어질 수 있음 (corridorDimension 모드에 영향)
|
||||||
|
//
|
||||||
|
// 수정 방침:
|
||||||
|
// - **표시 레이어 (lengthText.text) 만 보정**.
|
||||||
|
// - line.attributes.actualSize / line.attributes.planeSize 는 절대 안 건드림.
|
||||||
|
// → 다운스트림 read 경로 (라인 분할 비율 / 확장라인 병합 / 모듈배치 shape
|
||||||
|
// 상속 / JSON 저장 / DB / 복제 플랜) 영향 0.
|
||||||
|
//
|
||||||
|
// 처리:
|
||||||
|
// - 대각선 hip 라벨끼리 묶어서, 표시값이 ±2mm 이내이면 정수 round 한
|
||||||
|
// 공통값으로 스냅 (5048.5/5048 → 둘 다 5049 또는 5048).
|
||||||
|
// - corridorDimension / realDimension 모드 모두 적용.
|
||||||
|
// - noneDimension 모드는 빈 문자열이라 패스.
|
||||||
|
//
|
||||||
|
// 추후 근본 수정 (다른 개발자 검토 필요):
|
||||||
|
// - QLine.js:23 toFixed(1) → toFixed(2) 정밀도 상향 (영향 범위 넓어 별건)
|
||||||
|
// - skeleton-utils.js getLineIntersection 결과 좌표 round
|
||||||
|
// - useLine.js setActualSize 마지막 round 단위 변경 (0.5 → 1.0)
|
||||||
|
// 위 근본수정이 들어가면 이 보정 코드는 제거 가능.
|
||||||
|
//
|
||||||
|
// 메모리: feedback_display_vs_internal_values.md 참고.
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
if (column === 'corridorDimension' || column === 'realDimension') {
|
||||||
|
// 대각선(hip) lengthText 추출.
|
||||||
|
// lengthText 객체는 QPolygon.js:712-734 에서 minX/maxX/minY/maxY 로 부모 라인의
|
||||||
|
// 바운딩박스를 저장. 둘 다 양수 차이 = 대각선.
|
||||||
|
const hipTexts = lengthTexts.filter((obj) => {
|
||||||
|
const dx = (obj.maxX ?? 0) - (obj.minX ?? 0)
|
||||||
|
const dy = (obj.maxY ?? 0) - (obj.minY ?? 0)
|
||||||
|
return dx > 0.5 && dy > 0.5
|
||||||
|
})
|
||||||
|
|
||||||
|
if (hipTexts.length >= 2) {
|
||||||
|
// 현재 표시 텍스트를 숫자로 파싱.
|
||||||
|
const items = hipTexts
|
||||||
|
.map((obj) => ({ obj, value: parseFloat(obj.text) }))
|
||||||
|
.filter((item) => !isNaN(item.value))
|
||||||
|
|
||||||
|
// 그룹화: 표시값이 ±TOLERANCE mm 이내면 동일 그룹.
|
||||||
|
// TOLERANCE=2 는 0.5 단위 round drift + sqrt fp 노이즈 흡수.
|
||||||
|
// 대칭 hip 들의 정상 길이차 (예: 다른 지붕면의 hip) 보다는 작아야 함.
|
||||||
|
const TOLERANCE = 2
|
||||||
|
const groups = []
|
||||||
|
for (const item of items) {
|
||||||
|
const matched = groups.find((g) => Math.abs(g.representative - item.value) <= TOLERANCE)
|
||||||
|
if (matched) {
|
||||||
|
matched.items.push(item)
|
||||||
|
// 그룹 대표값은 첫 항목 값 유지 (안정적인 클러스터링).
|
||||||
|
} else {
|
||||||
|
groups.push({ representative: item.value, items: [item] })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 각 그룹의 멤버가 2개 이상이면 정수 round 평균값으로 통일.
|
||||||
|
// 1개 그룹은 단독 hip 이므로 보정 불필요.
|
||||||
|
for (const group of groups) {
|
||||||
|
if (group.items.length < 2) continue
|
||||||
|
const avg = group.items.reduce((s, i) => s + i.value, 0) / group.items.length
|
||||||
|
const unified = Math.round(avg).toString()
|
||||||
|
for (const item of group.items) {
|
||||||
|
// text 만 set. obj.actualSize / obj.planeSize 는 그대로.
|
||||||
|
item.obj.set({ text: unified })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user