dev #911
@ -368,6 +368,53 @@ export function useEavesGableEdit(id) {
|
||||
break
|
||||
}
|
||||
|
||||
// [KERAB-STATE-DUMP 2026-06-11] A/B타입(가로/세로 케라바) 토글 진입 시점 지붕 상태 진단.
|
||||
// 벽 type 지정은 있는데 내부 skLine 이 0인 "무에서 유" 케이스 파악용 — 사용자 설명 전 사실 수집.
|
||||
// 읽기 전용(좌표/visible/type 만 덤프), 동작 변경 없음. logger 게이트(local 만 출력).
|
||||
{
|
||||
const _dr = canvas
|
||||
.getObjects()
|
||||
.find((o) => o.name === POLYGON_TYPE.ROOF && !o.isFixed && o.id === target.attributes?.roofId)
|
||||
const _r1 = (v) => (typeof v === 'number' ? Math.round(v * 10) / 10 : v)
|
||||
logger.log(
|
||||
'[KERAB-STATE-DUMP] ' +
|
||||
JSON.stringify({
|
||||
uiType: typeRef.current,
|
||||
radio: radioTypeRef.current,
|
||||
target: {
|
||||
type: target.attributes?.type,
|
||||
offset: target.attributes?.offset,
|
||||
x1: _r1(target.x1),
|
||||
y1: _r1(target.y1),
|
||||
x2: _r1(target.x2),
|
||||
y2: _r1(target.y2),
|
||||
},
|
||||
willBecome: attributes?.type,
|
||||
roofId: target.attributes?.roofId,
|
||||
roofFound: !!_dr,
|
||||
points: _dr?.points?.map((p) => ({ x: _r1(p.x), y: _r1(p.y) })),
|
||||
lines: _dr?.lines?.map((l) => ({
|
||||
type: l.attributes?.type,
|
||||
offset: l.attributes?.offset,
|
||||
x1: _r1(l.x1),
|
||||
y1: _r1(l.y1),
|
||||
x2: _r1(l.x2),
|
||||
y2: _r1(l.y2),
|
||||
})),
|
||||
innerCount: (_dr?.innerLines || []).length,
|
||||
innerLines: (_dr?.innerLines || []).map((il) => ({
|
||||
lineName: il.lineName,
|
||||
type: il.attributes?.type,
|
||||
visible: il.visible !== false,
|
||||
x1: _r1(il.x1),
|
||||
y1: _r1(il.y1),
|
||||
x2: _r1(il.x2),
|
||||
y2: _r1(il.y2),
|
||||
})),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// [2240 KERAB-NOOP-REKLICK 2026-05-19] 같은 type 으로의 재클릭은 무동작.
|
||||
// - 케라바→케라바, 처마→처마 등. 기존 rebuild 흐름이 다시 돌면 패턴 상태
|
||||
// (ridge/half-label/orphan ext 정리)를 망가뜨림.
|
||||
@ -1854,36 +1901,17 @@ export function useEavesGableEdit(id) {
|
||||
wallHit = ip
|
||||
}
|
||||
}
|
||||
let ridgeStop = null
|
||||
let ridgeT = Infinity
|
||||
// [KERAB-VALLEY-EXT-RIDGE-STOP 2026-05-29] 룰 1: 원래 ridge 만 stop (roof 측 post 경로).
|
||||
for (const il of roof.innerLines || []) {
|
||||
if (!il || il.visible === false) continue
|
||||
if (il.name !== LINE_TYPE.SUBLINE.RIDGE) continue
|
||||
if (il.lineName !== 'ridge') continue
|
||||
const ip = lineLineIntersection(start, rayEnd, { x: il.x1, y: il.y1 }, { x: il.x2, y: il.y2 })
|
||||
if (!ip) continue
|
||||
if (!isOnSegV(ip, il.x1, il.y1, il.x2, il.y2)) continue
|
||||
const t = (ip.x - start.x) * ux + (ip.y - start.y) * uy
|
||||
if (t < 0.5) continue
|
||||
if (wallT !== Infinity && t > wallT + 0.5) continue
|
||||
if (t < ridgeT) {
|
||||
ridgeT = t
|
||||
ridgeStop = ip
|
||||
}
|
||||
}
|
||||
if (ridgeStop) {
|
||||
bestStop = ridgeStop
|
||||
// [KERAB-VALLEY-HALF 2026-06-11] A/B 타입 표준 규칙(방향 무관):
|
||||
// 내부확장라인은 맞은편 roofLine 까지 거리의 "절반"에서 멈춘다.
|
||||
// 기존 ridge-stop / wall-끝까지 휴리스틱은 ridge 가 우연히 중간에 있으면 절반처럼,
|
||||
// 없으면 끝까지 가버려 방향(세로/가로)에 따라 결과가 들쭉날쭉했다 → 항상 절반으로 통일.
|
||||
// wallHit = 이 ray 가 만나는 맞은편 roof 외곽선(roofLine). 그 중점이 stop.
|
||||
if (wallHit) {
|
||||
bestStop = { x: (start.x + wallHit.x) / 2, y: (start.y + wallHit.y) / 2 }
|
||||
logger.log(
|
||||
'[KERAB-VALLEY-EXT-RIDGE-STOP] post label=' + ep.label +
|
||||
' ridgeT=' + Math.round(ridgeT * 100) / 100 +
|
||||
' stop={' + Math.round(bestStop.x * 100) / 100 + ',' + Math.round(bestStop.y * 100) / 100 + '}',
|
||||
)
|
||||
} else if (wallHit) {
|
||||
bestStop = wallHit
|
||||
logger.log(
|
||||
'[KERAB-VALLEY-EXT-WALL] post label=' + ep.label +
|
||||
' end={' + Math.round(bestStop.x * 100) / 100 + ',' + Math.round(bestStop.y * 100) / 100 + '}',
|
||||
'[KERAB-VALLEY-HALF] post label=' + ep.label +
|
||||
' wallHit={' + Math.round(wallHit.x * 100) / 100 + ',' + Math.round(wallHit.y * 100) / 100 + '}' +
|
||||
' halfStop={' + Math.round(bestStop.x * 100) / 100 + ',' + Math.round(bestStop.y * 100) / 100 + '}',
|
||||
)
|
||||
}
|
||||
if (bestStop) {
|
||||
@ -2049,15 +2077,11 @@ export function useEavesGableEdit(id) {
|
||||
const offX = newWStart.x - vStart.x
|
||||
const offY = newWStart.y - vStart.y
|
||||
const wEndProj = { x: vEnd.x + offX, y: vEnd.y + offY }
|
||||
// wEnd(원 ray hit) 가 wEndProj 보다 ray 방향으로 더 멀리 있는지 — newWStart 기준 투영 비교.
|
||||
const tProj = (wEndProj.x - newWStart.x) * wUx + (wEndProj.y - newWStart.y) * wUy
|
||||
const tEndR = (wEnd.x - newWStart.x) * wUx + (wEnd.y - newWStart.y) * wUy
|
||||
buildOverlapLine(newWStart, wEndProj, '-wall')
|
||||
buildOverlapLine(vStart, newWStart, '-bridge-start')
|
||||
buildOverlapLine(vEnd, wEndProj, '-bridge-end')
|
||||
if (tEndR > tProj + 0.5) {
|
||||
buildOverlapLine(wEndProj, wEnd, '-extend')
|
||||
}
|
||||
// [KERAB-VALLEY-HALF 2026-06-11] 절반 규칙: wLine(wallBase) 도 vEnd(절반) 까지만.
|
||||
// wEndProj 는 절반인 vEnd 에서 파생되므로, wEnd(원 ray full hit) 너머 확장은 금지.
|
||||
logger.log(
|
||||
'[KERAB-VALLEY-OVERLAP] drawn ' +
|
||||
JSON.stringify({
|
||||
@ -2068,7 +2092,7 @@ export function useEavesGableEdit(id) {
|
||||
wEnd: { x: Math.round(wEnd.x * 100) / 100, y: Math.round(wEnd.y * 100) / 100 },
|
||||
vStart: { x: Math.round(vStart.x * 100) / 100, y: Math.round(vStart.y * 100) / 100 },
|
||||
vEnd: { x: Math.round(vEnd.x * 100) / 100, y: Math.round(vEnd.y * 100) / 100 },
|
||||
extended: tEndR > tProj + 0.5,
|
||||
extended: false,
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user