Compare commits
2 Commits
af954728d8
...
946088ddc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
946088ddc2 | ||
|
|
5c02d1d45c |
@ -86,4 +86,76 @@ splitRoofLinesToInnerLines(roof, canvas, textMode) → QLine[]
|
||||
## 6. 범위 밖 (YAGNI)
|
||||
|
||||
- 외곽 지붕선 전용 우클릭 메뉴/가드 (변별 경로와 완전 동일하게 가므로 추가 분기 없음).
|
||||
- 박공(`drawGableRoof`) / 한쪽흐름(`drawShedRoof`) 경로는 이번 변경 대상 아님.
|
||||
|
||||
> 박공(`drawGableRoof`) / 한쪽흐름(`drawShedRoof`) 경로는 **§7 에서 범위로 편입** (2026-06-09).
|
||||
|
||||
---
|
||||
|
||||
## 7. 4경로 종합 (2026-06-09 추가)
|
||||
|
||||
`QPolygon.drawHelpLine()`(`QPolygon.js:773-791`) 의 4갈래 분기별 외곽 지붕선 처리 현황.
|
||||
|
||||
| 경로 | 함수 | 외곽선 생성 방식 | name / selectable / visible | 편집 가능? | 작업량 |
|
||||
|---|---|---|---|---|---|
|
||||
| **변별** | `drawRoofByAttribute` (`qpolygon-utils.js:1731`) | `roof.lines` 직접 순회 → innerLine 끝점으로 **split** (`:5432-5496`) | `hip` / true / true | ✅ 레퍼런스 | 없음(원본 추출) |
|
||||
| **박공** | `drawGableRoof` (`:710`) | 지붕면 **둘레 재구성** → `drawRoofLine`/`drawHipLine` (`:1605-1617`), `roof.innerLines.push` (`:1630`) | `hip` / true / true | ✅ **이미 됨** | 회귀 검증만 |
|
||||
| **용마루** | `drawSkeletonRidgeRoof` → `createInnerLinesFromSkeleton` | SK outer edge QLine 직접 생성 후 **숨김** (`skeleton-utils.js:1624,1638`) | `eaves` / **false** / **false** | ❌ | 중 (§3) |
|
||||
| **한쪽흐름** | `drawShedRoof` (`:1644`) | 외곽선 innerLine화 **없음** — `pitchSizeLine` 만 add (`:1701-1721`) | — | ❌ | 대 (§8) |
|
||||
|
||||
핵심 계약: `drawRoofLine`(`:5863`) 과 `drawHipLine`(`:5763`) 은 둘 다 `name: LINE_TYPE.SUBLINE.HIP` + `selectable` 미지정(QLine 기본 true). 즉 **"이 함수로 그린 외곽선 = 편집 가능한 hip innerLine"**. 컨텍스트 메뉴는 `useContextMenu.js:300-303` 에서 `name` 기준으로 자동 연결되므로 별도 바인딩 불필요(§2-1 과 동일).
|
||||
|
||||
### 7-1. 박공 — 이미 편집 가능, 메커니즘만 다름
|
||||
외곽선이 `name='hip'` innerLine 으로 이미 들어가 select+우클릭 동작. 단 변별처럼 `roof.lines` 를 split 하지 않고 **지붕면 둘레 점을 직교 재정렬**(`getSortedOrthogonalPoints`, `:1571`)해서 그린다. → "신규 구현" 이 아니라 **이동/사이즈변경 시 `roof.lines` 정합성 회귀 검증** 대상.
|
||||
|
||||
### 7-2. 한쪽흐름 — 미구현 + 경사변 특수성 (→ §8)
|
||||
`drawShedRoof` 는 `roof.innerLines` 를 건드리지 않아 초기화된 `[]` 로 남는다. 외곽선 편집을 위해 split 을 새로 붙여야 하나, **공용 split 을 그대로 쓰면 경사변의 실제길이가 틀린다** — §8.
|
||||
|
||||
## 8. 한쪽흐름 degree 전략 주입 설계 (2026-06-09 추가)
|
||||
|
||||
### 8-1. 문제: 평면길이 ≠ 실제길이
|
||||
한쪽흐름은 흐름방향으로 기울어져 변마다 경사 적용 여부가 다르다.
|
||||
|
||||
| 변 종류 | 흐름방향 관계 | 경사 | plane vs actual |
|
||||
|---|---|---|---|
|
||||
| 처마(eaves) / 마루(shed) | 수직 | 수평 | plane = actual |
|
||||
| **박공(gable)** | **평행** | 경사면 | **plane ≠ actual** (= `planeSize / cos(shedDegree)`) |
|
||||
|
||||
공용 split 이 외곽선을 그리는 `drawRoofLine`(`:5863`) 은 `actualSize: calcLinePlaneSize(...)` 로 **무조건 actual=plane** 을 박는다(degree 인자 없음, 수평선 전용 가정). `drawHipLine`(`:5763`) 은 degree 를 받지만 split 이 넘기는 값은 **인접 변의 `attributes.pitch`**(`:5443-5444`)라 흐름 경사와 무관. 게다가 한쪽흐름은 분할점이 없어(내부 용마루·추녀 없음) 전 외곽변이 통째 `drawRoofLine` 으로 그려져 → 박공변도 actual=plane → **틀림**.
|
||||
|
||||
도메인 규칙의 단서는 `drawShedRoof` 자체에 이미 있다(`:1656-1669`):
|
||||
```js
|
||||
const shedDegree = getDegreeByChon(sheds[0].attributes.pitch) // 흐름 경사각
|
||||
gables.forEach((gable) =>
|
||||
gable.attributes.actualSize = calcLineActualSize({...gable}, shedDegree)) // 박공변만 보정
|
||||
```
|
||||
`calcLineActualSize(points, deg) = planeSize / cos(deg)` (`:6270`). 현재는 `roof.lines` attributes 에만 쓰고 innerLine 을 안 만들어 편집 불가.
|
||||
|
||||
### 8-2. 설계 (방향 1 채택): degree 결정 전략 주입
|
||||
공용 split 의 **기하(분할/연결) 로직은 재사용**, "각 분할 라인의 degree" 만 경로별 전략으로 분리한다.
|
||||
|
||||
`splitRoofLinesToInnerLines(roof, canvas, textMode, opts)` 시그니처에 degree 전략 주입:
|
||||
|
||||
```
|
||||
opts.degreeOf?: (parentLine) => number // 부모 외곽변 → 경사각(도). 없으면 기존 인접 pitch 방식.
|
||||
```
|
||||
|
||||
- **변별 / 박공 / 용마루**: `degreeOf` 미전달 → 기존 끝점·인접 pitch 기반 (동작 불변).
|
||||
- **한쪽흐름**: `degreeOf = (parentLine) => isGable(parentLine) ? shedDegree : 0`
|
||||
- `isGable`: 부모 변의 `attributes.type === LINE_TYPE.WALLLINE.GABLE` (흐름방향 평행 변).
|
||||
|
||||
구간 그리기 분기:
|
||||
- 경사 구간(`deg > 0`): `drawRoofLine` 대신 **`drawHipLine(points, …, deg, deg)`**. 박공변이 수평/수직이면 `drawHipLine` 의 대각선 분기(`:5767`)를 건너뛰고 `calcLineActualSize(points, deg)` 로 `plane/cos(deg)` 계산 → `drawShedRoof` 기존 보정과 **수식 일치**.
|
||||
- 수평 구간(`deg === 0`): 기존대로 `drawRoofLine`.
|
||||
|
||||
### 8-3. 편집 환산까지 해결 — degree 를 라인 attributes 에 저장
|
||||
표시용 actualSize 뿐 아니라 **select → 사이즈 변경** 시 입력값(plane↔actual) 환산에도 라인이 자기 degree 를 들고 있어야 한다. 변별/용마루 hip 은 `attributes` 에 경사 정보가 있어 환산되지만, 한쪽흐름 경사변은 **`shedDegree` 를 라인 `attributes.pitch`(또는 degree)에 심지 않으면 편집 모달 환산이 깨진다.** → §8-2 의 `drawHipLine(…, deg, deg)` 호출이 degree 를 라인 속성에 함께 저장하도록 하여 표시·편집을 동시에 해결.
|
||||
|
||||
### 8-4. 적용 순서 / 검증
|
||||
1. `splitRoofLinesToInnerLines` 추출 시 `degreeOf` 옵션 포함 (§3-1 + §8-2 병합).
|
||||
2. `drawShedRoof` 끝에서 `splitRoofLinesToInnerLines(roof, canvas, textMode, { degreeOf })` 호출. 기존 `pitchSizeLine` 추가는 유지.
|
||||
3. 검증: 한쪽흐름 박공변 select 시 actual 표시값 = `plane / cos(shedDegree)`, 사이즈변경 모달에서 plane↔actual 양방향 환산 정상, 처마/마루변은 plane=actual.
|
||||
4. 회귀: 변별·박공·용마루는 `degreeOf` 미전달이므로 동작 불변 확인.
|
||||
|
||||
### 8-5. 리스크
|
||||
- **분할점 부재**: 한쪽흐름은 내부 보조선이 없어 외곽변이 1:1 통짜 라인으로 그려진다 → 부모 변 type 매칭이 단순(분할 시에도 조각은 부모 type 상속). split 의 끝점 정합성(`isPointOnLineNew`, tol 0.1) 자체는 분할점이 없으면 무의미하므로 `else` 통짜 경로(`:5493`)로 안전하게 떨어진다.
|
||||
- **`isGable` 판정원**: `drawShedRoof` 의 `gables` 분류(`:1653`)와 동일 기준(`attributes.type === GABLE`)을 써야 보정 대상이 일치.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user