- CLAUDE.md: 프로젝트 전체 가이드 및 워크플로우 정의 - CONSIDERATIONS.md: 8개 영역 고려사항 분석 (기술, 품질, 배포, UX) - PROGRESS.md: 진행 상황 추적 및 체크리스트 - PLAN.md: 단계 5~9 상세 계획 및 에이전트 역할 정의 - 메모리: 프로젝트 정보 저장 다음: 단계 5 (에이전트/커맨드/스킬/훅 아이디어 제안)
311 lines
16 KiB
Markdown
311 lines
16 KiB
Markdown
# 로드맵 — 일반 도면 세트 → 3D → IFC
|
||
|
||
지금 파이프라인은 **평면도 + 단면도** 조합에서 검증됐다(맨홀 일반도 4매, 11파트).
|
||
2026-08-07 에 **두 번째 도면군**(교량 설계지침 삽도 7장)을 넣어 1장을 관통시켰다
|
||
(중앙분리대 방호벽, 4.8058 m³ — 모델러·해석 일치).
|
||
궁극 목표는 **평면 · 입면 · 단면 · 좌측면 · 우측면**을 읽어 IFC 구조로 내보내는 것.
|
||
|
||
이 문서는 거기까지 무엇이 남았는지, 어떤 순서로 하면 되는지를 적는다.
|
||
|
||
> **두 번째 도면군이 바꾼 것.** 남은 일 목록이 「연산이 부족하다」에서
|
||
> 「**입력 해석 가정이 부족하다**」로 옮겨갔다. 교량에서 실제로 막은 것은
|
||
> sweep·revolve 가 아니라 단위·축척·뷰 제목·레이어·폐곡선이었다.
|
||
> 자세한 것은 [`methodology.html`](methodology.html) 11장, 교훈은
|
||
> [`2d-3d-conversion.md`](2d-3d-conversion.md) #20~#26.
|
||
|
||
> 그 위에 얹은 **파라메트릭 설계 층**은 [`parametric.md`](parametric.md) 에 따로 있다.
|
||
> **구현됐다**(fit/build 분리 · 규칙 · 편집 UI). 본체 목표(2D→3D)를 대체하지 않는다.
|
||
|
||
---
|
||
|
||
## 1. 뷰 종류의 일반화
|
||
|
||
지금 `titles.views` 는 뷰 제목을 네 가지 `kind` 로 분류한다.
|
||
|
||
```
|
||
plan 평면도 DWG(x,y) → 프로젝트(X, Y)
|
||
long 종단면 DWG(x,y) → 프로젝트(X, Z)
|
||
cross 횡단면 DWG(x,y) → 프로젝트(Y, Z)
|
||
horizontal 수평 단면 DWG(x,y) → 프로젝트(Y, X) (swapUV)
|
||
```
|
||
|
||
정면도·배면도·좌측면도·우측면도를 넣으면 이렇게 된다.
|
||
|
||
| 뷰 | 보는 방향 | 평면 | 비고 |
|
||
|---|---|---|---|
|
||
| 평면도 | −Z (위에서) | XY | |
|
||
| 저면도 | +Z | XY | 좌우 반전 → `flip` |
|
||
| 정면도 | +Y | XZ | |
|
||
| 배면도 | −Y | XZ | 좌우 반전 → `flip` |
|
||
| 좌측면도 | +X | YZ | |
|
||
| 우측면도 | −X | YZ | 좌우 반전 → `flip` |
|
||
| 종단면 | ±Y | XZ | 정면도와 같은 평면 |
|
||
| 횡단면 | ±X | YZ | 측면도와 같은 평면 |
|
||
| 수평 단면 | −Z | XY | 평면도와 같은 평면 |
|
||
|
||
**결국 평면은 셋(XY · XZ · YZ)뿐이고, 나머지는 반전 여부의 문제다.**
|
||
`kind` 라는 이름이 오해를 부른다 — 앞으로는 `plane` + `flip` 으로 부르는 게 맞다.
|
||
|
||
### 할 일
|
||
|
||
- `titles.views` 항목을 `{ plane, u0, v0, flip, flipV, swapUV }` 한 덩어리로 합친다.
|
||
지금은 `titles.views` 와 `anchors` 로 나뉘어 있어 뷰 하나가 두 곳에 흩어져 있다.
|
||
- 뷰가 어느 방향에서 본 것인지 **도면에서 검출**할 방법을 찾는다.
|
||
단면은 절단 기호(`SYM`)로 알 수 있지만, 입면도는 제목 말고 단서가 없다.
|
||
→ 제목 규칙(`정면도`/`좌측면도` …)을 설정에 두는 게 현실적이다.
|
||
|
||
---
|
||
|
||
## 2. 입면도가 단면도와 다른 점
|
||
|
||
단면도는 **잘린 면**만 그리지만 입면도는 **보이는 모든 것**을 그린다.
|
||
그래서 입면도의 폐곡선은 구조체 경계가 아니라 **투영 윤곽**이다.
|
||
|
||
| | 단면도 | 입면도 |
|
||
|---|---|---|
|
||
| 폐곡선의 의미 | 재료 영역 | 보이는 면의 윤곽 (여러 깊이가 겹침) |
|
||
| 압출 가능? | 그대로 가능 | **불가.** 깊이 정보가 없다 |
|
||
| 쓸모 | 형상 생성 | 형상 **검증**, 높이·폭 확인, 개구부 위치 |
|
||
|
||
**입면도로 솔리드를 만들려 하지 말 것.** 입면도는
|
||
|
||
- 다른 뷰에서 만든 형상의 **외곽 검증**
|
||
- 창·문·개구부의 **XZ(또는 YZ) 위치** 확보
|
||
- 마감선·레벨선 확인
|
||
|
||
에 쓰고, 실제 압출은 평면도(footprint) + 단면도(높이)로 한다.
|
||
|
||
### 할 일
|
||
|
||
- 입면도용 검증 도구: 만든 3D 를 그 방향으로 투영해 입면도 윤곽과 대조
|
||
- 개구부 위치만 뽑아 쓰는 경로 (지금 `rect()` + `expect()` 로 하는 것과 같은 방식)
|
||
|
||
---
|
||
|
||
## 3. 곡면 · 원호
|
||
|
||
지금은 **직선 선분만** 다룬다(`src/core/parse.mjs` 의 `toSegments`).
|
||
ARC · CIRCLE · ELLIPSE 는 버린다.
|
||
|
||
| 대상 | 필요한 것 |
|
||
|---|---|
|
||
| 모따기·필렛 | 이미 직선으로 그려져 있으면 그대로 됨 (지금 잘 되고 있다) |
|
||
| **원형 관통 (Ø900·Ø100)** | **됨** — `collectCircles` → `circles()` → `cylinder` |
|
||
| 원호 벽체 | ARC 를 선분으로 근사(tessellate)하거나 IR 에 호 지원 추가 |
|
||
| 나선계단 | 전용 연산. `Sweep1` 또는 파라메트릭 생성 |
|
||
|
||
### CIRCLE — 된다 (2026-08-06)
|
||
|
||
```sh
|
||
node src/build.mjs <도면> --circles # 뷰별 원 목록 (지름 · 레이어 · 좌표)
|
||
```
|
||
|
||
```js
|
||
circles('평 면 도', 900, /^-전력구$/) // 지름으로 집는다. 폐곡선과 같은 규칙
|
||
circle('평 면 도', 100) // 정확히 하나일 때. 여럿이면 예외
|
||
```
|
||
|
||
**선분과 섞지 않는다.** 원을 다각형으로 근사해 평면 분할에 넣으면 폐곡선이 그
|
||
윤곽을 따라 돌아 프로파일이 오염된다. 원은 그 자체가 형상이라 `cylinder` 로 바로 간다.
|
||
|
||
뷰 귀속은 중심 좌표로 한다 — 뷰 분리(조각 클러스터링)에 원을 넣으면 관통 구멍
|
||
하나가 뷰를 잇는 다리가 될 수 있다. 이 도면은 133개 중 129개가 귀속됐다.
|
||
|
||
**부수 효과: 평면도에 `v0` 앵커가 필요해졌다.** 평면도는 세로축이 표고가 아니라
|
||
폭방향(Y)인데, 지금까지 치수(폭×높이)만 봐서 드러나지 않았다. 좌표를 직접 쓰는
|
||
순간 필요해진다. 수평 단면(H/I/J)과 같은 문제였다.
|
||
|
||
남은 것: **Ø100 관통 5개**(`환기구` 4 · `배수관` 1). 평면도에 있는 1개는
|
||
X=17,690 으로 맨홀 #2 영역이라 그 형상을 세운 뒤에 뚫는다.
|
||
|
||
---
|
||
|
||
## 4. IFC 출력
|
||
|
||
### 이미 확보된 것
|
||
|
||
레이어가 재질을 인코딩한다는 사실(노하우 문서 교훈 #6). 그래서 클래스·재질
|
||
배정에 필요한 정보가 이미 IR 에 실려 있다.
|
||
|
||
```js
|
||
part({ …, name: '맨홀1_전력구_구체',
|
||
material: '구체 콘크리트 fck=27MPa' })
|
||
```
|
||
|
||
### 매핑 초안
|
||
|
||
| 부재 | IFC 클래스 | 재질 |
|
||
|---|---|---|
|
||
| 벽체 | `IfcWall` | Concrete C27 |
|
||
| 슬래브 | `IfcSlab` | Concrete C27 |
|
||
| 기초 | `IfcFooting` | Concrete C18 |
|
||
| 잡석·토목섬유 | civil 계열 (**IFC4.3 엔티티명 확인 필요**) | — |
|
||
| 집합 요소 | `IfcBuiltElement` 또는 civil 계열 | — |
|
||
|
||
- 재질 속성 → `IfcMaterial` + `Pset_MaterialConcrete`(CompressiveStrength)
|
||
- 층상 구성(잡석 → 기초 → 구체) → `IfcMaterialLayerSet`
|
||
- 설계 정보(fck · fy · 설계법 · 하중) → `IfcProject` 속성
|
||
|
||
> `IfcWall`/`IfcSlab`/`IfcFooting`/`IfcMaterial*`/`Pset_MaterialConcrete` 는 IFC4
|
||
> 표준이라 그대로 써도 된다. **잡석·토목섬유용 IFC4.3 civil 엔티티 이름은
|
||
> 스키마를 직접 확인하고 확정할 것.** 위 표의 후보는 검증 전이다.
|
||
|
||
### 할 일
|
||
|
||
- `part` 에 `ifcClass` 필드 추가 (지금은 `material` 만 있다)
|
||
- `src/emit/ifc.mjs` — IR → IFC4 STEP(.ifc)
|
||
- 형상 표현: `IfcExtrudedAreaSolid` 가 지금 IR 의 `extrude` 와 1:1 로 맞는다.
|
||
`difference`/`union` 은 `IfcBooleanResult` 로 그대로 옮겨진다.
|
||
**IR 을 IFC 를 염두에 두고 설계해둔 게 여기서 값을 한다.**
|
||
|
||
---
|
||
|
||
## 5. 우선순위 제안
|
||
|
||
2026-08-06 에 순서를 정했다 — **본체(A)를 좁혀서 먼저, 그 다음 파라메트릭(B).**
|
||
근거는 [`parametric.md`](parametric.md) 11절.
|
||
|
||
```
|
||
✔ 0. 부피 측정 자동화 (measure.mjs) 손계산 → 회귀 검사. B 의 quantity 몸통
|
||
✔ 1. CIRCLE → circles() 헬퍼 손으로 적은 R450 이 도면 대조로 바뀌었다
|
||
2. manhole1-trans 를 본편으로 통합 지금 반쪽 모델이 둘이다. 기초·잡석 이관
|
||
3. 맨홀 #2 + 출구 스터브 제일 크다. 파라미터 표본을 대표성 있게 만든다
|
||
✔ 4. 파라메트릭 (parametric.md 10·12절) fit/build 분리 · 규칙 · 편집 UI 까지 완료
|
||
5. 뷰 설정 통합 (titles.views + anchors + viewBoxes → 한 덩어리) ← 아래 참고
|
||
6. emit/ifc.mjs IR 이 이미 준비돼 있다
|
||
7. 입면도 검증 경로 새 도면 종류를 받으려면 필요
|
||
8. Sweep 백엔드 (선형 곡선부·구배) Loft 는 완료
|
||
```
|
||
|
||
**5 의 값이 올라갔다.** 뷰 하나를 서술하는 자리가 이제 **셋**이다 —
|
||
`titles.views`(평면) · `anchors`(앵커·축척) · `viewBoxes`(영역·평면·축척).
|
||
`unitMm` 이 `viewBoxes` 와 `anchors` 양쪽에 있고, 뷰 분리 방식에 따라 어느 쪽이
|
||
읽히는지가 갈린다. 뷰 종류를 늘리기 전에 정리하는 편이 싸다 —
|
||
`{ plane, box?, u0, v0, flip, flipV, swapUV, unitMm, role }` 한 덩어리로.
|
||
|
||
**교량군에서 새로 생긴 것 (전부 구현됨, 정리 필요):**
|
||
|
||
```
|
||
cfg.unitMm DWG 모델단위. 도면군마다 다르다
|
||
cfg.entityFilter 레이어 말고 색·선종으로 거른다
|
||
cfg.viewBoxes 제목 없는/중복인 도면의 뷰 영역
|
||
cfg.datum.mode='none' 공통 기준선이 없는 도면
|
||
viewBoxes[뷰].unitMm 도형별 축척
|
||
rules[].needs 규칙 적용 범위 (부재 타입 태그의 임시 대용)
|
||
```
|
||
|
||
**아직 없는 것 (교량 일반도를 받으면 바로 필요해진다):**
|
||
|
||
```
|
||
G1.5 도면 적격 판정 도구 숫자/기호 치수 계수 + 윤곽 닫힘률. 지금은 손으로 센다
|
||
축척 역산 도구 표기 치수 2개 ↔ 기하 길이 대조. 지금은 손으로 잰다
|
||
부재 타입 태그 rules 를 파라미터 이름이 아니라 부재 종류에 붙인다
|
||
받침 기반 로컬 프레임 상부(선형) ↔ 하부(연직) 좌표계 전환 (methodology 11.1)
|
||
```
|
||
|
||
1 을 3 보다 앞에 두는 이유는 로드맵상 흔해서만이 아니다. **파라메트릭의
|
||
전제이기도 하다** — 지금 샤프트 보어 R450 은 원본 엔티티에서 눈으로 읽어 손으로
|
||
적은 값이라 도면과의 끈이 아예 없다. CIRCLE 지원이 들어와야 `loop()`/`expect()`
|
||
로 대조되고, 그제서야 보어 반지름이 정당한 파라미터가 된다.
|
||
|
||
1·2·3 은 서로 독립이라 순서를 바꿔도 된다.
|
||
|
||
**Loft 백엔드는 끝났다** — 전이부(챔퍼·수직 단차·종방향 헌치)를 세워 부피
|
||
오차 0.0002% 로 검증했다. 배경은 [`2d-3d-conversion.md`](2d-3d-conversion.md)
|
||
교훈 #16. 남은 것은 **rail 을 따라가는 스윕**이다 (`Sweep1 C=True V=True` 가
|
||
IFC4.3 `IfcSectionedSolidHorizontal` 과 의미가 같다). 그러려면 IR 이 직선축
|
||
`from/to` 대신 **측점(station)** 을 다뤄야 한다.
|
||
4 는 실제 입면도가 있는 도면을 하나 받아야 설계가 확정된다.
|
||
|
||
---
|
||
|
||
## 6. 미완 목록 (맨홀 도면 기준)
|
||
|
||
| 항목 | 상태 |
|
||
|---|---|
|
||
| 스터브↔본체 전이부 | **완료.** `assembleDuct()` 를 본편·trans 가 공유한다 |
|
||
| 관로↔맨홀 관통구 | **완료.** 개구 기호에서 좌표가 나온다. 합치기 **전에** 뚫는다 |
|
||
| 구조물만 (기초·잡석 제외) | **완료.** 5파트 |
|
||
| **맨홀 #2 부피 9.32 손실** | IR 은 맞고(74.68) 모델러가 흘린다(65.36). 원인은 면으로만 맞닿은 union — 교훈 #19 |
|
||
| 외부 헌치 5개 | **완료.** 아래 참조 |
|
||
| 내부 헌치 (100×100·150×150) | 미구현. 맨홀을 **수평 단면에서 Z 로 쌓아야** 따라온다 |
|
||
| H/I/J 내부 링 끊김 | H-H 내부가 Y 1,800~3,700 만 닫힌다. 위 항목의 전제 |
|
||
| Ø100 관통 5개 | 위치 확인됨 (전선인입 ×2 · 우수관연결 ×2 · 유도배수관 ×1). 미구현 |
|
||
| 침사구 (0.8×0.8) | I-I 개구 기호로 **잡힌다**. `opening('단 면 I-I', 800, 800)` |
|
||
| 나선계단 · 방호난간 | 현 IR 연산으로 표현 불가 |
|
||
| 기초 · 잡석 · 보도 | 뺐다. 되살리는 데 필요한 값은 `manhole1.mjs` 주석에 있다 |
|
||
|
||
### 외부 헌치 — 완료 (2026-08-06)
|
||
|
||
평면도 대각선 21개 중 **외부 표면 모서리**인 5개를 세 종류로 나눠 넣었다.
|
||
Z 구간은 도면에서 뽑았지 지어내지 않았다.
|
||
|
||
| 종류 | 도면 근거 | 구현 | 부피 변화 |
|
||
|---|---|---|---|
|
||
| 출구 스터브 챔퍼 | A-A `(18200,-4607)→(18500,-4907)` 300×300 · `(18200,-8007)→(18550,-7657)` **350×350** | loft 2단 | +0.577 |
|
||
| 전력구↔맨홀 접합 | 평면 `(15100,1900)→(15400,2200)` 300×300 | XY 삼각형 → Z 압출 → union | +0.224 |
|
||
| 챔버↔환기구 다리 | 평면 `(15400,4100)→(15500,4200)` 100×100 ×2 | XY 사각 쐐기 → Z 압출 → 커터 | −0.029 |
|
||
|
||
**3D 검증 완료** — `modelCount 5`, 의도 vs 결과가 셋 다 맞는다.
|
||
|
||
```
|
||
파트 실측 IR 의도 차이
|
||
맨홀1_전력구_구체 100.7473 100.7592 −0.0119 ✓ 접합 헌치 들어감
|
||
맨홀1_전력구_출구스터브 3.5474 3.5490 −0.0016 ✓ 출구 챔퍼 2단 들어감
|
||
맨홀1_사다리샤프트_1·2 3.3217/3.2805 ✓ 건드리지 않은 것 확인
|
||
맨홀1_맨홀2_구체 66.0875 74.6527 −8.5652 ✗ 기존 손실 (수평단면 재구성 대기)
|
||
```
|
||
|
||
**출구는 입구와 대칭이 아니다.** 위·옆은 300×300(X 18,200~18,500)인데 아래는
|
||
350×350(18,200~**18,550**)이라 꺾이는 X 가 다르다. loft 하나로 이으면 아래 챔퍼가
|
||
300 짜리로 짧아진다 — 입구에서 이미 겪은 교훈 #16 이 그대로 반복됐다.
|
||
|
||
검산: 격자 +0.5765 vs 심프슨 해석 +0.5749 — **0.3% 일치**.
|
||
|
||
**평면 방향 헌치는 XZ 단면에 안 나타난다.** 다리 100×100 의 Z 범위를 F-F·G-G 에서
|
||
찾으려 했지만 없다(거기 있는 150×150 은 다리 *내부* 헌치다). 그래서 `fit()` 이
|
||
E-E 외곽 링에서 `Y>4,200` 구간의 Z 범위를 **코드로** 뽑는다 → −5,257 ~ 176.
|
||
|
||
다리 테이퍼의 부피 변화가 작은(−0.029) 데는 이유가 있다. E-E 링을 보면 하부 블록이
|
||
**Y=4,100 에서 끝나고**(`[4100,-10007]→[4100,-5557]`) 그 위로 다리가 선다. 그래서
|
||
테이퍼가 걸리는 Y 4,100~4,200 구간에는 재료가 100mm 높이밖에 없다.
|
||
|
||
### 맨홀 #2 를 수평 단면 기반으로 다시 세우면 셋이 한꺼번에 풀린다
|
||
|
||
```
|
||
부피 9.32 손실 조각이 Z 로 진짜 겹쳐 union 이 한 덩어리가 된다
|
||
내부 헌치 H/I/J 의 XY 프로파일에 모따기가 이미 들어 있다
|
||
층별 정확도 E-E 치수 사슬이 각 층의 Z 범위를 그대로 준다
|
||
```
|
||
|
||
전제는 H/I/J 의 내부 링 끊김 수리다. **조사는 끝났다.**
|
||
|
||
`gaps.mjs` 는 H-H·I-I 에 끊김 **0** 이라고 한다 — 선이 없는 게 아니라 개구부
|
||
윤곽이 안 닫혀 있어 면이 새는 것이다(교훈 #12 와 같은 종류). 선분을 직접 뽑아
|
||
실태를 확정했다.
|
||
|
||
```
|
||
H-H 내부는 격벽으로 3칸이다 (전부 X 15,800~17,800, 모서리 150×150 모따기)
|
||
A Y -1,500 ~ 1,500 3,000 ← 환기 OPEN부가 들어 있어 안 닫힘
|
||
B Y 1,800 ~ 3,700 1,900 ← 유일하게 폐곡선으로 잡힌다 (#2)
|
||
C Y 3,700 ~ 8,000 4,300 ← 점검구·방호난간이 들어 있어 안 닫힘
|
||
격벽 Y 1,500~1,800 (300)
|
||
```
|
||
|
||
A·C 가 안 닫히는 이유는 개구부 좌측 변이 `000-구조물실선` 에 **Y -1,000~1,000
|
||
로만** 그려져 있기 때문이다(개구는 Y -500~1,500). 대응은 교훈 #12 대로
|
||
`rect()`/`opening()` 으로 재구성 — 위 좌표가 그 재료다.
|
||
|
||
---
|
||
|
||
## 7. 검증 기준선
|
||
|
||
`baselines/<도면>.volumes.json` 은 **커밋한다.** `out/` 과 달리 재생성으로
|
||
복구되지 않기 때문이다 — 사람이 한 번 확인한 부피가 남아 있어야 다음 변경이
|
||
형상을 건드렸는지 알 수 있다.
|
||
|
||
| 도면 | 파트 | 부피 m³ | 확인 |
|
||
|---|---|---|---|
|
||
| `manhole1-trans` | 3 | 107.1425 | 원시 파트 합으로 교차검증 |
|
||
| `manhole1` | 11 | — | 기준선 없음. 통합 후 뜬다 |
|