feat(roof-shape): 지붕형상 패턴 카탈로그 상수 모듈 추가

[작업내용] :
- ROOF_SHAPE_PATTERNS(8) + ROOF_FLOW/ROOF_SHAPE_TYPE/ROOF_RIDGE 상수
- 매칭 키 type+ridge+flows, flows 집합만으로 8패턴 유일 식별
- getRoofShapePatternByShapeNum 접근자
- 매칭 함수·PDF 분석 확장은 다음 작업으로 분리

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
sangwook yoo 2026-06-24 10:50:35 +09:00
parent 105c8470ad
commit 61ffcee949

View File

@ -0,0 +1,106 @@
// 지붕형상 설정 팝업(RoofShapeSetting)의 8개 패턴 카탈로그.
// PDF 분석→지붕형상 자동 매칭의 룩업 테이블. 매칭 키: type + ridge + flows(집합).
// 설계 근거: docs/superpowers/specs/2026-06-24-roof-shape-pattern-catalog-design.md
// 화면축 흐름방향 (방위적용 前 — 지붕형상 설정 시점에는 실제 방위가 없다)
export const ROOF_FLOW = { TOP: 'top', BOTTOM: 'bottom', LEFT: 'left', RIGHT: 'right' }
// 지붕 유형
export const ROOF_SHAPE_TYPE = { HIP: 'hip', GABLE: 'gable', SHED: 'shed', MANUAL: 'manual' }
// 용마루 방향
export const ROOF_RIDGE = { HIP: 'hip', HORIZONTAL: 'horizontal', VERTICAL: 'vertical', SHED: 'shed', NONE: 'none' }
// shapeNum = useRoofShapeSetting.shapeMenu 의 id 이자 자동 클릭 대상(setShapeNum 값).
// flows 집합만으로 8패턴이 상호 유일하게 식별된다.
// 5~8 화면축↔버튼 매핑은 useRoofShapeSetting case 4~8 에서 전사(정규 winding: outerLines[0].direction==='bottom').
export const ROOF_SHAPE_PATTERNS = [
{
shapeNum: 1,
key: 'ridge',
nameKey: 'modal.roof.shape.setting.ridge',
type: ROOF_SHAPE_TYPE.HIP,
ridge: ROOF_RIDGE.HIP,
flows: [ROOF_FLOW.TOP, ROOF_FLOW.BOTTOM, ROOF_FLOW.LEFT, ROOF_FLOW.RIGHT],
autoMatchable: true,
note: '寄棟 — 전 변 처마, 사방 흐름',
},
{
shapeNum: 2,
key: 'patternA',
nameKey: 'modal.roof.shape.setting.patten.a',
type: ROOF_SHAPE_TYPE.GABLE,
ridge: ROOF_RIDGE.HORIZONTAL,
flows: [ROOF_FLOW.TOP, ROOF_FLOW.BOTTOM],
autoMatchable: true,
note: '切妻 — 상하 처마/좌우 케라바, 가로 용마루',
},
{
shapeNum: 3,
key: 'patternB',
nameKey: 'modal.roof.shape.setting.patten.b',
type: ROOF_SHAPE_TYPE.GABLE,
ridge: ROOF_RIDGE.VERTICAL,
flows: [ROOF_FLOW.LEFT, ROOF_FLOW.RIGHT],
autoMatchable: true,
note: '切妻 — 좌우 처마/상하 케라바, 세로 용마루',
},
{
shapeNum: 5,
key: 'west',
nameKey: 'commons.west',
type: ROOF_SHAPE_TYPE.SHED,
ridge: ROOF_RIDGE.SHED,
flows: [ROOF_FLOW.BOTTOM],
direction: 'west',
autoMatchable: true,
note: '片流れ — 처마/흐름 bottom, 케라바 좌우',
},
{
shapeNum: 6,
key: 'east',
nameKey: 'commons.east',
type: ROOF_SHAPE_TYPE.SHED,
ridge: ROOF_RIDGE.SHED,
flows: [ROOF_FLOW.TOP],
direction: 'east',
autoMatchable: true,
note: '片流れ — 처마/흐름 top, 케라바 좌우',
},
{
shapeNum: 7,
key: 'south',
nameKey: 'commons.south',
type: ROOF_SHAPE_TYPE.SHED,
ridge: ROOF_RIDGE.SHED,
flows: [ROOF_FLOW.RIGHT],
direction: 'south',
autoMatchable: true,
note: '片流れ — 처마/흐름 right, 케라바 상하',
},
{
shapeNum: 8,
key: 'north',
nameKey: 'commons.north',
type: ROOF_SHAPE_TYPE.SHED,
ridge: ROOF_RIDGE.SHED,
flows: [ROOF_FLOW.LEFT],
direction: 'north',
autoMatchable: true,
note: '片流れ — 처마/흐름 left, 케라바 상하',
},
{
// 변별로 설정 — 자동매칭 비대상(폴백). 깨끗한 매칭 실패 시 후보로만 표시.
shapeNum: 4,
key: 'side',
nameKey: 'modal.roof.shape.setting.side',
type: ROOF_SHAPE_TYPE.MANUAL,
ridge: ROOF_RIDGE.NONE,
flows: [],
autoMatchable: false,
note: '변별로 설정 — 자동매칭 비대상(폴백)',
},
]
// shapeNum 으로 카탈로그 항목 조회. 없으면 null.
export const getRoofShapePatternByShapeNum = (shapeNum) => ROOF_SHAPE_PATTERNS.find((pattern) => pattern.shapeNum === shapeNum) || null