step3-4: 프로젝트 기본 구조 & 상세 계획 수립
- CLAUDE.md: 프로젝트 전체 가이드 및 워크플로우 정의 - CONSIDERATIONS.md: 8개 영역 고려사항 분석 (기술, 품질, 배포, UX) - PROGRESS.md: 진행 상황 추적 및 체크리스트 - PLAN.md: 단계 5~9 상세 계획 및 에이전트 역할 정의 - 메모리: 프로젝트 정보 저장 다음: 단계 5 (에이전트/커맨드/스킬/훅 아이디어 제안)
This commit is contained in:
commit
363c2a2a25
16 files changed
+9018
No files matched your search
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(git init *)",
|
||||
"Bash(git config *)",
|
||||
"Bash(git add *)",
|
||||
"Bash(git commit -m 'step3-4: 프로젝트 기본 구조 & 상세 계획 수립 *)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
# CLAUDE.md — DXF to 3D Web App 프로젝트 가이드
|
||||
|
||||
> **이것은 AI 에이전트를 위한 프로젝트 지침서입니다.**
|
||||
> 이 파일을 먼저 읽고 작업을 시작하세요.
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
### 목표
|
||||
2D DXF 도면(가시설 일반도)을 분석하여 3D 모델로 변환하고, 웹상에서 실시간으로 검토할 수 있는 웹앱을 만든다.
|
||||
|
||||
### 최종 산출물
|
||||
```
|
||||
사용자 → 웹사이트 (무료 도메인)
|
||||
↓
|
||||
DXF 업로드 & 자동 변환
|
||||
↓
|
||||
3D 모델 실시간 시각화
|
||||
↓
|
||||
부재 정보 조회, 측정, 다운로드
|
||||
```
|
||||
|
||||
### 핵심 요구사항
|
||||
- ✅ **Git 관리**: 모든 작업 과정 기록
|
||||
- ✅ **무료 배포**: Vercel + 커스텀 도메인
|
||||
- ✅ **품질**: Haiku 4.5 모델임에도 우수한 결과물
|
||||
- ✅ **단계별 검증**: 각 단계 전에 작업 리마인드 + 진행 확인
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트 구조
|
||||
|
||||
```
|
||||
D:\Obsidian Vault\999ETC\261016_HW_DwfTo3D\
|
||||
│
|
||||
├── docs/ # 기초 자료 (읽기 전용)
|
||||
│ ├── roadmap.md # 진행 상황 & 우선순위
|
||||
│ ├── 2d-3d-conversion.md # 19개 교훈 (매우 중요!)
|
||||
│ ├── 2d-3d-process.md # 절차 문서
|
||||
│ ├── methodology.html # 방법론 상세
|
||||
│ └── dwg2model-CLAUDE.md # 기존 프로젝트 가이드
|
||||
│
|
||||
├── RAG/ # 대상 DXF 파일
|
||||
│ ├── 가시설_평면.dxf # 평면도
|
||||
│ ├── 가시설_단면.dxf # 단면도
|
||||
│ └── 가시설_상세1~4.dxf # 상세도
|
||||
│
|
||||
├── src/ # 소스 코드 (구현 예정)
|
||||
│ ├── drawings/
|
||||
│ │ ├── index.mjs # 모든 도면의 중앙 진입점
|
||||
│ │ └── gasiseol.mjs # 가시설 도면 설정 & 조립 로직
|
||||
│ │
|
||||
│ ├── core/ # 도면 고유값 없음 (절대 건드리지 말 것)
|
||||
│ │ ├── parse.mjs # DXF 파싱
|
||||
│ │ ├── views.mjs # 뷰 분리
|
||||
│ │ ├── loops.mjs # 폐곡선 추출
|
||||
│ │ └── datum.mjs # 기준점 검출
|
||||
│ │
|
||||
│ ├── build/ # IR 생성 (도면 독립)
|
||||
│ │ ├── assemble.mjs # 부재 조립
|
||||
│ │ └── validate.mjs # 검증
|
||||
│ │
|
||||
│ ├── emit/ # 3D 출력 (도면 독립)
|
||||
│ │ ├── egm.mjs # EGModeler 명령 생성
|
||||
│ │ └── ifc.mjs # IFC 출력
|
||||
│ │
|
||||
│ ├── web/ # React 웹앱 (새로)
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── Viewer3D.tsx # Three.js 뷰어
|
||||
│ │ │ ├── FileUpload.tsx # DXF 업로드
|
||||
│ │ │ ├── PropertyPanel.tsx # 부재 정보
|
||||
│ │ │ └── Controls.tsx # 조작 UI
|
||||
│ │ ├── pages/
|
||||
│ │ │ ├── index.tsx # 메인 페이지
|
||||
│ │ │ └── api/convert.ts # 변환 API
|
||||
│ │ ├── styles/
|
||||
│ │ ├── App.tsx
|
||||
│ │ └── main.tsx
|
||||
│ │
|
||||
│ ├── run.mjs # 도면 검증 (기존)
|
||||
│ ├── build.mjs # IR 생성 (기존)
|
||||
│ ├── measure.mjs # 부피 측정 (기존)
|
||||
│ └── paths.mjs # 경로 관리 (한 곳)
|
||||
│
|
||||
├── .claude/ # 에이전트 설정 (단계 6에서)
|
||||
│ ├── agents/
|
||||
│ │ ├── research.md
|
||||
│ │ ├── pipeline.md
|
||||
│ │ ├── webui.md
|
||||
│ │ └── deploy.md
|
||||
│ ├── commands/
|
||||
│ ├── skills/
|
||||
│ └── hooks/
|
||||
│
|
||||
├── PROGRESS.md # 진행 상황 추적 (매 세션 업데이트)
|
||||
├── PLAN.md # 상세 계획 및 에이전트 역할 분담
|
||||
├── CONSIDERATIONS.md # 고려사항 (단계 2 결과)
|
||||
├── CLAUDE.md # 이 파일
|
||||
│
|
||||
└── .gitignore # git 설정
|
||||
node_modules/
|
||||
dist/
|
||||
*.obj
|
||||
*.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 개발 워크플로우
|
||||
|
||||
### 0️⃣ 세션 시작 전
|
||||
```
|
||||
1. PROGRESS.md 읽기 ← 진행 상황 파악
|
||||
2. PLAN.md 읽기 ← 다음 작업 확인
|
||||
3. 메모리 로드 ← 이전 세션 컨텍스트
|
||||
```
|
||||
|
||||
### 1️⃣ 각 단계 시작 시
|
||||
```
|
||||
리마인드 (작업 내용 명시화)
|
||||
├─ 이 단계에서 할 것
|
||||
├─ 예상 결과물
|
||||
└─ 성공 기준
|
||||
|
||||
진행 확인 (사용자 승인)
|
||||
└─ "다음으로 진행해도 될까요?" → 대기
|
||||
|
||||
작업 수행 (git 커밋 포함)
|
||||
└─ 의미 있는 커밋 메시지
|
||||
|
||||
검증 (문제 없는지 확인)
|
||||
└─ 자동 테스트 또는 수동 검사
|
||||
|
||||
완료 리포트 (PROGRESS.md 업데이트)
|
||||
└─ 결과물 요약 & 다음 단계 예고
|
||||
```
|
||||
|
||||
### 2️⃣ Git 커밋 원칙
|
||||
```
|
||||
좋은 예시:
|
||||
step2: CONSIDERATIONS.md 작성 - 고려사항 8개 영역 정리
|
||||
step3: CLAUDE.md 작성 - 프로젝트 구조 & 워크플로우 정의
|
||||
|
||||
나쁜 예시:
|
||||
❌ update (너무 모호)
|
||||
❌ fix bugs (어떤 버그?)
|
||||
❌ step1-draft (완료 전 중간 저장)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 핵심 원칙 (반드시 지킬 것)
|
||||
|
||||
### 🚫 절대 어기면 안 되는 경계
|
||||
```
|
||||
src/core/* · src/build/* → 도면 고유값 금지 (= 설정파일로 분리)
|
||||
src/drawings/*.mjs → 레이어명, 좌표, 단위 모두 여기
|
||||
src/web/* → 웹앱만 담당 (도면 파싱 X)
|
||||
src/emit/* → 3D 도구 사정만 (도면값 X)
|
||||
```
|
||||
|
||||
**위반하면**: 두 번째 도면(다른 가시설)을 할 때 파이프라인이 아니라 복사본이 생긴다.
|
||||
|
||||
### 📊 검증 체크리스트 (필수)
|
||||
|
||||
#### 도면 검증
|
||||
- [ ] 기준점이 도면 치수 2개 이상과 일치
|
||||
- [ ] 뷰 폭·높이가 도면 표기와 ±2% 이내
|
||||
- [ ] 폐곡선 수가 예상과 일치
|
||||
- [ ] 자기교차 링 없음 (`--loops` 확인)
|
||||
|
||||
#### 3D 모델 검증
|
||||
- [ ] 부피 오차 < 0.5% (IR vs 실제)
|
||||
- [ ] manifold 체크 (닫힌 면)
|
||||
- [ ] 렌더링 성공 (Three.js)
|
||||
- [ ] 부재 정보 표시 가능
|
||||
|
||||
#### 배포 검증
|
||||
- [ ] 웹앱 로딩 < 3초
|
||||
- [ ] 3D 렌더링 60fps
|
||||
- [ ] 모바일 반응형 확인
|
||||
- [ ] 도메인 접속 가능
|
||||
|
||||
---
|
||||
|
||||
## 에이전트 역할 (단계 5에서 상세 정의)
|
||||
|
||||
| 에이전트 | 담당 영역 | 도구 |
|
||||
|---------|---------|------|
|
||||
| **Research** | 가시설 도면 분석, 설정 파일 작성 | DXF 파싱, 기하학 분석 |
|
||||
| **Pipeline** | dwg2model 통합, 테스트 자동화 | 빌드, 검증, 측정 |
|
||||
| **WebUI** | React 컴포넌트, Three.js 통합 | 개발 서버, 빌드 |
|
||||
| **Deploy** | CI/CD, Vercel 배포, 도메인 설정 | GitHub Actions, npm |
|
||||
|
||||
---
|
||||
|
||||
## 빠른 참조
|
||||
|
||||
### 자주 실행하는 명령
|
||||
|
||||
```bash
|
||||
# 도면 검증 (Node.js 필요)
|
||||
node src/run.mjs 가시설
|
||||
|
||||
# 3D 생성 (Python & egm CLI 필요)
|
||||
python src/run_egm.py 가시설 --export=out/gasiseol.obj
|
||||
|
||||
# 부피 측정
|
||||
node src/measure.mjs 가시설 --ir
|
||||
|
||||
# 웹앱 개발 서버 (나중)
|
||||
cd src/web && npm run dev
|
||||
|
||||
# 배포 (CI/CD 자동)
|
||||
git push
|
||||
```
|
||||
|
||||
### 주요 문서 (필독)
|
||||
|
||||
| 문서 | 언제 읽을까 |
|
||||
|------|-----------|
|
||||
| [`docs/2d-3d-conversion.md`](docs/2d-3d-conversion.md) | **새 도면 추가 전 필수** (19개 함정) |
|
||||
| [`docs/2d-3d-process.md`](docs/2d-3d-process.md) | 절차 확인 시 |
|
||||
| [`docs/roadmap.md`](docs/roadmap.md) | 우선순위 확인 시 |
|
||||
| [`CONSIDERATIONS.md`](CONSIDERATIONS.md) | 고려사항 확인 시 |
|
||||
| [`PLAN.md`](PLAN.md) | 에이전트 분담 시 |
|
||||
| [`PROGRESS.md`](PROGRESS.md) | 진행 상황 업데이트 시 |
|
||||
|
||||
---
|
||||
|
||||
## 품질 기준
|
||||
|
||||
### 코드 스타일
|
||||
```
|
||||
- 주석은 "왜"를 적는다. "무엇"은 코드가 말한다.
|
||||
- 조용히 틀리느니 예외를 던진다
|
||||
- 좌표·치수는 mm 정수로 (egm에 넘기기 전에만 m로 변환)
|
||||
- 가정하지 마라. 검증하고 단정해라
|
||||
```
|
||||
|
||||
### 테스트
|
||||
```
|
||||
- 도면 검증: 자동화 (--loops, --ir, measure.mjs)
|
||||
- 웹앱: 단위 테스트 + E2E 테스트
|
||||
- 배포: 리뷰 URL에서 수동 테스트 후 병합
|
||||
```
|
||||
|
||||
### 문서
|
||||
```
|
||||
- 코드와 문서를 따로 유지 (업데이트가 다르다)
|
||||
- 변경사항은 PROGRESS.md에 즉시 기록
|
||||
- 함정/해결책은 이 파일에 추가
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 트러블슈팅
|
||||
|
||||
### "도면 로드가 실패했어요"
|
||||
→ `docs/2d-3d-conversion.md` 교훈 #1~#6 확인
|
||||
|
||||
### "폐곡선이 4개가 아니에요"
|
||||
→ `docs/2d-3d-conversion.md` 교훈 #12, #18 (자기교차 검사)
|
||||
|
||||
### "부피가 IR과 맞지 않아요"
|
||||
→ `src/measure.mjs --ir` 로 의도(IR) vs 결과(모델러) 분리
|
||||
|
||||
### "웹앱이 느려요"
|
||||
→ 모델 정점 수 확인, LOD 적용, 번들 최적화
|
||||
|
||||
### "배포 실패"
|
||||
→ GitHub Actions 로그 확인, 환경 변수 설정 검사
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 날짜 | 내용 |
|
||||
|------|------|------|
|
||||
| 1.0 | 2026-10-16 | 초안 작성 (단계 3) |
|
||||
|
||||
---
|
||||
|
||||
## 라이선스
|
||||
|
||||
이 프로젝트는 [`docs/dwg2model-CLAUDE.md`](docs/dwg2model-CLAUDE.md)를 상속받는다.
|
||||
특히 `vendor/acadrust-dwg/` 의 **MPL-2.0** 라이선스를 준수해야 한다.
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
# DXF to 3D 웹앱 구현 고려사항
|
||||
|
||||
## 1. 가시설 도면의 특수성
|
||||
|
||||
### 1.1 구조적 특징
|
||||
- **모듈화**: 표준 부재 조합 → 조합 가능 옵션 제공
|
||||
- **임시성**: 설치/해체 순서 명시 필요
|
||||
- **안전성**: 구조 안정성 검증 필수 (처짐, 강도)
|
||||
- **확장성**: 설계 변경 쉬워야 함 (파라메트릭)
|
||||
|
||||
### 1.2 도면 특성
|
||||
- 평면도, 단면도, 상세도 조합
|
||||
- 치수 표기가 중심 (기하보다 수치 신뢰)
|
||||
- 레이어로 재질/용도 구분
|
||||
- 절단 기호로 단면 위치 명시
|
||||
|
||||
### 1.3 이전 도면(맨홀)과의 차이
|
||||
| 항목 | 맨홀 | 가시설 |
|
||||
|------|------|--------|
|
||||
| 목적 | 지하 구조물 | 임시 가설물 |
|
||||
| 부재 | 공사별 맞춤 | 표준 규격 + 조합 |
|
||||
| 검증 | 부피, 구조 | 구조, 안정성, 조립도 |
|
||||
| 변경 | 드물음 | 빈번 (설계 변경) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 기술 구현 전략
|
||||
|
||||
### 2.1 DXF 파싱 및 변환
|
||||
**결정**: 기존 dwg2model 파이프라인 재사용
|
||||
|
||||
- ✅ 검증된 파싱 로직
|
||||
- ✅ 기준점 자동 검출
|
||||
- ⚠️ 가시설 설정 파일 신규 작성 필요
|
||||
|
||||
**관리 항목**:
|
||||
```
|
||||
- 도면 좌표계 일치성 검증 (X, Y, Z 기준점)
|
||||
- 레이어 필터링 (구조선 vs 치수선)
|
||||
- 단위 설정 (mm vs m 자동 변환)
|
||||
```
|
||||
|
||||
### 2.2 3D 모델 생성
|
||||
**선택지**:
|
||||
1. EGModeler (egm CLI) - 기존 검증됨
|
||||
2. Open3D/PyMesh - 오픈소스, 더 가볍지만 테스트 필요
|
||||
3. Rhino.Compute - 클라우드 기반, 비용 발생
|
||||
|
||||
**추천**: EGModeler 지속 사용
|
||||
- 가장 안정적 (19개 교훈)
|
||||
- 부피/기하학 검증 자동화 완성
|
||||
- 이전 도면 사례와 비교 검증 가능
|
||||
|
||||
### 2.3 웹 시각화
|
||||
**요구사항**:
|
||||
- 실시간 3D 렌더링 (60fps 목표)
|
||||
- 부재 정보 표시 (클릭 시)
|
||||
- 단면/뷰 전환
|
||||
- 측정 기능 (거리, 면적)
|
||||
|
||||
**기술 선택**:
|
||||
| 라이브러리 | 크기 | 성능 | 학습곡선 | 선택 |
|
||||
|-----------|------|------|---------|------|
|
||||
| Three.js | 200KB | 매우 좋음 | 중간 | ✅ |
|
||||
| Babylon.js | 300KB | 좋음 | 높음 | △ |
|
||||
| Cesium.js | 1.2MB | 보통 | 높음 | ✗ |
|
||||
|
||||
**선택 이유**: Three.js
|
||||
- 가벼운 로드
|
||||
- 풍부한 예제
|
||||
- React 통합 용이 (drei)
|
||||
|
||||
### 2.4 웹앱 프레임워크
|
||||
```
|
||||
React (상태 관리, UI 컴포넌트)
|
||||
↓
|
||||
Vite (빠른 개발 & 빌드)
|
||||
↓
|
||||
Three.js + react-three-fiber (3D 렌더링)
|
||||
↓
|
||||
TypeScript (타입 안정성)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 품질 보증 전략
|
||||
|
||||
### 3.1 도면 검증 (단계별)
|
||||
```
|
||||
Level 1: 기본 파싱
|
||||
├─ 도면 로딩 성공
|
||||
├─ 엔티티 수 > 0
|
||||
└─ 기준점 감지 가능
|
||||
|
||||
Level 2: 기하학 검증
|
||||
├─ 뷰 폭/높이 vs 도면 치수 비교 (±2%)
|
||||
├─ 폐곡선 수 확인
|
||||
├─ 자기교차 감지
|
||||
└─ 좌표 범위 타당성
|
||||
|
||||
Level 3: 3D 모델 검증
|
||||
├─ 부피 오차 < 0.5%
|
||||
├─ 폐면 여부 (manifold)
|
||||
├─ 면 법선 방향
|
||||
└─ 경계 무결성
|
||||
|
||||
Level 4: 시각적 검증
|
||||
├─ 웹 렌더링 성공
|
||||
├─ 부재 식별 가능
|
||||
└─ 기본 상호작용 작동
|
||||
```
|
||||
|
||||
### 3.2 자동화 테스트
|
||||
```
|
||||
도면 → 설정 파일 → IR 생성 → 부피 계산 → 기준값 비교
|
||||
↓
|
||||
✅ 0.5% 이내 → PASS
|
||||
❌ 초과 → FAIL (알림)
|
||||
```
|
||||
|
||||
### 3.3 회귀 검증
|
||||
- 이전 도면(맨홀) 재처리 → 부피 일치 확인
|
||||
- 새 도면(가시설) 첫 처리 → 기준값 수립
|
||||
- 매 수정 후 부피 추적
|
||||
|
||||
---
|
||||
|
||||
## 4. 배포 전략
|
||||
|
||||
### 4.1 호스팅 선택
|
||||
```
|
||||
Vercel (추천)
|
||||
├─ Next.js/React 최적화
|
||||
├─ 무료 SSL
|
||||
├─ 자동 배포 (git 푸시)
|
||||
├─ 환경 변수 관리
|
||||
└─ 서버리스 함수 지원
|
||||
|
||||
Netlify (대안)
|
||||
├─ 마찬가지로 무료
|
||||
├─ Netlify Functions
|
||||
└─ 더 유연한 구성
|
||||
```
|
||||
|
||||
### 4.2 도메인
|
||||
- Freenom (완전 무료, .tk/.ml/.ga)
|
||||
- DNS 리다이렉트 → Vercel
|
||||
|
||||
### 4.3 CI/CD 파이프라인
|
||||
```
|
||||
git push
|
||||
↓
|
||||
GitHub Actions
|
||||
├─ 린트 & 타입 체크
|
||||
├─ 빌드 테스트
|
||||
├─ DXF 도면 검증
|
||||
└─ 부피 회귀 테스트
|
||||
↓
|
||||
Vercel 자동 배포
|
||||
├─ 프리뷰 URL 생성
|
||||
└─ 프로덕션 배포
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 사용자 경험 (UX)
|
||||
|
||||
### 5.1 핵심 기능
|
||||
1. **도면 업로드** → DXF 선택
|
||||
2. **자동 변환** → 진행 상황 표시
|
||||
3. **3D 뷰** → 회전, 줌, 패닝
|
||||
4. **부재 정보** → 클릭 시 표시
|
||||
5. **다운로드** → OBJ, IFC, 스크린샷
|
||||
|
||||
### 5.2 대시보드
|
||||
```
|
||||
┌─────────────────────────────┐
|
||||
│ DXF to 3D 변환기 │
|
||||
├─────────────────────────────┤
|
||||
│ 📁 업로드 │ 최근 변환 목록 │
|
||||
├──────────┼─────────────────┤
|
||||
│ 3D 뷰 │ 부재 정보 패널 │
|
||||
│ (Three.js)│ - 이름 │
|
||||
│ │ - 재질 │
|
||||
│ │ - 부피 │
|
||||
└──────────┴─────────────────┘
|
||||
```
|
||||
|
||||
### 5.3 모바일 반응형
|
||||
- 터치 제스처 (pinch zoom)
|
||||
- 모바일 레이아웃 최적화
|
||||
- 가로/세로 자동 전환
|
||||
|
||||
---
|
||||
|
||||
## 6. 보안 및 성능
|
||||
|
||||
### 6.1 보안
|
||||
- DXF 파일 크기 제한 (50MB)
|
||||
- 바이러스 스캔 (선택사항)
|
||||
- 개인정보 없음 (파일 자동 삭제)
|
||||
- HTTPS만 (Vercel 기본)
|
||||
|
||||
### 6.2 성능
|
||||
| 지표 | 목표 | 수단 |
|
||||
|------|------|------|
|
||||
| 로딩 | < 3초 | 번들 최적화, 이미지 압축 |
|
||||
| 렌더링 | 60fps | Three.js 최적화, LOD |
|
||||
| 변환 | < 10초 | 병렬 처리 (Worker) |
|
||||
|
||||
### 6.3 캐싱
|
||||
```
|
||||
정적 파일 → CDN 캐시 (1년)
|
||||
API 응답 → 메모리 캐시 (1시간)
|
||||
3D 모델 → 로컬스토리지 (세션)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 개발 일정 (추정)
|
||||
|
||||
| 단계 | 작업 | 기간 |
|
||||
|------|------|------|
|
||||
| 1 | 가시설 설정 파일 작성 | 2-3일 |
|
||||
| 2 | 웹앱 기본 구조 | 2-3일 |
|
||||
| 3 | Three.js 통합 | 2-3일 |
|
||||
| 4 | 품질 테스트 | 2-3일 |
|
||||
| 5 | 배포 & 도메인 | 1일 |
|
||||
|
||||
**전체**: ~2주 (병렬 처리 시)
|
||||
|
||||
---
|
||||
|
||||
## 8. 위험 요소 및 완화 방안
|
||||
|
||||
| 위험 | 영향 | 확률 | 완화 |
|
||||
|------|------|------|------|
|
||||
| DXF 파일 다양성 | 파싱 실패 | 중 | 설정 파일 테스트 |
|
||||
| 3D 모델 복잡도 | 웹 렌더링 느림 | 중 | LOD, 정점 최적화 |
|
||||
| 배포 시간 | 서비스 시작 지연 | 낮음 | 사전 인프라 준비 |
|
||||
| 유지보수 | 기술 부채 | 중 | 명확한 문서 & 테스트 |
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
# PLAN.md — 상세 계획 및 에이전트 역할
|
||||
|
||||
> **PROGRESS.md의 예정 항목을 상세히 풀어 쓴 것입니다.**
|
||||
> 각 단계 시작 전에 여기서 자신의 역할을 확인하세요.
|
||||
|
||||
---
|
||||
|
||||
## 전체 일정 (단계 4~9)
|
||||
|
||||
```
|
||||
단계 4 → 단계 5 → 단계 6 → 단계 7 → 단계 8 → 단계 9
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
계획 아이디어 구현 보강 병렬화 모델확정
|
||||
2일 2일 3일 1일 2일 1일
|
||||
(총 ~12일)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 단계 4: PROGRESS.md & PLAN.md 작성 ✅ (완료)
|
||||
|
||||
### 목표
|
||||
- PROGRESS.md: 진행 상황 추적용 (에이전트가 매 세션 읽기)
|
||||
- PLAN.md: 상세 계획 및 에이전트 역할 (이 파일)
|
||||
|
||||
### 완료 기준
|
||||
- [ ] PROGRESS.md 작성 (2026-10-16)
|
||||
- [ ] PLAN.md 작성 (지금)
|
||||
- [ ] 메모리에 저장
|
||||
|
||||
### 산출물
|
||||
- `PROGRESS.md`: 현재 상태, 완료 단계, 예정 항목
|
||||
- `PLAN.md`: 상세 계획 (이 파일)
|
||||
|
||||
---
|
||||
|
||||
## 단계 5: 에이전트/커맨드/스킬 아이디어 제안
|
||||
|
||||
### 목표
|
||||
Claude Code의 에이전트, 커맨드, 스킬, 훅 구조를 이해하고, 이 프로젝트에 필요한 것들을 제안한다.
|
||||
|
||||
### 작업 항목
|
||||
|
||||
#### 5.1 에이전트 설계
|
||||
```
|
||||
4개 에이전트 (병렬 처리 가능):
|
||||
|
||||
[Agent-Research]
|
||||
목적: 가시설 도면 분석 & 설정 파일 작성
|
||||
담당: DXF 파싱, 좌표 검증, 기하학 분석
|
||||
주요 스킬: Grep (도면 패턴 찾기), 계산
|
||||
입력: 원본 DXF 파일
|
||||
출력: src/drawings/gasiseol.mjs (설정 파일)
|
||||
|
||||
[Agent-Pipeline]
|
||||
목적: dwg2model 파이프라인 최적화 & 테스트
|
||||
담당: 빌드, 검증, 부피 측정
|
||||
주요 커맨드: node src/run.mjs, node src/build.mjs, node src/measure.mjs
|
||||
입력: 설정 파일 (src/drawings/gasiseol.mjs)
|
||||
출력: IR (중간 표현), 검증 리포트
|
||||
|
||||
[Agent-WebUI]
|
||||
목적: React 웹앱 & Three.js 통합
|
||||
담당: UI 컴포넌트, 3D 뷰어, API
|
||||
주요 기술: React, Three.js, TypeScript
|
||||
입력: 3D 모델 (OBJ/IFC)
|
||||
출력: 웹앱 (src/web/)
|
||||
|
||||
[Agent-Deploy]
|
||||
목적: CI/CD, 배포, 도메인 설정
|
||||
담당: GitHub Actions, Vercel, 도메인
|
||||
주요 도구: git, npm, gh CLI
|
||||
입력: 웹앱 소스 코드
|
||||
출력: 배포된 웹사이트 + 무료 도메인
|
||||
```
|
||||
|
||||
#### 5.2 커맨드 설계
|
||||
```
|
||||
프로젝트 특화 커맨드 (구현 예정):
|
||||
|
||||
/step-X 단계별 워크플로우 실행
|
||||
/validate 도면 & 3D 모델 자동 검증
|
||||
/convert DXF → 3D 한 번에 (3개 에이전트 병렬)
|
||||
/deploy 웹앱 배포 (CI/CD 자동)
|
||||
/report 진행 상황 & 검증 결과 리포트
|
||||
```
|
||||
|
||||
#### 5.3 스킬 설계
|
||||
```
|
||||
프로젝트 특화 스킬:
|
||||
|
||||
/dxf-analyze
|
||||
입력: DXF 파일
|
||||
출력: 도면 분석 리포트 (좌표 범위, 레이어, 엔티티 수)
|
||||
|
||||
/3d-validate
|
||||
입력: OBJ 또는 IFC 파일
|
||||
출력: 검증 리포트 (manifold, 부피, 면 수)
|
||||
|
||||
/web-dev
|
||||
입력: 3D 모델
|
||||
출력: 웹앱 로컬 서버 실행
|
||||
|
||||
/ci-setup
|
||||
입력: 저장소 설정
|
||||
출력: GitHub Actions 워크플로우 파일
|
||||
```
|
||||
|
||||
#### 5.4 훅 설계
|
||||
```
|
||||
자동 실행 훅 (settings.json):
|
||||
|
||||
[git commit 후]
|
||||
훅: 자동 검증
|
||||
→ node src/measure.mjs <도면> 실행
|
||||
→ 부피 변화 감지
|
||||
→ 문제 시 경고
|
||||
|
||||
[PROGRESS.md 수정 후]
|
||||
훅: 상태 반영
|
||||
→ 다음 세션에 알림
|
||||
|
||||
[배포 전]
|
||||
훅: 모든 테스트 통과 확인
|
||||
→ npm run test
|
||||
→ npm run lint
|
||||
→ node src/build.mjs --validate
|
||||
```
|
||||
|
||||
### 완료 기준
|
||||
- [ ] 4개 에이전트 정의 (이름, 목적, 담당, 입출력)
|
||||
- [ ] 5개 커맨드 아이디어 제안
|
||||
- [ ] 3개 스킬 아이디어 제안
|
||||
- [ ] 4개 훅 아이디어 제안
|
||||
- [ ] 사용자 승인 받기
|
||||
|
||||
### 산출물
|
||||
- 텍스트 문서 또는 이 파일 확장
|
||||
|
||||
### 의존성
|
||||
- 단계 4 완료 후
|
||||
|
||||
---
|
||||
|
||||
## 단계 6: Claude Code 구조 조사 및 정확한 포맷 구현
|
||||
|
||||
### 목표
|
||||
Claude Code의 공식 에이전트, 커맨드, 스킬, 훅 포맷을 학습하고, 단계 5의 아이디어를 정확한 포맷으로 구현한다.
|
||||
|
||||
### 작업 항목
|
||||
|
||||
#### 6.1 Claude Code 구조 조사
|
||||
```
|
||||
학습 대상:
|
||||
- .claude/agents/*.md 포맷 (에이전트 정의)
|
||||
- .claude/commands/*.yaml 포맷 (커맨드)
|
||||
- .claude/skills/*.yaml 포맷 (스킬)
|
||||
- settings.json hooks 포맷 (자동 실행)
|
||||
|
||||
공식 문서:
|
||||
- /help claude-code
|
||||
- /help agents
|
||||
- https://claude.com/claude-code (설명)
|
||||
```
|
||||
|
||||
#### 6.2 정확한 포맷으로 구현
|
||||
```
|
||||
폴더 구조:
|
||||
D:\Obsidian Vault\999ETC\261016_HW_DwfTo3D\.claude\
|
||||
├── agents/
|
||||
│ ├── dxf-research.md [Agent-Research]
|
||||
│ ├── pipeline-build.md [Agent-Pipeline]
|
||||
│ ├── web-ui-dev.md [Agent-WebUI]
|
||||
│ └── deploy-ci.md [Agent-Deploy]
|
||||
│
|
||||
├── commands/
|
||||
│ ├── step.yaml (/step-X)
|
||||
│ ├── validate.yaml (/validate)
|
||||
│ ├── convert.yaml (/convert)
|
||||
│ └── deploy.yaml (/deploy)
|
||||
│
|
||||
├── skills/
|
||||
│ ├── dxf-analyze.yaml (/dxf-analyze)
|
||||
│ ├── 3d-validate.yaml (/3d-validate)
|
||||
│ └── web-dev.yaml (/web-dev)
|
||||
│
|
||||
└── settings.json
|
||||
└── hooks: [자동 실행 규칙]
|
||||
```
|
||||
|
||||
#### 6.3 각 파일의 내용
|
||||
```
|
||||
agents/dxf-research.md:
|
||||
- name: 도면 분석 & 설정 파일
|
||||
- description: DXF 파일 파싱, 좌표 검증, 설정 파일 작성
|
||||
- tools: [Read, Edit, Write, Grep, Bash]
|
||||
- instructions: [...상세 지침...]
|
||||
|
||||
commands/convert.yaml:
|
||||
- name: convert
|
||||
- description: DXF → 3D 변환 (병렬 처리)
|
||||
- agents:
|
||||
- dxf-research (stage 1)
|
||||
- pipeline-build (stage 2)
|
||||
- web-ui-dev (stage 3)
|
||||
- sequential: false (병렬 실행)
|
||||
|
||||
skills/dxf-analyze.yaml:
|
||||
- 트리거: /dxf-analyze <파일>
|
||||
- 실행: Agent-Research 호출
|
||||
- 결과: 도면 분석 리포트
|
||||
```
|
||||
|
||||
### 완료 기준
|
||||
- [ ] .claude/ 폴더 구조 생성
|
||||
- [ ] 4개 에이전트 정의 파일 작성
|
||||
- [ ] 4개 커맨드 파일 작성
|
||||
- [ ] 3개 스킬 파일 작성
|
||||
- [ ] settings.json 훅 설정
|
||||
- [ ] 모든 파일 git 커밋
|
||||
|
||||
### 산출물
|
||||
```
|
||||
.claude/ 폴더 완성
|
||||
├── agents/ (4개 파일)
|
||||
├── commands/ (4개 파일)
|
||||
├── skills/ (3개 파일)
|
||||
└── settings.json (훅 포함)
|
||||
```
|
||||
|
||||
### 의존성
|
||||
- 단계 5 완료 + 아이디어 승인 후
|
||||
- Claude Code 공식 문서 학습 필요
|
||||
|
||||
---
|
||||
|
||||
## 단계 7: 추가 하네스 및 보강
|
||||
|
||||
### 목표
|
||||
Anthropic 엔지니어링 블로그의 "harness-design-long-running-apps" 자료를 읽고, 장기 실행 앱 설계를 프로젝트에 적용한다.
|
||||
|
||||
### 작업 항목
|
||||
|
||||
#### 7.1 하네스 개념 학습
|
||||
```
|
||||
읽을 자료:
|
||||
https://www.anthropic.com/engineering/harness-design-long-running-apps
|
||||
|
||||
학습 항목:
|
||||
- 에이전트 상태 관리
|
||||
- 장기 실행 작업의 진행률 추적
|
||||
- 오류 복구 전략
|
||||
- 단계별 검증 포인트
|
||||
```
|
||||
|
||||
#### 7.2 프로젝트에 적용
|
||||
```
|
||||
개선 사항:
|
||||
1. 에이전트 체크포인트
|
||||
- 각 에이전트의 중간 결과 저장
|
||||
- 실패 시 재개 가능
|
||||
|
||||
2. 진행 상황 실시간 추적
|
||||
- PROGRESS.md 자동 업데이트
|
||||
- 웹 대시보드 (옵션)
|
||||
|
||||
3. 롤백 가능성
|
||||
- git 커밋 포인트 명확
|
||||
- 문제 시 이전 버전 복구
|
||||
|
||||
4. 재시도 로직
|
||||
- 네트워크 오류 시 재시도
|
||||
- 지수 백오프
|
||||
```
|
||||
|
||||
#### 7.3 CLAUDE.md 업데이트
|
||||
```
|
||||
추가 내용:
|
||||
- 에이전트 체크포인트 정의
|
||||
- 오류 복구 절차
|
||||
- 진행 상황 모니터링
|
||||
- 롤백 가이드
|
||||
```
|
||||
|
||||
### 완료 기준
|
||||
- [ ] 하네스 설계 개념 문서 작성
|
||||
- [ ] 프로젝트 구조 다이어그램 (상태 관리)
|
||||
- [ ] CLAUDE.md 보강
|
||||
- [ ] 에이전트에 체크포인트 로직 추가
|
||||
|
||||
### 산출물
|
||||
- 보강된 CLAUDE.md
|
||||
- 하네스 설계 다이어그램
|
||||
- 각 에이전트의 체크포인트 정의
|
||||
|
||||
### 의존성
|
||||
- 단계 6 완료 후
|
||||
|
||||
---
|
||||
|
||||
## 단계 8: 동적 에이전트 + 병렬화 워크플로우 구현
|
||||
|
||||
### 목표
|
||||
복합 작업을 여러 에이전트가 병렬로 처리하는 워크플로우를 구현한다. 안정성을 유지하면서 속도를 높인다.
|
||||
|
||||
### 작업 항목
|
||||
|
||||
#### 8.1 병렬 처리 구조
|
||||
```
|
||||
사용자 입력
|
||||
↓
|
||||
Orchestrator 에이전트
|
||||
├─→ [Agent-Research]
|
||||
│ (DXF 분석, 설정 파일)
|
||||
│
|
||||
├─→ [Agent-Pipeline]
|
||||
│ (빌드, 검증)
|
||||
│ (Research 완료 대기)
|
||||
│
|
||||
└─→ [Agent-WebUI]
|
||||
(UI 개발)
|
||||
(Pipeline 완료 대기)
|
||||
|
||||
병렬화 규칙:
|
||||
- Research와 WebUI: 병렬 가능
|
||||
- Pipeline: Research 완료 후 시작
|
||||
- 최종 병합: 모든 에이전트 완료 대기
|
||||
```
|
||||
|
||||
#### 8.2 워크플로우 정의 (코드 또는 설정)
|
||||
```
|
||||
example: convert.yaml
|
||||
|
||||
stages:
|
||||
stage1:
|
||||
agents:
|
||||
- dxf-research
|
||||
parallel: false
|
||||
|
||||
stage2:
|
||||
agents:
|
||||
- pipeline-build
|
||||
depends_on: stage1
|
||||
parallel: false
|
||||
|
||||
stage3:
|
||||
agents:
|
||||
- web-ui-dev
|
||||
parallel: true (stage1과 동시)
|
||||
|
||||
stage4:
|
||||
agents:
|
||||
- orchestrator (병합)
|
||||
depends_on: [stage2, stage3]
|
||||
```
|
||||
|
||||
#### 8.3 안정성 보장
|
||||
```
|
||||
체크포인트 전략:
|
||||
- 각 stage 시작 전: 상태 저장
|
||||
- 각 stage 완료 후: 결과 검증
|
||||
- 실패 시: 해당 stage부터 재시작
|
||||
|
||||
타임아웃:
|
||||
- Research: 5분
|
||||
- Pipeline: 10분
|
||||
- WebUI: 10분
|
||||
- 전체: 30분
|
||||
|
||||
에러 처리:
|
||||
- 중단 불가: Research + WebUI (서로 독립)
|
||||
- 중단 가능: Pipeline 실패 → 전체 실패
|
||||
```
|
||||
|
||||
#### 8.4 모니터링 대시보드 (옵션)
|
||||
```
|
||||
실시간 추적:
|
||||
├─ 각 에이전트 진행률
|
||||
├─ 현재 병목 지점
|
||||
├─ 예상 완료 시간
|
||||
└─ 오류 알림
|
||||
|
||||
구현:
|
||||
- 웹 UI (React)
|
||||
- 또는 CLI 대시보드
|
||||
```
|
||||
|
||||
### 완료 기준
|
||||
- [ ] 워크플로우 YAML 정의
|
||||
- [ ] Orchestrator 에이전트 구현
|
||||
- [ ] 병렬 실행 테스트 (2회 이상)
|
||||
- [ ] 오류 복구 테스트
|
||||
- [ ] 모니터링 (CLI 또는 웹)
|
||||
|
||||
### 산출물
|
||||
- .claude/commands/convert.yaml (병렬 워크플로우)
|
||||
- Orchestrator 에이전트 구현
|
||||
- 워크플로우 다이어그램
|
||||
- 테스트 리포트
|
||||
|
||||
### 의존성
|
||||
- 단계 7 완료 후
|
||||
|
||||
---
|
||||
|
||||
## 단계 9: 모델 선택 확정
|
||||
|
||||
### 목표
|
||||
Haiku 4.5로 작업한 결과를 평가하고, 필요시 더 강력한 모델로 전환할지 결정한다.
|
||||
|
||||
### 작업 항목
|
||||
|
||||
#### 9.1 성능 평가
|
||||
```
|
||||
평가 항목:
|
||||
- 코드 품질 (정확성, 버그)
|
||||
- 개발 속도 (각 단계별 소요 시간)
|
||||
- 결과물 품질 (웹앱 기능성, 3D 정확도)
|
||||
- 비용 (Haiku 비용 vs 상위 모델)
|
||||
|
||||
기준:
|
||||
✅ Haiku 충분: 모든 항목 80점 이상
|
||||
△ 개선 필요: 1~2개 항목 60~80점
|
||||
❌ Haiku 부족: 2개 이상 항목 60점 미만
|
||||
```
|
||||
|
||||
#### 9.2 대안 평가
|
||||
```
|
||||
모델 선택지:
|
||||
|
||||
현재: Claude Haiku 4.5
|
||||
- 비용: 저 (토큰당 0.80/3.2)
|
||||
- 속도: 매우 빠름
|
||||
- 추론: 기본적 작업 우수
|
||||
|
||||
대안 1: Claude Sonnet 5
|
||||
- 비용: 중 (3/15)
|
||||
- 속도: 빠름
|
||||
- 추론: 복잡한 구조 이해 우수
|
||||
|
||||
대안 2: Claude Opus 5
|
||||
- 비용: 높음 (15/60)
|
||||
- 속도: 느림
|
||||
- 추론: 최고 수준
|
||||
```
|
||||
|
||||
#### 9.3 의사결정
|
||||
```
|
||||
선택 기준:
|
||||
|
||||
Haiku 유지:
|
||||
✓ 결과물 품질 만족
|
||||
✓ 개발 일정 충족
|
||||
✓ 비용 절감 (목표)
|
||||
|
||||
→ Sonnet 전환:
|
||||
✗ 정확도 부족 (3D 모델 오류)
|
||||
✗ 개발 지연 (단계별 시간 초과)
|
||||
✗ 특정 기술 이해 미흡
|
||||
|
||||
→ Opus 전환:
|
||||
✗ Sonnet도 부족한 경우만
|
||||
✗ 비용 대폭 증가
|
||||
```
|
||||
|
||||
### 완료 기준
|
||||
- [ ] 1단계별 소요 시간 기록
|
||||
- [ ] 코드 품질 평가 (린트, 테스트)
|
||||
- [ ] 3D 모델 정확도 검증
|
||||
- [ ] 웹앱 기능 평가
|
||||
- [ ] 최종 모델 결정
|
||||
|
||||
### 산출물
|
||||
- 평가 리포트 (성능 지표)
|
||||
- 모델 선택 의사결정 문서
|
||||
|
||||
### 의존성
|
||||
- 단계 8 완료 + 전체 구현 완료 후
|
||||
|
||||
---
|
||||
|
||||
## 크리티컬 패스
|
||||
|
||||
```
|
||||
단계 5 (아이디어)
|
||||
↓
|
||||
단계 4 (계획) → 단계 6 (구현) → 단계 7 (보강)
|
||||
↓ ↓
|
||||
단계 8 (병렬화)
|
||||
↓
|
||||
단계 9 (평가)
|
||||
|
||||
병목:
|
||||
- 단계 5→6: 포맷 학습 (1일)
|
||||
- 단계 6→7: 구조 확정 (1일)
|
||||
- 단계 8: 병렬 안정성 (2일)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 리스크 및 완화책
|
||||
|
||||
| 단계 | 리스크 | 완화책 |
|
||||
|------|--------|--------|
|
||||
| 5 | 아이디어 과다 | 핵심만 4개 에이전트로 제한 |
|
||||
| 6 | 포맷 불일치 | 공식 문서 읽고 예제 확인 |
|
||||
| 7 | 복잡도 증가 | 단계별 검증점 명확 |
|
||||
| 8 | 병렬 관리 어려움 | Orchestrator 패턴 활용 |
|
||||
| 9 | 모델 전환 비용 | 초기 평가 명확 기준 설정 |
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 날짜 | 내용 |
|
||||
|------|------|------|
|
||||
| 1.0 | 2026-10-16 | 초안 (단계 4) |
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
# PROGRESS.md — 프로젝트 진행 상황
|
||||
|
||||
> **매 세션마다 업데이트하세요.**
|
||||
> 에이전트는 이 파일을 읽고 현재 상태를 파악합니다.
|
||||
|
||||
---
|
||||
|
||||
## 현재 상태 (2026-10-16)
|
||||
|
||||
### ✅ 완료된 단계
|
||||
- **단계 0**: 리마인드 및 절차 확인
|
||||
- **단계 1**: 웹 조사 + 기술 선택
|
||||
- 기존 dwg2model 파이프라인 검증
|
||||
- 가시설 도면 샘플 확인 (7개 DXF 파일)
|
||||
- 에이전트 역할 정의 (4개)
|
||||
|
||||
- **단계 2**: 고려사항 분석
|
||||
- CONSIDERATIONS.md 작성 (8개 영역)
|
||||
- 기술 스택 결정 (Three.js, React, Vite)
|
||||
- 품질 기준 수립 (4단계 검증)
|
||||
- 배포 전략 정의 (Vercel + 무료 도메인)
|
||||
|
||||
- **단계 3**: 프로젝트 가이드 작성
|
||||
- CLAUDE.md 완성 (프로젝트 구조, 워크플로우)
|
||||
|
||||
### 🔄 진행 중
|
||||
- 단계 4: PROGRESS.md & PLAN.md 작성 (현재)
|
||||
|
||||
### ⏳ 예정
|
||||
- **단계 4**: PROGRESS.md & PLAN.md 작성
|
||||
- **단계 5**: 에이전트/커맨드/스킬 아이디어 수집
|
||||
- **단계 6**: Claude Code 구조 조사 후 정확한 포맷으로 구현
|
||||
- **단계 7**: 추가 넘침 및 하네스 설계 학습
|
||||
- **단계 8**: 동적 에이전트 + 병렬화 워크플로우 구현
|
||||
- **단계 9**: 모델 선택 확정
|
||||
|
||||
---
|
||||
|
||||
## 산출물 목록
|
||||
|
||||
### 생성된 파일
|
||||
```
|
||||
D:\Obsidian Vault\999ETC\261016_HW_DwfTo3D\
|
||||
├── CONSIDERATIONS.md (단계 2 결과)
|
||||
├── CLAUDE.md (단계 3 결과)
|
||||
├── PROGRESS.md (이 파일)
|
||||
└── PLAN.md (작성 예정)
|
||||
```
|
||||
|
||||
### 메모리 저장
|
||||
```
|
||||
C:\Users\User\.claude\projects\d--Obsidian-Vault-999ETC-261016_HW_DwfTo3D\memory\
|
||||
├── MEMORY.md
|
||||
├── project_dxf_to_3d.md
|
||||
├── feedback_project_process.md
|
||||
└── step1_findings.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 주요 결정사항
|
||||
|
||||
| 항목 | 결정 | 근거 |
|
||||
|------|------|------|
|
||||
| **DXF 파싱** | dwg2model 재사용 | 검증됨, 19개 교훈 |
|
||||
| **3D 시각화** | Three.js | 가볍고 React 통합 용이 |
|
||||
| **웹앱** | React + Vite | 개발 속도, 번들 크기 |
|
||||
| **배포** | Vercel | React 최적화, CI/CD 자동 |
|
||||
| **호스팅** | Freenom + 커스텀 도메인 | 완전 무료 |
|
||||
| **모델** | Haiku 4.5 | 제약 조건 (능력 검증 목적) |
|
||||
|
||||
---
|
||||
|
||||
## 알려진 위험 및 완화책
|
||||
|
||||
| 위험 | 영향 | 완화 방안 |
|
||||
|------|------|----------|
|
||||
| DXF 파일 형식 다양성 | 파싱 실패 | 설정 파일 사전 작성 & 테스트 |
|
||||
| 3D 모델 복잡도 | 웹 렌더링 느림 | LOD, 정점 최적화 |
|
||||
| 새 기술 통합 (Three.js) | 학습 곡선 | 기존 예제 활용, react-three-fiber |
|
||||
| 무료 도메인 신뢰도 | 사용자 진입 난색 | 정식 도메인으로 전환 옵션 |
|
||||
|
||||
---
|
||||
|
||||
## 다음 세션 체크리스트
|
||||
|
||||
### 시작 전 (읽기 전용)
|
||||
- [ ] CLAUDE.md 빠른 참조 확인
|
||||
- [ ] 이 파일(PROGRESS.md) 전체 읽기
|
||||
- [ ] PLAN.md 읽어서 에이전트 역할 파악
|
||||
|
||||
### 작업 시작 시
|
||||
- [ ] 단계 리마인드 (이번 단계 목표 명시)
|
||||
- [ ] 작업 수행 (git 커밋 포함)
|
||||
- [ ] 검증 (문제 확인)
|
||||
- [ ] PROGRESS.md 업데이트
|
||||
|
||||
---
|
||||
|
||||
## 메모 및 교훈
|
||||
|
||||
### 성공한 접근법
|
||||
- ✅ 기존 프로젝트(dwg2model) 활용 → 6개월치 실패 경험 활용 가능
|
||||
- ✅ 사전 계획 문서 작성 → 에이전트 지침 명확
|
||||
- ✅ 단계별 리마인드 → 의도하지 않은 실수 방지
|
||||
|
||||
### 주의할 점
|
||||
- ⚠️ 19개 교훈(2d-3d-conversion.md) 필독 필수
|
||||
- ⚠️ src/core/* 에 도면 고유값 절대 금지
|
||||
- ⚠️ 단계 4 완료 전에 셋업 시작하지 말 것
|
||||
|
||||
---
|
||||
|
||||
## 이전 세션 기록
|
||||
|
||||
### 2026-10-16 (초기화)
|
||||
- 작업지시서.md 읽음
|
||||
- 프로젝트 메모리 생성
|
||||
- 단계 0~3 완료
|
||||
- CLAUDE.md 작성
|
||||
|
||||
---
|
||||
|
||||
## 문의 및 피드백
|
||||
|
||||
문제 발생 시:
|
||||
1. CLAUDE.md "트러블슈팅" 절 확인
|
||||
2. `docs/2d-3d-conversion.md` 교훈 검색
|
||||
3. CONSIDERATIONS.md 재검토
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,524 @@
|
||||
# 2D → 3D 제작 과정
|
||||
|
||||
DWG 도면 한 벌을 3D 솔리드로 세우기까지 **실제로 무엇을 어떤 순서로 했는지**를
|
||||
기록한다. 다른 프로젝트로 옮길 때 이 문서만 따라가면 재현된다.
|
||||
|
||||
- 판단의 근거·함정·교훈은 [`2d-3d-conversion.md`](2d-3d-conversion.md) 에 따로 있다.
|
||||
이 문서는 **절차**, 그 문서는 **왜 그렇게 하는가**.
|
||||
- 코드: [`src/`](../src/)
|
||||
- 대상: `drawings-src/04manhole1-simplify.dwg` (맨홀 #1 및 출입구 일반도, 4매)
|
||||
|
||||
---
|
||||
|
||||
## 0. 준비물
|
||||
|
||||
| 항목 | 이 프로젝트에서의 위치 | 옮길 때 확인할 것 |
|
||||
|---|---|---|
|
||||
| DWG 파서 | `vendor/acadrust-dwg/` (wasm, read-only) | wasm 파일 2개(`.js`, `_bg.wasm`)를 같이 옮긴다 |
|
||||
| Node | 18+ (ESM, top-level await 사용) | — |
|
||||
| 3D 툴 | EGModeler + `egm` CLI (`D:\GiteaAll\EG-BIM_Modeler`) | 앱이 **실행 중**이어야 한다. `egm status` 로 확인 |
|
||||
| Python | 3.10+ (`src/run_egm.py`) | 표준 라이브러리만 쓴다 |
|
||||
|
||||
`egm` 은 Named Pipe 로 실행 중인 EGModeler 에 명령을 보내는 CLI 다.
|
||||
연결 확인:
|
||||
|
||||
```sh
|
||||
egm status # {"command":null,"modelCount":0,"selectedCount":0}
|
||||
```
|
||||
|
||||
`EGModeler가 실행 중이지 않거나 응답하지 않습니다.` 가 나오면 앱을 먼저 띄운다.
|
||||
|
||||
**`status` 가 응답한다고 모델링이 되는 건 아니다.** 뷰어 모드면 모델링 명령이
|
||||
등록조차 안 된 채로 파이프만 살아 있다. 등록된 명령 개수로 가른다.
|
||||
|
||||
```sh
|
||||
egm guide | python -c "import sys,json;print(len(json.load(sys.stdin)))"
|
||||
# 39 → 뷰어 모드. Polyline·Extrude·Boolean* 이 통째로 없다. 모델링 불가
|
||||
# 207 → 정상
|
||||
```
|
||||
|
||||
39 이 나오면 모델러 UI 에서 **Edit Mode** 로 바꾼다 (View Mode / Edit Mode 토글).
|
||||
Assistive Features 의 `ModelerMode` 와는 다른 값이다. 자세한 배경은
|
||||
[`2d-3d-conversion.md`](2d-3d-conversion.md) 교훈 #15.
|
||||
|
||||
---
|
||||
|
||||
## 1. 전체 흐름
|
||||
|
||||
```
|
||||
DWG ─parse─→ 엔티티 ─segment─→ 뷰 ─datum─→ 프로젝트좌표 ─loops─→ 프로파일
|
||||
│
|
||||
조립 스펙 (IR, JSON)
|
||||
↙ ↓ ↘
|
||||
egm IFC three.js
|
||||
```
|
||||
|
||||
명령 4개로 끝난다.
|
||||
|
||||
```sh
|
||||
cd src
|
||||
|
||||
node src/run.mjs manhole1 # ① 파싱 · 기준점 · 뷰 분리 → out/manhole1.views.json
|
||||
node src/build.mjs manhole1 # ② 프로파일 추출 · 조립 → out/manhole1.ir.json
|
||||
node src/emit/egm.mjs out/manhole1.ir.json # ③ 모델러 명령으로 번역 → out/manhole1.egm.json
|
||||
python src/run_egm.py out/manhole1.egm.json # ④ 실행
|
||||
```
|
||||
|
||||
`src/run.mjs` 는 검증이 깨지면 **종료 코드 1** 을 낸다. CI 게이트로 바로 쓸 수 있다.
|
||||
|
||||
---
|
||||
|
||||
## 2. 단계별 절차
|
||||
|
||||
### ① 파싱 · 기준점 · 뷰 분리 — `src/run.mjs`
|
||||
|
||||
```sh
|
||||
node src/run.mjs manhole1 # 산출물까지 저장
|
||||
node src/run.mjs manhole1 --report # 검증표만 출력
|
||||
```
|
||||
|
||||
출력 예:
|
||||
|
||||
```
|
||||
도면 manhole1 — R2018, 엔티티 7035
|
||||
|
||||
표고 기준선 DWG y = 483623.47666155506 (뷰 11곳에 반복, 총연장 61492mm)
|
||||
✓ B-B 구체 상단 실측 -4907 도면 -4907
|
||||
✓ B-B 기초 하단 실측 -7757 도면 -7757
|
||||
✓ B-B 잡석 하단 실측 -8057 도면 -8057
|
||||
✓ D-D 구체 상단 실측 -4907 도면 -4907
|
||||
|
||||
뷰 kind 조각 선 폭mm 높이mm Z 범위
|
||||
평 면 도 plan 1 72 20200 10200 -1478 ~ -11678 ✓
|
||||
단 면 A-A long 2 123 20200 10839 232 ~ -10607
|
||||
...
|
||||
✓ 검증 통과 — 뷰 분리와 표고 기준이 도면 치수와 일치
|
||||
```
|
||||
|
||||
**이 단계를 통과하지 못하면 다음으로 가지 않는다.** 여기서 틀린 채로 3D 를
|
||||
세우면 어디가 원인인지 알 수 없게 된다.
|
||||
|
||||
문제가 나오면:
|
||||
|
||||
| 증상 | 확인 도구 |
|
||||
|---|---|
|
||||
| 뷰가 없다 / 크기가 안 맞는다 | `node src/inspect.mjs manhole1 "<뷰>"` — 그 영역의 모든 엔티티를 레이어 무관하게 훑는다 |
|
||||
| 기준점 검증 실패 | `datum.checks` 의 레이어 이름이 맞는지, 계획고 선이 `layers.ground` 에 잡히는지 |
|
||||
|
||||
### ② 프로파일 추출 · 조립 — `src/build.mjs`
|
||||
|
||||
```sh
|
||||
node src/build.mjs manhole1 --loops # 뷰별 폐곡선 목록 (조립 스펙 작성용)
|
||||
node src/build.mjs manhole1 # IR 생성
|
||||
```
|
||||
|
||||
`--loops` 출력이 조립 스펙을 쓰는 **재료 목록**이다.
|
||||
|
||||
```
|
||||
단 면 B-B (cross)
|
||||
# 0 2700× 2750 bbox[-1350..1350, -7657..-4907] 꼭짓점 4 부모 -
|
||||
# 1 2100× 2150 bbox[-1050..1050, -7357..-5207] 꼭짓점 10 부모 #0
|
||||
# 2 4300× 300 bbox[-2150..2150, -8057..-7757] 꼭짓점 4 부모 -
|
||||
# 3 2900× 100 bbox[-1450..1450, -7757..-7657] 꼭짓점 4 부모 -
|
||||
```
|
||||
|
||||
폭×높이가 도면 표기 치수와 일치하는지 먼저 눈으로 확인한다. 여기가 맞으면
|
||||
그 뒤는 거의 틀리지 않는다.
|
||||
|
||||
한 뷰만 자세히 보려면:
|
||||
|
||||
```sh
|
||||
node src/probe.mjs manhole1 "단 면 B-B" # 표
|
||||
node src/probe.mjs manhole1 "단 면 B-B" --ring # 꼭짓점 좌표까지
|
||||
```
|
||||
|
||||
### ③ 모델러 명령으로 번역 — `src/emit/egm.mjs`
|
||||
|
||||
IR 의 연산을 egm 명령으로 바꾼다. 여기서만 egm 의 사정을 안다.
|
||||
|
||||
```
|
||||
extrude → Polyline(닫힌 커브) → SelByUids → Extrude C=True D F {벡터}
|
||||
loft → 단면마다 Polyline → SelByUids(단면 순서대로) → Loft C=True Enter
|
||||
box → Box {대각1} {대각2} {높이}
|
||||
difference → SelByUids(base) → SelByUids(A=true, cutters) → BooleanDifference
|
||||
union → SelByUids(첫째) → SelByUids(A=true, 나머지) → BooleanUnion
|
||||
```
|
||||
|
||||
`Loft` 는 기본이 **서피스**라 `C=True`(Cap)로 막아야 솔리드가 나온다.
|
||||
단면 커브는 `L`(DeleteOriginal, 기본 true)로 자동 삭제된다. 별도 `Cap` 명령은
|
||||
제자리 수정이라 새 uid 가 안 나오므로 여기서는 못 쓴다.
|
||||
|
||||
### ④ 실행 — `src/run_egm.py`
|
||||
|
||||
```sh
|
||||
python src/run_egm.py out/manhole1.egm.json # 실행
|
||||
python src/run_egm.py out/manhole1.egm.json --dry # 보내지 않고 명령만 출력
|
||||
```
|
||||
|
||||
`--dry` 로 좌표를 먼저 검산하는 습관을 들이면 모델러를 왕복하지 않아도 된다.
|
||||
|
||||
```
|
||||
[ 0] duct.solid — extrude
|
||||
egm ~Polyline 0,-1.9,-7.757 0,1.9,-7.757 0,1.9,-3.157 0,-1.9,-3.157 0,-1.9,-7.757
|
||||
egm ~SelByUids A=false <duct.solid$crv> Esc
|
||||
egm ~Extrude C=True D F 0,0,0 15.4,0,0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 새 도면을 추가하는 절차
|
||||
|
||||
**코드는 건드리지 않는다.** `src/drawings/` 에 파일 하나만 추가한다.
|
||||
|
||||
### 3.1 뼈대 만들기
|
||||
|
||||
`src/drawings/manhole1.mjs` 를 복사해 이름을 바꾸고 `dwg` 경로를 고친다.
|
||||
`layers` / `titles.views` 는 일단 대충 채우고 ①을 돌린다.
|
||||
|
||||
### 3.2 레이어 알아내기
|
||||
|
||||
```sh
|
||||
node src/run.mjs <도면> --report # 일단 실패해도 좋다
|
||||
node src/inspect.mjs <도면> "<뷰>" # 그 영역의 레이어 실태
|
||||
```
|
||||
|
||||
`src/inspect.mjs` 는 레이어 필터를 무시하고 전부 보여준다. 여기서
|
||||
구조체 외곽선이 어느 레이어에 있는지 눈으로 고른다.
|
||||
|
||||
### 3.3 레이어를 세 갈래로 나눈다
|
||||
|
||||
```js
|
||||
layers: {
|
||||
struct: /…/, // 뷰 분리용. 넉넉하게. 가구·주기까지 들어가도 된다
|
||||
body: /…/, // 구체 프로파일용. 좁게. 케이블랙 같은 가구는 빼야 한다
|
||||
material: /…/, // 기초·잡석·보도 등 별개 재료. 프로파일 추출엔 함께 넣는다
|
||||
ground: /…/, // 계획고·GL 선. 표고 기준 검출용
|
||||
}
|
||||
```
|
||||
|
||||
`body ⊆ struct` 는 코드가 강제한다(`src/run.mjs`). 어겨도 조용히 틀리지 않는다.
|
||||
|
||||
### 3.4 표고 기준 잡기
|
||||
|
||||
```js
|
||||
datum: {
|
||||
levelLabel: /도로\s*계획고/, // 기준선을 찾는 힌트. 값은 선에서 가져온다
|
||||
checks: [ // 도면 치수와 대조. 최소 2개
|
||||
['B-B 구체 상단', (v) => v['단 면 B-B']?.layerZ['-전력구']?.[1], -4907],
|
||||
['B-B 기초 하단', (v) => v['단 면 B-B']?.layerZ['!-기초']?.[0], -7757],
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
`layerZ[레이어] = [최저 Z, 최고 Z]`. 도면에 적힌 치수를 그대로 넣는다.
|
||||
|
||||
### 3.5 뷰별 앵커 잡기
|
||||
|
||||
각 뷰의 u(가로) 좌표 중 무엇이 프로젝트 0 인지 정한다.
|
||||
`--loops` 로 폐곡선 bbox 를 보고 도면 치수와 맞춰가며 찾는다.
|
||||
|
||||
```js
|
||||
anchors: {
|
||||
'평 면 도': { u0: 1000 }, // u → X
|
||||
'단 면 B-B': { u0: 2150 }, // u → Y (중심선)
|
||||
'단 면 F-F': { u0: -14700 }, // XZ 단면
|
||||
'단 면 H-H': { u0: 1900, v0: -17125, swapUV: true }, // 수평 단면
|
||||
}
|
||||
```
|
||||
|
||||
| 옵션 | 뜻 |
|
||||
|---|---|
|
||||
| `u0` | 가로축 원점. `프로젝트 = u - u0` |
|
||||
| `v0` | 세로축 원점. 수직 단면은 생략(표고가 이미 기준) |
|
||||
| `flip` / `flipV` | 축 방향이 반대일 때 |
|
||||
| `swapUV` | 도면 가로축이 프로젝트 Y, 세로축이 X 일 때 (수평 단면) |
|
||||
|
||||
### 3.6 조립 스펙 쓰기
|
||||
|
||||
파이프라인에서 **사람 판단이 들어가는 유일한 자리**다.
|
||||
|
||||
```js
|
||||
assemble({ loop, profile, part, rect, expect }) {
|
||||
profile('duct.outer', 'YZ', loop('단 면 B-B', 2700, 2750).ring);
|
||||
part({ id: 'duct.solid', op: 'extrude', profile: 'duct.outer', axis: 'X',
|
||||
from: 0, to: 15400, cap: true, keep: false });
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
| 도우미 | 용도 |
|
||||
|---|---|
|
||||
| `loop(뷰, 폭, 높이)` | 그 치수의 폐곡선을 집는다. 0개나 2개 이상이면 예외 |
|
||||
| `profile(id, 평면, ring)` | 프로파일 등록. 평면은 `'XY' \| 'XZ' \| 'YZ'` |
|
||||
| `part({...})` | 파트 추가 |
|
||||
| `rect(u0,v0,u1,v1)` | 직사각 프로파일. 폐곡선이 인접 형상과 붙어 못 쓸 때 |
|
||||
| `expect(뷰, 폭, 높이, 이유)` | 그 폐곡선이 실재하는지 확인만. `rect` 값 교차검증용 |
|
||||
|
||||
IR 연산:
|
||||
|
||||
| op | 필드 |
|
||||
|---|---|
|
||||
| `box` | `min:[x,y,z]`, `max:[x,y,z]` |
|
||||
| `extrude` | `profile`, `axis`, `from`, `to`, `cap` |
|
||||
| `union` | `members:[id,…]` |
|
||||
| `difference` | `base`, `cutters:[id,…]` |
|
||||
| `loft` | `sections:[{profile, at},…]` — `at` 은 평면 법선축 위 위치 |
|
||||
|
||||
**loft 는 꺾인 자리를 못 만든다.** 두 단면 사이를 곧게 이을 뿐이라, 형상이
|
||||
꺾이는 X 마다 단면을 놓고 구간을 끊어야 한다. 단면은 2개씩만 쓴다 — 3개
|
||||
이상이면 스플라인 보간으로 부푼다. 두 단면은 **꼭짓점 수가 같아야** 하고,
|
||||
링 정규화는 `addProfile` 이 자동으로 한다. 자세한 배경은
|
||||
[`2d-3d-conversion.md`](2d-3d-conversion.md) 교훈 #16.
|
||||
|
||||
`keep: false` 는 boolean 에 소모될 중간 파트. 최종 산출물에만 `name`/`color` 를 준다.
|
||||
|
||||
---
|
||||
|
||||
## 4. 이 도면에서 실제로 만든 것
|
||||
|
||||
### 4.1 좌표계
|
||||
|
||||
```
|
||||
X = 전력구 길이방향, 0 = 구조물 최좌단
|
||||
Y = 폭방향, 0 = 전력구 중심선
|
||||
Z = 표고, 0 = 도로 계획고 (DWG y = 483623.477, 자동 검출)
|
||||
단위 = 내부 mm 정수, egm 넘길 때만 m
|
||||
```
|
||||
|
||||
### 4.2 구간 구성 (A-A 종단면에서 읽음)
|
||||
|
||||
```
|
||||
X -1,000 ~ 0 입구 스터브 B-B 구체 2,700×2,750
|
||||
X 0 ~ 15,400 전력구 본체 C-C 구체 3,800×4,600 / 내부 3,000×3,800
|
||||
X 1,900 ~ 3,200 사다리 샤프트 1 Z -3,157 ~ 0
|
||||
X 12,600 ~ 13,900 사다리 샤프트 2 Z -3,157 ~ -39
|
||||
X 15,400 ~ 18,200 맨홀 #2 Z -10,007 ~ +182, Y -1,900 ~ 8,300
|
||||
X 18,200 ~ 19,200 출구 스터브 B-B
|
||||
```
|
||||
|
||||
### 4.3 뷰 ↔ 부재 대응
|
||||
|
||||
| 뷰 | 평면 | 쓰인 곳 |
|
||||
|---|---|---|
|
||||
| 평 면 도 | XY | X 구간 확정, 샤프트 위치, 환기구 footprint |
|
||||
| 단 면 A-A | XZ | **구간 배정표** — 어디서 어디까지 어느 단면인지 |
|
||||
| 단 면 B-B / D-D | YZ | 스터브 단면 (2,700×2,750) |
|
||||
| 단 면 C-C | YZ | 전력구 본체 단면 (3,800×4,600) |
|
||||
| 단 면 E-E | YZ | 맨홀 전체 (챔버·격실·환기구 다리) |
|
||||
| 단 면 F-F / G-G | XZ | 환기구 X 벽, 기초·잡석 |
|
||||
| 단 면 H-H | XY | 환기 OPEN부 개구 (1.2×2.0) |
|
||||
| 단 면 I-I | XY | 집수정 점검구 개구 (1.2×1.0) |
|
||||
| 단 면 J-J | XY | 침사조·집수조 평면 (E-E 교차검증) |
|
||||
|
||||
### 4.4 최종 산출 파트
|
||||
|
||||
```
|
||||
● 맨홀1_전력구_구체 스터브+본체 union 후 공동 차감
|
||||
● 맨홀1_전력구_기초 4,000 × 100 fck=18MPa
|
||||
● 맨홀1_전력구_잡석 5,400 × 500
|
||||
● 맨홀1_전력구_출구스터브
|
||||
● 맨홀1_사다리샤프트_1 / _2
|
||||
● 맨홀1_맨홀2_구체 봉투 union 후 공동·개구부 차감
|
||||
● 맨홀1_맨홀2_기초 / _잡석
|
||||
● 맨홀1_환기구_기초 / _잡석
|
||||
```
|
||||
|
||||
트리 이름은 `대분류_중분류_소분류` 형식이라 ObjectTreeViewer 에서 자동 그룹화된다.
|
||||
|
||||
---
|
||||
|
||||
## 5. 검증 절차
|
||||
|
||||
3D 를 세우기 **전에** 아래를 순서대로 통과시킨다. 한 단계라도 건너뛰면
|
||||
나중에 어디가 원인인지 추적이 불가능해진다.
|
||||
|
||||
```
|
||||
0. egm guide | wc -l 뷰어 모드가 아닌가 (39 면 뷰어 — 모델링 불가)
|
||||
1. node src/run.mjs <도면> 지반선 Z 가 전 뷰에서 일치하는가
|
||||
기준점이 도면 치수 2개 이상과 맞는가
|
||||
뷰 폭·높이가 도면 치수와 맞는가
|
||||
2. node src/gaps.mjs <도면> 프로파일이 안 닫히는 곳이 있는가
|
||||
원인이 레이어 오분류인가 선 누락인가
|
||||
3. node src/build.mjs <도면> --loops
|
||||
폐곡선 치수가 도면 표기와 맞는가
|
||||
node src/build.mjs <도면> --circles
|
||||
원 지름이 도면 표기(Ø900·Ø100)와 맞는가
|
||||
node src/report.mjs <도면> → out/<도면>.html
|
||||
**자기교차 링이 있는가** (있으면 압출부터 쓰레기다)
|
||||
링을 그림으로 확인. 표로는 못 보이는 것이 보인다
|
||||
4. node src/build.mjs <도면> IR 검증 (참조 무결성, 소모 파트 keep 플래그)
|
||||
5. python run_egm.py ... --dry
|
||||
좌표가 예상대로 나오는가
|
||||
6. python run_egm.py ... --export=out/<도면>.obj
|
||||
실행 + OBJ 내보내기
|
||||
7. egm status modelCount 가 최종 파트 수와 같은가
|
||||
8. node src/measure.mjs <도면> --ir
|
||||
의도(IR 격자 평가) vs 결과(모델러 OBJ) 대조
|
||||
+ 기준선 (실패 시 exit 1)
|
||||
```
|
||||
|
||||
7 이 어긋나면 boolean 이 인자를 흘린 것이다 (교훈 #14). 형상만 봐서는 못 잡는다 —
|
||||
남은 커터 솔리드가 구체와 겹쳐 있어 겉보기엔 멀쩡하다.
|
||||
|
||||
### 꼭짓점 수를 먼저 본다
|
||||
|
||||
`--loops` 출력에서 **직사각형이어야 할 것이 4가 아니면 의심**한다. 링이 오염됐다는
|
||||
신호다. 이 도면에서 실제로 나온 값:
|
||||
|
||||
```
|
||||
꼭짓점 4 정상 직사각형
|
||||
꼭짓점 10 헌치(150×150)가 있는 정상 형상
|
||||
꼭짓점 8 개구 기호(X 표시)가 사각형 안을 가로질러 링이 자기교차
|
||||
꼭짓점 114 케이블 지지대가 프로파일 레이어에 섞임
|
||||
```
|
||||
|
||||
링이 오염됐으면 **bbox 는 여전히 정확하므로** `rect()` 로 재구성하고
|
||||
`expect()` 로 치수만 확인한다.
|
||||
|
||||
### 부피를 대조한다 — `src/measure.mjs`
|
||||
|
||||
비틀린 loft 는 형상만 봐서는 못 잡는다. 부피가 어긋나는 것으로만 드러난다.
|
||||
|
||||
```sh
|
||||
python src/run_egm.py out/manhole1-trans.egm.json --export=out/manhole1-trans.obj
|
||||
node src/measure.mjs manhole1-trans # 기준선 대조 (실패 시 exit 1)
|
||||
node src/measure.mjs manhole1-trans --save # 지금 값을 기준선으로 얼린다
|
||||
node src/measure.mjs manhole1-trans --primitives # IR 원시 파트 부피표도
|
||||
```
|
||||
|
||||
OBJ 삼각형을 발산 정리로 잰다. `~SetObjectName` 으로 붙인 이름이 OBJ 의 `g` 로
|
||||
나오므로 파트 대조가 이름 하나로 끝난다. 나오는 것:
|
||||
|
||||
```
|
||||
파트 부피 m³ 표면적 m² 삼각형 열린변 재질
|
||||
맨홀1_전력구_구체 100.5403 507.471 10862 28 구체 콘크리트 fck=27MPa
|
||||
맨홀1_사다리샤프트_1 3.3217 28.356 3127 13 …
|
||||
합계 107.1425
|
||||
```
|
||||
|
||||
**IR 에 없는 그룹이 나오면 boolean 이 인자를 흘린 것이다** — `modelCount` 대조와
|
||||
같은 신호인데 어느 커터가 남았는지까지 알려준다.
|
||||
|
||||
`열린변`은 다양체 여부다. 이음매를 맞대어 붙이면 양쪽 삼각분할이 달라 T 정점이
|
||||
남는다(교훈 #16). 부피·렌더링에는 문제가 없지만 IFC 로 갈 때 걸릴 수 있다.
|
||||
|
||||
#### 기준선은 `baselines/` 에 두고 **커밋한다**
|
||||
|
||||
`out/` 과 달리 재생성으로 복구되지 않는다. 사람이 한 번 확인한 부피가 남아야
|
||||
다음 변경이 형상을 건드렸는지 알 수 있다.
|
||||
|
||||
#### 기대값은 자동으로 안 나온다 — 그리고 그게 맞다
|
||||
|
||||
`measure.mjs` 는 **boolean 을 합성하지 않는다.** 커터는 관통을 확실히 하려고
|
||||
대상 밖으로 `OVER` 만큼 튀어나와 있고(교훈 #13), 샤프트 보어는 본체 공동과
|
||||
겹친다. 그래서 `Σ멤버` 도 `base − Σ커터` 도 틀린 값이 된다. **틀린 기대값은
|
||||
기대값이 없는 것보다 나쁘다.**
|
||||
|
||||
새 형상의 기대값은 `--primitives` 표를 재료로 사람이 한 번 조립하고, 맞으면
|
||||
`--save` 로 얼린다. 두 단면 사이 면적은 t 의 2차식이라 심프슨
|
||||
`L·(A0 + 4·A(½) + A1)/6` 이 **근사가 아니라 정확**하다.
|
||||
|
||||
```
|
||||
duct.solid 5.1975 + 1.6540 + 0.9760 + 269.1920 = 277.0195
|
||||
샤프트 1 원시합 5.3299 − 보어(솔리드 범위로 클립) 2.0084 = 3.3215 실측 3.3217
|
||||
└ 원기둥이 다면체로 나와 미세하게 크다
|
||||
```
|
||||
|
||||
결과의 **정점 X 값에 중간 행이 없는지**도 같이 본다. 없으면 직선 룰드다.
|
||||
|
||||
### `src/gaps.mjs` 읽는 법
|
||||
|
||||
```
|
||||
뷰 채택선 경계 레이어 누락 고치면 되는 레이어
|
||||
단 면 J-J 22 0 0 0 —
|
||||
단 면 E-E 69 1 3 0 잡석, 선형
|
||||
```
|
||||
|
||||
| 열 | 뜻 | 대응 |
|
||||
|---|---|---|
|
||||
| 경계 | 뷰 밖으로 이어져 잘린 것 | 결함 아님. 무시 |
|
||||
| 레이어 | 선은 있는데 다른 레이어에 있음 | `layers.body` 에 추가 (설정 한 줄) |
|
||||
| 누락 | 도면에 선이 없음 | 도면 수정 또는 스냅 오차 확인 |
|
||||
|
||||
이 도면은 끊김 50곳 중 29곳이 뷰 경계, 20곳이 레이어 오분류, **선이 실제로
|
||||
없는 곳은 1곳**(그것도 1mm 스냅 오차)이었다.
|
||||
|
||||
---
|
||||
|
||||
## 6. 도구 목록
|
||||
|
||||
| 파일 | 역할 |
|
||||
|---|---|
|
||||
| `src/run.mjs` | 파싱 · 기준점 검출 · 뷰 분리 · 검증 |
|
||||
| `src/build.mjs` | 프로파일 추출 · 조립 스펙(IR) 생성 |
|
||||
| `src/emit/egm.mjs` | IR → egm 명령 목록 |
|
||||
| `src/run_egm.py` | 명령 실행 (`--dry`, `--export=<obj>` 지원) |
|
||||
| `src/measure.mjs` | OBJ 부피 실측 · 기준선 대조 · 재질별 물량 |
|
||||
| `src/report.mjs` | 추출 결과 뷰어 (한 장짜리 HTML). 링 그림 · 자기교차 · 원 · IR |
|
||||
| `src/capture.mjs` | 뷰별 **도면** 캡처 + 좌표 사이드카 (전 레이어, `--crop`·`--png`) |
|
||||
| `src/render.mjs` | 만든 **3D** 를 정투영 렌더 (`--axis`·`--part`·`--clip`·`--png`) |
|
||||
| `src/volume.mjs` | IR 을 격자로 평가 — 모델러 없이 "의도" 부피 |
|
||||
| `src/fit.mjs` | 도면 → `params/<이름>.json` |
|
||||
| `src/params.mjs` | 파라미터 스키마·식·검증 |
|
||||
| `src/rules.mjs` | 설계 규칙 (위상은 막고, 설계는 경고) |
|
||||
| `src/ui.mjs` | 파라미터 편집 + 갱신 UI (로컬 서버) |
|
||||
| `src/core/views.mjs` | 뷰 → 프로젝트 좌표. `build.mjs` 와 `report.mjs` 가 **같이 쓴다** |
|
||||
| `src/probe.mjs` | 뷰 하나의 폐곡선을 표로 (`--ring` 으로 좌표까지) |
|
||||
| `src/gaps.mjs` | 프로파일 끊김 진단 + 원인 분류 |
|
||||
| `src/inspect.mjs` | 뷰 영역의 모든 엔티티를 레이어 무관하게 |
|
||||
| `src/materials.mjs` | 뷰별 재질 주기 수집 · 레이어 ↔ 재질 대응 확인 |
|
||||
| `src/core/parse.mjs` | DWG → 엔티티, 선분 펴기, 표제 수집 |
|
||||
| `src/core/datum.mjs` | 표고 기준 검출 · 좌표 변환 |
|
||||
| `src/core/segment.mjs` | 뷰 분리 (교대 간격분할 + 제목 귀속) |
|
||||
| `src/core/loops.mjs` | 선분 → 닫힌 프로파일 (평면 분할) |
|
||||
| `src/ir.mjs` | 조립 스펙 스키마 · 빌더 · 검증 |
|
||||
| `src/drawings/*.mjs` | **도면별 설정.** 새 도면은 여기에 파일 하나 |
|
||||
| `src/drawings/manhole1-trans.mjs` | 전이부만 세우는 최소 모델. `manhole1` 설정을 상속하고 `assemble()` 만 교체 — 한 부분을 떼어 검증할 때의 본보기 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 모델러 조작 시 주의
|
||||
|
||||
`Modeler_AI/docs/egm-usage.md` 중 이 작업에서 특히 물리기 쉬운 것.
|
||||
|
||||
- **`Extrude C=True` 단독은 항상 +Z 로 민다.** 커브 평면의 법선을 따르지 않는다.
|
||||
`src/emit/egm.mjs` 는 항상 `D F {기준점} {방향점}` 으로 방향을 명시한다.
|
||||
- **`C=True` 는 `D F` 앞에** 와야 한다. 뒤에 오면 무시되고 서피스가 나온다.
|
||||
- **닫힌 `Polyline` 에 `Enter` 를 붙이지 말 것.** 자동 종료되므로 남은 신호가
|
||||
다음 명령으로 새어나간다.
|
||||
- **`SelByUids` 는 `Esc` 로 닫는다.** 안 닫으면 이후 명령이 전부 무시된다.
|
||||
- 명령은 비동기다. `egm status` 의 `command` 가 `null` 이 될 때까지 기다린다.
|
||||
`src/run_egm.py` 의 `wait()` 가 그 일을 한다.
|
||||
- **`BooleanDifference`/`BooleanUnion` 은 두 개만 먹는다.** 플러그인이
|
||||
`TargetModels[0]`, `[1]` 만 쓰므로 셋 이상 선택하면 나머지는 조용히 무시된다.
|
||||
`src/emit/egm.mjs` 의 `fold()` 가 둘씩 접는다.
|
||||
- **뷰어 모드면 모델링 명령이 등록조차 안 된다.** 0절의 `egm guide` 확인을
|
||||
건너뛰지 말 것.
|
||||
- **`ExportByPath` 의 경로는 반드시 큰따옴표로 감싼다.** `_` 가 egm 스크립트
|
||||
특수문자라, 경로에 밑줄이 있으면 오류도 경고도 없이 **아무 파일도 안 생긴다**.
|
||||
`result` 는 정상으로 보이고 `created:[]` 도 원래 그런 명령이라 신호가 없다.
|
||||
내보내기 전에 `SelAll` 이 필요하고, `.obj` 만 나온다(`.stl` 은 파일이 안 생긴다).
|
||||
`src/run_egm.py` 의 `export_obj()` 가 이걸 다 하고 파일 생성까지 확인한다.
|
||||
|
||||
### 씬 초기화가 실패할 때
|
||||
|
||||
`SelAll` → `Delete` 직후 상태가 남아 다음 명령이 씹히는 경우가 있다.
|
||||
|
||||
```sh
|
||||
egm "Esc"; egm "!Cancel"; egm "SelAll"; egm "Delete"; egm "Esc"; egm "!Cancel"
|
||||
egm status # command 가 null 인지 확인
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 현재 미완
|
||||
|
||||
| 항목 | 상태 | 필요한 것 |
|
||||
|---|---|---|
|
||||
| 전이부 챔퍼 | `manhole1-trans` 에서 완성 (챔퍼·단차·종방향 헌치) | `manhole1` 본편에 이관 |
|
||||
| 이음매 T 정점 | 열린 변 21개 (기하는 닫힘) | IFC 내보낼 때 재검토 |
|
||||
| Φ100 관통 ×5 | 미구현 | 평면도에서 전선인입 2 · 우수관연결 2 · 유도배수관 1 위치 특정 |
|
||||
| 나선계단 | 미구현 | 현 IR 연산으로 표현 불가. `Sweep1` 또는 전용 연산 추가 |
|
||||
| 방호난간 L=7.2m | 미구현 | H-H 에 표기 |
|
||||
| IFC 출력 | 미구현 | `emit/ifc.mjs`. 레이어 ↔ 재질 매핑은 이미 확보 |
|
||||
| 브라우저 연동 | 미구현 | `src/core/*` 순수화 + localhost 브리지 |
|
||||
@@ -0,0 +1,217 @@
|
||||
# CLAUDE.md — dwg2model 작업 가이드
|
||||
|
||||
이 저장소에서 작업할 때 지켜야 할 것. 사람이 읽어도 된다.
|
||||
|
||||
---
|
||||
|
||||
## 이 프로젝트가 하는 일
|
||||
|
||||
2D 도면(평면 · 입면 · 단면 · 좌/우측면)을 읽어 3D 솔리드와 IFC 로 옮긴다.
|
||||
**도면마다 설정 파일 하나만 바꾸면 도는 구조**가 목표다.
|
||||
|
||||
문서 셋을 먼저 읽어라.
|
||||
|
||||
| 문서 | 읽어야 할 때 |
|
||||
|---|---|
|
||||
| [`README.md`](README.md) | 구조 · 실행 방법 |
|
||||
| [`docs/2d-3d-process.md`](docs/2d-3d-process.md) | **절차** — 새 도면 추가, 검증 순서 |
|
||||
| [`docs/2d-3d-conversion.md`](docs/2d-3d-conversion.md) | **노하우** — 함정, 실패 사례, 왜 그렇게 하는지 |
|
||||
| [`docs/roadmap.md`](docs/roadmap.md) | 남은 일 · 우선순위 |
|
||||
| [`docs/parametric.md`](docs/parametric.md) | **파라메트릭 설계 층** — 설계 노트, 미구현 |
|
||||
|
||||
`2d-3d-conversion.md` 의 함정 목록은 실제로 다 밟아본 것이다. 새로 시작하기 전에
|
||||
훑어보면 같은 곳에서 두 번 넘어지지 않는다.
|
||||
|
||||
---
|
||||
|
||||
## 절대 어기면 안 되는 경계
|
||||
|
||||
```
|
||||
src/core/* · src/ir.mjs → 도면 고유값이 들어가면 안 된다
|
||||
src/drawings/*.mjs → 레이어명 · 제목 · 임계값 · 좌표 · 단위 · 축척은 전부 여기
|
||||
src/emit/* → 여기서만 3D 툴의 사정을 안다
|
||||
```
|
||||
|
||||
이 경계가 무너지면 두 번째 도면에서 **파이프라인이 아니라 복사본**이 생긴다.
|
||||
`core/` 에 `'-전력구'` 같은 문자열을 넣고 싶어지면 설계가 잘못된 것이다.
|
||||
|
||||
**이 경계는 이미 두 번 새 있었다.** 교량 도면을 넣어보고서야 드러났다.
|
||||
|
||||
- `core/datum.mjs` 의 `UNIT_MM = 1000` — 숫자라서 눈에 안 띄었을 뿐 도면 고유값이다.
|
||||
같은 파일의 라벨 대역(`±3`)·뷰 구분 문턱(`2`)도 「1단위=1m」를 전제한 길이였다.
|
||||
- `rules.mjs` 는 주석에 "도면도 3D도 모른다"고 적혀 있었지만 `챔퍼_시작X`·`샤프트`
|
||||
같은 **첫 도면의 파라미터 이름**에 묶여 있었다. 두 번째 도면에서 `undefined` 비교가
|
||||
전부 위상 위반으로 떨어져 `build` 가 죽었다. 지금은 `needs` 로 적용 범위를 명시한다.
|
||||
|
||||
교훈: **문서에 "안 들어간다"고 쓰는 것으로는 안 지켜진다.** 두 번째 도면을 넣기 전에는 안 보인다.
|
||||
|
||||
경로는 `src/paths.mjs` 한 곳에서만 정한다. 스크립트에서 `../..` 을 세지 말 것.
|
||||
|
||||
---
|
||||
|
||||
## 작업 순서 — 이 순서를 건너뛰지 마라
|
||||
|
||||
3D 부터 세우면 **어디가 틀렸는지 알 수 없다.** 반드시 아래 순서로 통과시킨다.
|
||||
|
||||
```
|
||||
0. egm guide | wc -l 뷰어 모드가 아닌가 (39 면 뷰어 — 모델링 불가)
|
||||
1. node src/run.mjs <도면> 기준점이 도면 치수 2개 이상과 맞는가
|
||||
뷰 폭·높이가 도면 치수와 맞는가
|
||||
2. node src/gaps.mjs <도면> 프로파일이 안 닫히는 곳 · 그 원인
|
||||
3. node src/build.mjs <도면> --loops 폐곡선 치수가 도면 표기와 맞는가
|
||||
꼭짓점 수가 예상과 맞는가
|
||||
4. node src/build.mjs <도면> IR 검증
|
||||
5. python src/run_egm.py … --dry 좌표 검산
|
||||
6. python src/run_egm.py … --export=out/<도면>.obj 실행 + OBJ
|
||||
7. egm status modelCount 가 최종 파트 수와 같은가
|
||||
8. node src/measure.mjs <도면> --ir 의도(IR) vs 결과(모델러) 대조 + 기준선
|
||||
```
|
||||
|
||||
`--ir` 이 핵심이다. 부피가 이상할 때 **우리 조립이 틀렸는지 모델러가 흘렸는지**를
|
||||
한 줄로 가른다. 손으로 기대값을 조립하면 커터 범위를 놓쳐 세 번 다 틀렸다.
|
||||
|
||||
`run.mjs` 는 검증 실패 시 **exit 1** 을 낸다. 그 상태로 다음 단계에 가지 말 것.
|
||||
|
||||
7 이 어긋나면 boolean 이 인자를 흘린 것이다. 「모델러 조작」 절을 볼 것.
|
||||
|
||||
---
|
||||
|
||||
## 자주 틀리는 것 (전부 실제로 겪었다)
|
||||
|
||||
| 함정 | 올바른 방법 |
|
||||
|---|---|
|
||||
| 표고 기준을 **텍스트 위치**로 잡음 | **선**에서 잡는다. 713mm 틀렸다 |
|
||||
| 계획고 선 후보가 둘 (도로/토공) | 라벨 **바로 아래** 선을 고른다. 420mm 틀렸다 |
|
||||
| 횡단면 하나를 전 구간에 압출 | 종단면이 **구간 배정표**다. 구간마다 단면이 다르다 |
|
||||
| 폐곡선을 `loops[0]` 로 집음 | **치수**로 집는다. `loop(뷰, 2700, 2750)` |
|
||||
| 자기교차 링을 그냥 압출 | 솔리드가 쓰레기가 되고 이후 boolean 이 **조용히** 무력화된다. `--loops` 의 `✗ 자기교차` 를 먼저 볼 것 |
|
||||
| 원 좌표·반지름을 손으로 적음 | `circles(뷰, 900, /^-전력구$/)`. 손으로 적은 수는 도면이 바뀌어도 안 바뀐다 |
|
||||
| 원을 선분에 섞어 넣음 | 따로 모은다. 폐곡선이 원 윤곽을 따라 돌아 오염된다 |
|
||||
| 평면도 세로축을 표고로 봄 | 세로=Y. `v0` 앵커 필요. 치수만 보는 동안은 안 걸린다 |
|
||||
| 개구부 폐곡선을 그대로 씀 | X 기호 때문에 링이 자기교차. **bbox → `rect()`** 로 재구성 |
|
||||
| 오목한 외곽을 그대로 뚫음 | 노치를 합쳐 **봉투부터** 만들고 그 다음에 뚫는다 |
|
||||
| 구간별로 따로 difference | 구간 **몸통**을 union 한 뒤에 뚫는다. 경계에 구멍 난다 |
|
||||
| 커터를 union 해서 한 번에 | 떨어진 커터끼리는 교차하지 않아 union 이 죽는다. 커터는 **하나씩** |
|
||||
| 커터가 자기 부피보다 많이 뺌 | boolean 이 죽은 것이다. `--primitives` 로 커터 부피를 보면 즉시 확정 |
|
||||
| 면으로만 맞닿은 솔리드를 union | 조각으로 붙어 있다가 다음 difference 가 통째로 흘린다. **부피로 겹치게** |
|
||||
| union 결과를 뚫음 | 조각마다 제 몫을 먼저 뚫고 합친다. 커터는 조각 수만큼 따로 만든다 |
|
||||
| 커터를 대상 바깥면에서 시작 | `OVER` 만큼 밖으로 뺀다. 압출축뿐 아니라 **모든 방향** |
|
||||
| 수평 단면의 세로축을 Z 로 봄 | 가로=Y, 세로=X. `swapUV` |
|
||||
| 압출축을 의식 안 함 | YZ→X 압출은 **Y 방향 벽만** 만든다 |
|
||||
| 전이부를 loft 하나로 이음 | loft 는 **꺾인 자리를 못 만든다**. 꺾이는 X 마다 단면을 놓고 끊는다 |
|
||||
| loft 단면을 그냥 넣음 | 시작 꼭짓점이 어긋나면 면이 비틀린다. 링 정규화 + 꼭짓점 수 일치 |
|
||||
| DWG 1단위 = 1m 로 가정 | **도면군마다 다르다**. 맨홀군 1m, 교량 삽도군 1mm. `cfg.unitMm` 로 준다. 안 맞추면 전 치수가 1000× 로 **조용히** 틀린다 |
|
||||
| 모델스페이스가 1:1 이라고 가정 | 삽도는 **도형마다 배율이 다르다** (5.805배 사례). 표기 치수 2개로 역산해 교차검증 |
|
||||
| 표고 기준선이 있다고 가정 | 없는 도면이 있다. `datum.mode:'none'` + 뷰별 `anchors.v0`. 아무 수평선이나 자동 선택하면 안 된다 |
|
||||
| 뷰 제목으로 뷰를 가름 | 제목이 없거나 **N벌 중복**인 도면이 있다. `cfg.viewBoxes` 로 좌표를 짚는다 |
|
||||
| 레이어로 치수선을 거름 | 구조선과 같은 레이어인 도면이 있다. `colorIndex`(0=ByBlock=치수블록)가 가른다 → `cfg.entityFilter` |
|
||||
| 끊김 0인데 폐곡선 0 | 겹치는 **동일선상 선분**. T자 분할 뒤 중복 변이 남는다. `loops.mjs` 가 분할 뒤 한 번 더 지운다 |
|
||||
| 파싱 캐시 파일명에 `[^\w.-]→_` | `\w` 가 한글을 안 먹어 다른 도면이 **같은 캐시**를 쓴다. 인덱스·해시로 |
|
||||
| 도면을 바로 게이트에 넣음 | 먼저 **숫자 치수 vs 기호 치수**를 센다. 다만 「그 도면 안에 대조 상대가 없다」일 뿐 — 다른 도면·표준 부재 치수로 축척을 되찾으면 쓸 수 있다 |
|
||||
| 그림 안 보고 뷰 상자를 잡음 | **한 시트에 날짜 다른 작업본이 겹쳐** 있을 수 있다. 두 벌이 섞여도 폐곡선·치수가 그럴듯해 **숫자로는 안 걸린다.** 시트 전체 → 도형 하나 → 확인 → 상자 |
|
||||
| 같은 뷰에 확대 상세가 섞임 | 축척이 다르다(받침 153×182 ↔ 상세 461×196). 치수로 집으면 갈리지만 **갈렸는지 검사**를 넣는다 |
|
||||
| 같은 부재가 1mm 다르게 나옴 | 꼭짓점마다 따로 반올림한다. `loops(…, tol)` 로 열되 기본값 0 |
|
||||
| 면적은 맞는데 폭·높이가 틀림 | **매달린 변**(끝이 안 닿는 선) 왕복이 bbox 를 부풀린다. 면적은 0 이라 안 걸린다 |
|
||||
| 진단 도구가 본편과 다른 값 | 도구가 `projectViews` 를 안 거쳤다. 본편과 **같은 함수**를 써야 한다 |
|
||||
| 형상이 없으면 정보도 없다고 봄 | 말뚝은 **해치 + 중심선**이다. 중심선 x = 위치, 윤곽 두 줄 간격 = 지름 |
|
||||
|
||||
`--loops` 의 **꼭짓점 수**가 가장 빠른 이상 신호다.
|
||||
|
||||
```
|
||||
4 정상 직사각형
|
||||
10 헌치가 있는 정상 형상
|
||||
8 개구 기호(X)가 링을 오염시킴
|
||||
114 케이블랙 같은 가구가 프로파일 레이어에 섞임
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 모델러(EGModeler) 조작
|
||||
|
||||
```
|
||||
Extrude C=True 단독은 항상 +Z 로 민다. → 항상 D F {기준점} {방향점} 로 방향 명시
|
||||
C=True 는 D F 앞에. → 뒤에 오면 무시되고 서피스가 나온다
|
||||
닫힌 Polyline 에 Enter 금지 → 남은 신호가 다음 명령으로 샌다
|
||||
SelByUids 는 Esc 로 닫는다 → 안 닫으면 이후 명령이 전부 무시된다
|
||||
명령은 비동기 → command 가 null 될 때까지 대기
|
||||
보이드 객체 없음 → 커터 솔리드 + BooleanDifference 뿐
|
||||
Boolean 은 두 개만 먹는다 → 셋 이상 선택하면 나머지는 조용히 무시된다
|
||||
Loft 는 기본이 서피스 → C=True 로 막아야 솔리드. Enter 는 한 번
|
||||
Loft 의 L(원본삭제)은 기본 true → 끄면 커브가 남아 modelCount 가 어긋난다
|
||||
Cap 은 제자리 수정 → 새 uid 가 안 나와 파이프라인이 못 잡는다
|
||||
ExportByPath 경로에 _ 가 있으면 → 큰따옴표 필수. 없으면 조용히 파일이 안 생긴다
|
||||
SelAll 먼저. .obj 만 나온다 (.stl 은 안 됨)
|
||||
```
|
||||
|
||||
`SelAll`→`Delete` 가 파이프를 죽인 적이 있다. 프로세스도 창도 멀쩡한데
|
||||
(`Responding=True`, CPU 유휴) 명령만 전부 "응답하지 않습니다"가 된다.
|
||||
CLI 로는 못 살린다 — 모델러를 재시작한다.
|
||||
|
||||
### 시작 전에 뷰어 모드부터 확인한다
|
||||
|
||||
뷰어 모드면 **모델링 명령이 등록조차 안 된다.** 파이프는 살아 있어서 `egm status` 는
|
||||
정상 응답하고, `~Polyline` 은 아무 말 없이 `created:[]` 를 낸다. 원인을 찾는 데
|
||||
제일 오래 걸린 함정이다.
|
||||
|
||||
```sh
|
||||
egm guide | python -c "import sys,json;print(len(json.load(sys.stdin)))"
|
||||
# 39 → 뷰어 모드. 보기·선택·계측만 있다. 모델링 불가
|
||||
# 207 → 정상
|
||||
egm guide Polyline # "not found" 면 뷰어 모드
|
||||
```
|
||||
|
||||
CLI 로는 못 바꾼다. 모델러 UI 에서 **Assistive Features → Working Mode Setting** 을
|
||||
`Viewer & Modeler Use` 로 놓는다. 모델링 플러그인은 뷰포트가 한 번 렌더된 뒤
|
||||
`LoadProjectPluginsAsync()` 로 올라오므로, 창이 화면 밖에 있으면 같은 증상이 난다.
|
||||
|
||||
### Boolean 은 이항이다
|
||||
|
||||
`BooleanDifference` · `BooleanUnion` 플러그인은 선택 개수와 무관하게
|
||||
`TargetModels[0]`, `[1]` **두 개만** 쓴다. 커터 9개를 한 번에 넘겼더니 컷 1개만
|
||||
적용되고 커터 8개가 씬에 그대로 남았다 (`modelCount` 11 이어야 할 게 19).
|
||||
|
||||
`emit/egm.mjs` 의 `fold()` 가 둘씩 접는다. 중간 결과는 `id~1`, `id~2` … 로 잡고
|
||||
마지막만 `id` 가 된다.
|
||||
|
||||
**`modelCount` 가 최종 파트 수와 같은지 매번 확인한다.** 가장 빠른 이상 신호다.
|
||||
|
||||
### 씬 초기화
|
||||
|
||||
`!Cancel` 을 쓰면 모델러가 명령을 안 받는 상태에 빠진 적이 있다.
|
||||
초기화는 `Esc` → `SelAll` → `Delete` → `Esc` 로 하고 `egm status` 로 확인한다.
|
||||
|
||||
---
|
||||
|
||||
## 파라메트릭 층
|
||||
|
||||
```
|
||||
DWG ──fit──→ params/<이름>.json ──build --params──→ IR ──→ 3D
|
||||
↑ 사람은 여기만 만진다. build 는 도면을 안 본다
|
||||
```
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `src/fit.mjs` | 도면 → 파라미터. 재현 안 되는 링은 `grade: opaque` 로 좌표째 얼린다 |
|
||||
| `src/params.mjs` | 스키마·식(위상정렬)·검증·도면 이탈 감지 |
|
||||
| `src/rules.mjs` | 위상 규칙(**막는다**) · 설계 규칙(경고) |
|
||||
| `src/volume.mjs` | IR 을 격자로 평가 — 모델러 없이 "의도" 부피 |
|
||||
| `src/ui.mjs` | 편집 + 갱신 버튼. `node src/ui.mjs manhole1` |
|
||||
|
||||
- `drawings/*.mjs` 는 `fit()` 과 `assemble()` 둘로 나뉜다. **`assemble()` 에는
|
||||
도면 조회 도우미를 주지 않는다** — 주면 다시 도면에 묶인다.
|
||||
- **모델러에서 직접 편집하지 않는다.** 갱신하면 UID 가 전부 바뀌어 날아간다.
|
||||
|
||||
## 코드 스타일
|
||||
|
||||
- 주석은 **왜** 를 적는다. 무엇을 하는지는 코드가 말한다.
|
||||
- 실패했던 방법과 그 이유를 주석에 남긴다. 다음 사람이 같은 걸 시도한다.
|
||||
- 좌표·치수는 mm 정수. `egm` 에 넘기기 직전에만 m 로 나눈다.
|
||||
- 조용히 틀리느니 예외를 던진다 (`loop()` 가 0개나 2개 이상이면 throw).
|
||||
|
||||
---
|
||||
|
||||
## 라이선스
|
||||
|
||||
`vendor/acadrust-dwg/` 는 **MPL-2.0 수정본**이다.
|
||||
이 wasm 을 다른 저장소로 옮길 때 `THIRD-PARTY-NOTICES.md` 와 `licenses/` 두 파일을
|
||||
반드시 함께 옮겨야 한다. 패치 파일이 MPL-2.0 §3.2 의무의 근거다.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,194 @@
|
||||
# 다음 세션 프롬프트 — 교각 P11 (꺾임)
|
||||
|
||||
> 그대로 복사해 붙이면 된다. 아래 `---` 부터가 프롬프트다.
|
||||
|
||||
---
|
||||
|
||||
# 교각 P11 — 꺾인 코핑
|
||||
|
||||
## 지난 세션에 P9 를 끝냈다
|
||||
|
||||
`산외교_파이형_교각일반도(울산P9).dwg` 로 **교각 한 기를 끝까지** 세웠다.
|
||||
코핑 · 원형기둥 2 · 확대기초 2 · 버림 2 · 강관말뚝 44 · 받침 6기(교좌대·모르타르·
|
||||
받침·솔플레이트) · 미관문양 2 = **77 파트 · 660.4154 m³**.
|
||||
모델러 실측 대비 **불일치 0건**, 열린 변 0, IFC 내보내기까지 왕복 검증됐다.
|
||||
|
||||
이번엔 **P11** 이다. `산외교_파이형_교각일반도(울산P11-꺾임).dwg`.
|
||||
P9 와 뷰 구성이 같지만 **코핑 축선이 꺾여 있다.** 그게 이번 세션의 전부다.
|
||||
|
||||
## 먼저 읽어라 (순서대로)
|
||||
|
||||
1. `CLAUDE.md` — 경계 · 작업 순서 · 함정표
|
||||
2. `docs/methodology.html` **11.4 절** — P9 실증 결과. 판정표 · 코어 변경 · 새 함정
|
||||
3. `src/drawings/pier-p9.mjs` — **이번 작업의 원본이다.** 통째로 읽어라
|
||||
4. `docs/2d-3d-conversion.md` 교훈 #29~#33 (지난 교량 세션)
|
||||
|
||||
## 대상
|
||||
|
||||
```
|
||||
drawings-src/산외교_파이형_교각일반도(울산P11-꺾임).dwg
|
||||
도곽 CXBLKA1 INSERT (1,406,622, 390,000) × scale 100 × A1(841×594)
|
||||
→ sheet x[1,406,622 … 1,490,722] y[390,000 … 449,400]
|
||||
```
|
||||
|
||||
**도곽 밖은 전부 다른 벌이다.** 이 파일도 도면집 스택이라 17벌이 y 방향 65,000
|
||||
간격으로 쌓여 있고, 그중 P9 자리는 치수선만 남아 있다. 상자를 눈으로 잡지 마라 —
|
||||
도곽 블록에서 계산한다.
|
||||
|
||||
## 이미 확인한 것 (DWG 데이터에서 직접 잰 값)
|
||||
|
||||
```
|
||||
측점 STA.0+594.570
|
||||
표고 EL. 82.799 · 82.306 · 81.713 (코핑 상면 3단으로 추정)
|
||||
EL. 44.413 (기초 저면)
|
||||
기둥 Ø2,200 원형 3본 · CS-CONC-MINR CIRCLE
|
||||
평면도 (1,416,488, 437,383) (1,425,088, 437,383) (1,433,616, 436,442)
|
||||
기초평면 (1,416,488, 403,537) (1,425,088, 403,537) (1,433,616, 402,596)
|
||||
받침 블록 500x500 ×3 · 530x530 ×2 · 470x470 ×1
|
||||
연단거리 L=170.600 · H=36.203 · Theta=0
|
||||
```
|
||||
|
||||
### 꺾임각 = **6.30°**
|
||||
|
||||
```
|
||||
기둥 1→2 Δx 8,600 Δy 0 → 0.00° 간격 8,600
|
||||
기둥 2→3 Δx 8,528 Δy −941 → −6.30° 간격 8,580
|
||||
```
|
||||
|
||||
**두 뷰(평면도·기초평면도)에서 같은 941 이 나온다.**
|
||||
|
||||
> ⚠ 지난 세션에 이걸 한 번 「8.7°」로 잘못 말했다. 전 색 각도 분포에 있던
|
||||
> `81.3°/171.3°` 를 꺾임각으로 읽은 것인데, 구조 외곽선만(`ci=256`) 세면 그
|
||||
> 대역이 없다 — **보조선 각도였다.** 기둥 축선에서 직접 잰 6.30° 가 맞다.
|
||||
> **각도를 선 분포에서 읽지 말고 부재 좌표에서 재라.**
|
||||
|
||||
`(1,453,587, 436,249)` 의 Ø2,200 은 `CS-CONC-MAJR` 이고 x 가 19,971 떨어져 있다 —
|
||||
**단면 A-A** 의 기둥 단면이지 평면도 기둥이 아니다.
|
||||
|
||||
## 1단계 — 꺾임의 정체 (여기서 멈추고 보고)
|
||||
|
||||
**캡처를 먼저 봐라.** 좌표만으로는 못 가른다.
|
||||
|
||||
1. **평면도** — 꺾이는 자리가 **기둥 3번 위**인가 그 **사이**인가.
|
||||
코핑이 «각진 두 토막»인가 «한 곡선»인가. 꺾임부 폭·필렛
|
||||
2. **정면도** — 파단선 위치 · 코핑 상면 단수 · EL 지시 위치
|
||||
3. **단면도** — 코핑 교축폭 · 헌치
|
||||
4. **기초 평면도** — 기초 3기인가 · 말뚝 배치(P9 는 22본×2)
|
||||
|
||||
## 2단계 — 형상 전략 (보고 후 진행)
|
||||
|
||||
P9 코핑은 「정면 윤곽(YZ) × 교축 압출」 ∩ 「평면 윤곽 빗각기둥 2장」으로 섰다.
|
||||
**꺾이면 그 전제가 깨진다** — 정면도가 투영이라 실제 길이를 안 준다.
|
||||
|
||||
후보 셋. 캡처 보고 고른다.
|
||||
|
||||
| 방법 | 되는 조건 | 걸림돌 |
|
||||
|---|---|---|
|
||||
| 꺾임점에서 **끊어** 두 토막을 각자 압출 | 두 토막이 각각 직선 | 이음매 union — 면으로만 맞닿으면 다음 boolean 이 흘린다 |
|
||||
| 토막마다 **로컬 좌표계** | 가장 정직 | IR 에 배치 개념이 없다. 코어 변경 |
|
||||
| 평면 압출 ∩ 정면 압출 | 꺾임이 평면에만 있고 정면이 실제 길이를 줄 때 | 대개 안 준다 |
|
||||
|
||||
**끊는 쪽이 유력하다.** loft 는 쓰지 마라 — 결과가 안 닫혀 boolean 에서 샌다(아래).
|
||||
|
||||
## 절대 규칙
|
||||
|
||||
- `src/core/*` · `src/ir.mjs` 에 도면 고유값 금지. 레이어명 · 제목 · 좌표 · 단위 ·
|
||||
축척은 전부 `src/drawings/pier-p11.mjs`
|
||||
- **코어 수정이 필요해 보이면 먼저 보고해라.** 그게 방법론의 구멍이다
|
||||
- 못 찾거나 여러 개면 예외를 던져라. 자동 선택 금지
|
||||
- **손으로 읽은 수를 코드에 적지 마라.** 도면에서 집고 다른 값과 대조해라
|
||||
- **그림을 먼저 봐라.** 뷰 상자를 잡기 전에 시트 → 도형 → 확인 → 상자
|
||||
|
||||
## 게이트 (P9 에서 전부 통과시킨 순서)
|
||||
|
||||
```
|
||||
0. egm guide | 명령 수 208 이면 편집 모드 · 39 면 뷰어 모드(모델링 불가)
|
||||
1. node src/run.mjs pier-p11 뷰 폭·높이가 도면 표기와 맞는가
|
||||
2. node src/gaps.mjs pier-p11 끊김의 원인이 형상인가 파단선인가
|
||||
3. node src/build.mjs pier-p11 --loops 꼭짓점 수·자기교차
|
||||
node src/build.mjs pier-p11 --circles / --blocks
|
||||
node src/table.mjs pier-p11 --title "교량받침 ELEVATION TABLE"
|
||||
4. node src/build.mjs pier-p11 IR 검증
|
||||
5. node src/volume.mjs pier-p11 해석 부피 (모델러 없이)
|
||||
6. node src/emit/egm.mjs out/pier-p11.ir.json
|
||||
python src/run_egm.py out/pier-p11.egm.json --export=out/pier-p11.obj
|
||||
7. egm status modelCount == 최종 파트 수
|
||||
8. node src/measure.mjs pier-p11 --ir 의도 vs 결과 (합격선 절대 0.05 m³)
|
||||
9. node src/emit/ifc.mjs out/pier-p11.ir.json
|
||||
```
|
||||
|
||||
## 지난 세션에 코어를 이만큼 고쳤다 (되돌리지 마라)
|
||||
|
||||
```
|
||||
C12 core/loops.mjs dropCollinear 중복점 제거
|
||||
매달린 변 왕복이 길이 0 인 변을 남긴다. 압출하면 퇴화 면이 나온다
|
||||
C13 ir.mjs · emit/egm.mjs · volume.mjs intersect 연산
|
||||
BooleanIntersection 은 이항. 「두 방향이 동시에 맞아야 하는 형상」용
|
||||
C14 ir.mjs · emit/egm.mjs · volume.mjs extrude.drift (빗각 기둥)
|
||||
Extrude C=True D F 가 자유방향을 받고 결과가 닫힌다
|
||||
C15 core/parse.mjs collectBlocks · run.mjs · core/views.mjs · core/pick.mjs blocks()
|
||||
말뚝이 INSERT 블록. 삽입점=위치, 배율=치수
|
||||
C16 core/table.mjs (신규) · src/table.mjs (CLI) · run.mjs 색인 · pick.tables
|
||||
표를 (이름표, CSV) 쌍으로 색인. 이름표 아래 글자높이 ×2 로 표를 찾는다
|
||||
C17 run.mjs 뷰별 entityFilter
|
||||
뷰마다 무엇이 구조선인지 다르다 (문양은 ci=2, 본체는 ci=256)
|
||||
C18 volume.mjs 교집합 해석 부피
|
||||
① 압출∩압출 닫힌 식 ② 종단∩평면(높이 가변) Z 슬라이스 가우스
|
||||
C19 emit/ifc.mjs (신규) IFC4 출력. 해석 솔리드 우선 + IfcMapConversion
|
||||
C20 emit/egm.mjs loft → `~Loft Enter` + `~Cap` (그래도 boolean 엔 못 쓴다)
|
||||
```
|
||||
|
||||
## 새로 밟은 함정 (또 밟지 마라)
|
||||
|
||||
| 증상 | 원인 | 대응 |
|
||||
|---|---|---|
|
||||
| **부피는 맞는데 boolean 이 샌다** | **`Loft` 결과가 안 닫힌다.** 4각형 단면도 열린 변 12개. 발산 정리 부피는 정확해 **부피 검사로 절대 안 걸린다** | loft 를 boolean 인자로 쓰지 마라. 평행이동뿐이면 `drift` 압출 |
|
||||
| 그려진 길이가 실제가 아니다 | **파단선.** 기둥이 6,100 인데 실제 33,800 | `CS-CUTL` 을 본다. 생략량 = 실제 − 도형 (derived) |
|
||||
| 한 파일에 도형 17벌 | 도면집 스택 | **도곽 블록에서 상자를 계산** |
|
||||
| 「단면도」 안쪽 선을 부재로 읽음 | **절단면이 아니라 투영** | 치수가 `외곽 − 2×R` 이면 투영 |
|
||||
| 평면 모서리가 45° 모따기 | 파서가 `bulges` 를 버려 90° 호가 현으로 눌림 | 호 끝점은 정확 → R 은 되찾는다. 링 면적은 못 믿는다 |
|
||||
| 적분값이 0.2 m³ 샘 | 구간 끝점이 링 꼭짓점 → 스캔라인 교차 수 어긋남 | 내부 노드 구적(가우스). 심프슨 금지 |
|
||||
| 구조 형상이 **표**로 잡힘 | 평면도 격자가 73행×83열 「표」 | 표 색인에 `layerFilter` |
|
||||
| `actualMeasurement` 로 단위 판정 실패 | 주요 m 표기 · 상세 mm 표기 (**표시값**이 온다) | 도곽 배율 · 블록 scale · 격자 간격으로 교차검증 |
|
||||
|
||||
## P9 에서 통한 방식 — 그대로 가져다 써라
|
||||
|
||||
```
|
||||
단위 도곽 A1×100 · 블록 scale ↔ Φ 텍스트 · 격자 ↔ 「4@1.300」 → 넷 다 1단위=1mm
|
||||
공통중심 부재 대칭으로 자기검증 (코핑 ±7,000 · 기초 ±3,250 · 기둥 ±4,100)
|
||||
표고 공통 기준선이 없어도 **표가 준다** — EL.'X' = 코핑상면 + h1 + h2
|
||||
6기가 모두 같은 절대표고를 내면 그게 원점이다
|
||||
받침 평면도(위치·평면치수) × 표(적층고·표고·교축위치) 세 겹 검산
|
||||
파단 생략량 = 기둥_높이 − 기둥_도형길이 (derived. 손으로 적지 마라)
|
||||
```
|
||||
|
||||
## 보고 형식 (매 단계)
|
||||
|
||||
```
|
||||
쓴 도면·도형: 무엇을, 왜 그것을
|
||||
통과한 게이트:
|
||||
막힌 곳: 게이트 번호 + 증상 + 원인
|
||||
설정으로 해결: 무엇을
|
||||
코드가 필요: 무엇이 왜 (← 방법론의 구멍)
|
||||
방법론에서 틀린 것: 어느 절의 어느 주장이
|
||||
새 함정: 증상 → 원인 → 대응
|
||||
```
|
||||
|
||||
## 아직 안 한 일 (P11 과 별개, 여력 되면)
|
||||
|
||||
1. **`manhole1` 재검증** — loft 결과를 union·difference 인자로 쓴다.
|
||||
C20 의 함정 위에 서 있을 수 있다. 부피가 맞아 보여도 샜을 수 있다
|
||||
2. **P9 미관문양 형상 재검토** — 사용자가 「제대로 안 된다」고 했다.
|
||||
지금은 코핑 양 측면의 50 두께 띠 + 하단 250 구간 100 돌출로 세워져 있고,
|
||||
정면도의 매달린 대각선 6줄(문양 내부 능선)은 재현 안 한다
|
||||
3. **`docs/2d-3d-conversion.md` 에 교훈 #34~ 추가** — 위 함정표가 아직 안 옮겨졌다
|
||||
4. **텍스트 셀렉터** — 기둥 높이·말뚝 길이가 아직 `design` 이다.
|
||||
치수/표고 **텍스트**를 집는 수단이 없다. `blocks()` 를 만든 것과 같은 종류
|
||||
|
||||
## 마지막
|
||||
|
||||
1. `docs/2d-3d-conversion.md` 에 교훈 추가
|
||||
2. `docs/methodology.html` **11.5 절** 신설 — P11 이 무엇을 밝혔는지.
|
||||
판정표를 그대로 싣고, 배지를 올리되 **틀린 주장은 지우지 말고 왜 틀렸는지 적어라**
|
||||
3. `node src/ui.mjs pier-p11 --port 7333` 로 파라메트릭 UI 까지 확인
|
||||
4. `node src/emit/ifc.mjs out/pier-p11.ir.json` 로 IFC 까지
|
||||
@@ -0,0 +1,143 @@
|
||||
# 다음 세션 프롬프트 — 교각(Pier) 하나로 방법론 실증
|
||||
|
||||
> 그대로 복사해 붙이면 된다. 아래 `---` 부터가 프롬프트다.
|
||||
|
||||
---
|
||||
|
||||
# 교각(Pier) 한 부재로 방법론 실증
|
||||
|
||||
## 왜 부재를 쪼개나
|
||||
|
||||
지난 세션에 교량 도면 7장으로 한꺼번에 갔다가 **뷰 상자를 두 번 잘못 잡았다.**
|
||||
한 시트에 날짜가 다른 작업본이 겹쳐 있는 걸 못 보고 두 벌을 섞어 뽑았고,
|
||||
교대라고 부른 것이 실은 옆 도형의 날개벽이었다. **폐곡선도 치수도 그럴듯해서
|
||||
숫자로는 안 걸렸다.**
|
||||
|
||||
이번엔 **교각 하나만** 한다. 부재 하나를 끝까지 밀어 방법론의 어느 절이
|
||||
그 부재에 대해 참인지 거짓인지를 확정하는 것이 목적이다. 모델 완성이 아니다.
|
||||
|
||||
## 먼저 읽어라 (순서대로)
|
||||
|
||||
1. `CLAUDE.md` — 경계 · 작업 순서 · 함정표(마지막 7행이 지난 세션 것)
|
||||
2. `docs/2d-3d-conversion.md` — **교훈 #29~#33 을 반드시 읽어라.** 지난 세션에
|
||||
내가 밟은 것들이다
|
||||
3. `docs/methodology.html` — **11.0.4 · 11.0.5** 가 교량 실증 결과다
|
||||
4. `src/drawings/bridge-end.mjs` — 지난 세션 산출물. 교각을 이미 세워봤다
|
||||
(두부 2,244×1,334 · 기둥 1,586×3,904 · 확대기초 5,081×1,334)
|
||||
|
||||
## 대상
|
||||
|
||||
`drawings-src/` 의 **교각 도면**.
|
||||
- 새 DWG 가 들어와 있으면 그것을 쓴다
|
||||
- 없으면 기존 7장 중 교각이 그려진 것 (`교량시종점` 의 2지간 도형,
|
||||
`C-BRDG-PIER` 레이어를 가진 `교량폭원` · `횡단경사`)
|
||||
|
||||
**어느 것을 쓰는지 먼저 보고해라.**
|
||||
|
||||
## 절대 규칙 (지난 세션에 어긴 것 포함)
|
||||
|
||||
- `src/core/*` · `src/ir.mjs` 에 도면 고유값 금지. 레이어명 · 제목 · 좌표 · **단위** ·
|
||||
**축척**은 전부 `src/drawings/<이름>.mjs`
|
||||
- **코어 수정이 필요해 보이면 먼저 보고해라.** 그게 방법론의 구멍이다
|
||||
- 못 찾거나 여러 개면 예외를 던져라. 자동 선택 금지
|
||||
- 손으로 읽은 수를 코드에 적지 마라. 도면에서 집고 **다른 값과 대조**해라
|
||||
- **그림을 먼저 봐라.** 뷰 상자를 잡기 전에 반드시:
|
||||
① 시트 전체 캡처 → 도형이 몇 벌인지, 겹치는지
|
||||
② 도형 하나만 캡처 → 무엇이 들어 있는지 눈으로 확인
|
||||
③ 그 다음에 상자
|
||||
**이 순서를 건너뛰면 지난 세션과 같은 실수가 난다**
|
||||
- 캡처는 `src/capture.mjs` 를 써라 (`--crop`, `--scale`, `--png`).
|
||||
프로젝트 격자와 사이드카가 같이 나온다. 즉석 렌더를 던지지 마라
|
||||
|
||||
## 1단계 — 도면 파악 (여기서 멈추고 보고)
|
||||
|
||||
1. **시트 전수 캡처.** 도형이 몇 벌인가. 날짜 도장이 몇 개이고 **작업본이
|
||||
겹쳐 있는가** (교훈 #29)
|
||||
2. **교각이 그려진 도형을 전부 나열**하고 각각 무엇을 주는지:
|
||||
- 종단면(측면) / 횡단면 / 평면 중 무엇인가
|
||||
- 두부 · 기둥 · 확대기초 · 말뚝 중 무엇이 부재로 그려졌나
|
||||
- 확대 상세가 섞여 있나 (축척이 다르다 — 교훈 #31)
|
||||
3. **단위와 축척.** `DIMENSION.actualMeasurement` ↔ 치수 글자로 `unitMm` 확정.
|
||||
치수 글자가 없으면 **크기를 아는 표준 부재**로 축척을 되찾아라 (교훈 #30).
|
||||
두 값 이상으로 교차검증할 것
|
||||
4. **표기 치수가 숫자인가 기호인가** 세라. 기호뿐이면 그 도면 안에는 대조
|
||||
상대가 없다는 뜻일 뿐 — 다른 도면·표준 치수는 여전히 상대가 된다
|
||||
|
||||
## 2단계 — 교각 하나 세우기 (보고 후 진행)
|
||||
|
||||
**부재를 하나씩** 올려라. 한 번에 다 넣지 말 것.
|
||||
|
||||
```
|
||||
1. 기둥 가장 단순한 것부터. 폐곡선 → 압출 → 부피 대조
|
||||
2. 두부 기둥과 맞닿는 자리 확인
|
||||
3. 확대기초
|
||||
4. 말뚝 원기둥. 위치·지름을 도면에서 어떻게 얻는가 (교훈 #33)
|
||||
5. 받침 두부 위. 확대 상세와 섞이지 않는지
|
||||
```
|
||||
|
||||
각 부재마다 **게이트를 다 통과한 뒤** 다음으로 간다.
|
||||
`--loops` → `gaps` → `build` → `measure --ir` 이 0.0000 인지.
|
||||
|
||||
## 3단계 — 이 부재에서 방법론이 어디까지 참인가
|
||||
|
||||
교각에 대해 **명시적으로 판정**해라. 「해봤다」가 아니라 「참/거짓/해당없음」으로.
|
||||
|
||||
| 방법론 주장 | 교각에서 |
|
||||
|---|---|
|
||||
| 2.2 표고 기준은 전 뷰 공통 | ? |
|
||||
| 3.4 제목으로 뷰를 가른다 | ? |
|
||||
| 5.2 연산 결정 트리 | 교각에 필요한 연산이 트리에 있나 |
|
||||
| 11.1 기준 체인 (받침 → 교각 로컬) | **여기서 처음 검증 가능하다.** 하부공 도면이 받침 좌표·표고로 교각을 잡나 |
|
||||
| 11.2 revolve 필요 | 원형 교각·두부가 있나 |
|
||||
| 11.2 임의축 cylinder | 경사 말뚝이 있나 |
|
||||
|
||||
## 알려진 구멍 (지난 세션에 찾았고 아직 안 메웠다)
|
||||
|
||||
- **`pick` 이 선을 못 집는다.** 말뚝 위치는 `CS-CNTL` 중심선인데 집을 수단이
|
||||
없어 스크립트로 재서 설정에 적었다. `circles()` 처럼 `centerlines()` 가 필요하다.
|
||||
교각에서 또 필요해지면 **그때 코어에 넣자고 보고**해라
|
||||
- 말뚝 **폭방향 배치**와 길이를 주는 도면이 없었다. 교각 도면에 평면이 있으면
|
||||
거기서 나올 것이다 — **있는지 먼저 확인**해라
|
||||
- 개별 거더 치수 없음 (거더배치는 위상만 준다)
|
||||
|
||||
## 지난 세션에 코어를 이만큼 고쳤다 (되돌리지 마라)
|
||||
|
||||
```
|
||||
C1 cfg.unitMm DWG 모델단위가 도면군마다 다르다
|
||||
C2 groupByBox 제목 없는/중복인 도면의 뷰 영역
|
||||
C3 datum.mode:'none' 공통 기준선이 없는 도면
|
||||
C4 toSegments entityFilter 레이어 아닌 필터 (색·선종)
|
||||
C5 viewBoxes[뷰].unitMm 도형별 축척
|
||||
C6 buildLoops 분할 뒤 중복 제거 겹치는 동일선상 선분
|
||||
C7 rules[].needs 규칙 적용 범위
|
||||
C8 findLevelDatum 라벨 무리 검사 예외 없이 틀린 답을 막는다
|
||||
C9 pick.loops(w,h,tol) 같은 부재 여러 벌
|
||||
C10 volume.mjs 해석 부피 격자 거짓 경보 제거
|
||||
C11 buildLoops bbox collinear 제거 뒤로 (매달린 변)
|
||||
capture.mjs 단위·격자·사이드카
|
||||
probe.mjs → projectViews 경유
|
||||
render.mjs --part 정규식 · --clip 걸침 허용
|
||||
```
|
||||
|
||||
## 보고 형식 (매 단계)
|
||||
|
||||
```
|
||||
쓴 도면·도형: 무엇을, 왜 그것을
|
||||
통과한 게이트:
|
||||
막힌 곳: 게이트 번호 + 증상 + 원인
|
||||
설정으로 해결: 무엇을
|
||||
코드가 필요: 무엇이 왜 (← 방법론의 구멍)
|
||||
방법론에서 틀린 것: 어느 절의 어느 주장이
|
||||
새 함정: 증상 → 원인 → 대응
|
||||
```
|
||||
|
||||
## 마지막
|
||||
|
||||
1. `docs/2d-3d-conversion.md` 에 교훈 추가 (번호는 #34 부터)
|
||||
2. `docs/methodology.html`
|
||||
- 11장에 **교각 절** 신설 — 부재 단위 실증이 무엇을 밝혔는지
|
||||
- 3단계 판정표를 그대로 싣는다
|
||||
- 배지를 `가설` → `검증`/`부분` 으로 올리되 **틀린 주장은 지우지 말고 왜
|
||||
틀렸는지 적어라**
|
||||
3. `node src/ui.mjs <도면> --port 7333` 으로 파라메트릭 UI 까지 확인
|
||||
(`dims()` 를 만들어야 치수 상자가 나온다)
|
||||
@@ -0,0 +1,516 @@
|
||||
# 파라메트릭 설계 층 — 설계 노트
|
||||
|
||||
2026-08-06 토론 정리 → **구현 완료.** 12절에 실제로 만든 것과 확인된 것을 적었다.
|
||||
결정 근거는 11절(순서) · 8절 (b)(대조 등급) · 8.5절(UI).
|
||||
|
||||
- 절차는 [`2d-3d-process.md`](2d-3d-process.md), 노하우는 [`2d-3d-conversion.md`](2d-3d-conversion.md)
|
||||
- 남은 일 전체는 [`roadmap.md`](roadmap.md)
|
||||
|
||||
---
|
||||
|
||||
## 0. 대전제 — 목표는 바뀌지 않았다
|
||||
|
||||
**이 저장소의 목표는 여전히 `2D DWG → 3D 모델 · IFC` 다.**
|
||||
파라메트릭은 그 위에 얹는 층이지 대체가 아니다. 맨홀 도면 모델링은 **파이프라인을
|
||||
검증하는 과정**이지 그 자체가 목적이 아니다.
|
||||
|
||||
순서를 헷갈리면 안 된다.
|
||||
|
||||
```
|
||||
DWG 를 읽어 3D 를 세운다 ← 본체. 지금 여기
|
||||
그 위에
|
||||
치수를 파라미터로 뽑아 바꾼다 ← 이 문서
|
||||
그 위에
|
||||
바꾼 결과가 맞는지 평가한다 ← 설계 도구가 되는 지점
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 사용자가 원하는 것
|
||||
|
||||
> 설계란, 비슷한 도면을 가져와 **새 환경에 맞게 치수를 바꿔보고**, 맞는지 검토하고,
|
||||
> 다시 바꾸는 **반복 작업**이다.
|
||||
|
||||
그래서 필요한 것은 이것뿐이다.
|
||||
|
||||
```
|
||||
값을 바꾼다 → 모델이 다시 만들어진다
|
||||
```
|
||||
|
||||
**속도는 요구사항이 아니다.** 전체 재생성으로 충분하다(현재 28파트 1~2분).
|
||||
실시간 프리뷰·부분 재생성은 있으면 좋은 것이지 필수가 아니다 — 우선순위 뒤로.
|
||||
|
||||
### 모델러에 패밀리 개념이 없다는 것
|
||||
|
||||
EGModeler 는 Revit 패밀리 같은 것이 없다. 매번 새로 만들어야 한다.
|
||||
**그래도 된다 — 패밀리를 모델러가 아니라 우리가 들고 있으면 된다.**
|
||||
|
||||
| Revit | 우리 |
|
||||
|---|---|
|
||||
| 패밀리 `.rfa` | `assemble()` 조립 로직 |
|
||||
| 타입 파라미터 | `params.json` |
|
||||
| 인스턴스 배치 | egm 재생성 |
|
||||
|
||||
모델러는 **덤 렌더러**다. 형상 지능은 전부 IR 위쪽에 둔다. 지금 계층 구조가
|
||||
이미 그렇게 생겼다 — `core/*` 는 3D 를 모르고 `emit/*` 만 모델러 사정을 안다.
|
||||
|
||||
---
|
||||
|
||||
## 2. D-Cubed 검토 결과 — 쓰지 않는다
|
||||
|
||||
Siemens PLM 의 CAD 부품 라이브러리. 원래 영국 D-Cubed Ltd, 2004년 UGS 인수.
|
||||
|
||||
| 컴포넌트 | 하는 일 |
|
||||
|---|---|
|
||||
| **2D DCM** | 2D 스케치 구속 솔버 (치수·평행·접선·동심) |
|
||||
| **3D DCM** | 3D 어셈블리 구속 솔버 |
|
||||
| AEM / CDM / PGM | 기구학 · 간섭검사 · 2D 프로파일 연산 |
|
||||
|
||||
SolidWorks · Solid Edge · NX 가 쓴다.
|
||||
|
||||
**쓰지 않기로 한 이유**
|
||||
|
||||
- CAD 벤더용 **상용 C++ SDK**. Siemens 와 개별 계약해야 하고 공개 가격이 없다
|
||||
- 우리는 Node 다. FFI/N-API 바인딩을 직접 짜야 한다
|
||||
- **무엇보다, 우리 문제에 구속 솔버가 거의 필요 없다** (아래 3절)
|
||||
|
||||
오픈소스 대안 (필요해질 때 검토)
|
||||
|
||||
| | 라이선스 | 비고 |
|
||||
|---|---|---|
|
||||
| **planegcs** (FreeCAD 스케처 솔버) | LGPL | Eigen 기반. WASM 포팅본이 있다고 알고 있으나 **미확인** |
|
||||
| **SolveSpace `slvs`** | GPL-3 | C 라이브러리 + Python 바인딩. 2D·3D |
|
||||
|
||||
GPL 배포 조건 확인 필요. `vendor/acadrust-dwg` MPL-2.0 을 이미 다루고 있으니 낯선 문제는 아니다.
|
||||
|
||||
---
|
||||
|
||||
## 3. 구속 솔버가 필요 없는 이유
|
||||
|
||||
파라메트릭에는 성격이 다른 두 가지가 있다.
|
||||
|
||||
```
|
||||
① 명시적 (history-based) 치수 = 프로그램의 입력. 값 → 계산 → 형상
|
||||
OpenSCAD · Grasshopper · 그리고 지금 우리 파이프라인
|
||||
② 변분/구속 (variational) 엔티티 + 구속을 선언하고 솔버가 위치를 찾는다
|
||||
SolidWorks 스케치 · D-Cubed
|
||||
```
|
||||
|
||||
요구사항은 **①로 거의 다 된다.** 증거가 이미 코드에 있다 —
|
||||
`drawings/manhole1-trans.mjs` 의 외곽 챔퍼 중간 단면은 상수가 아니라 **식**이다.
|
||||
|
||||
```js
|
||||
const t = (CH1 - CH0) / (CH2 - CH0);
|
||||
const oY = Math.round(1350 + (1650 - 1350) * t); // 1550
|
||||
const oZ = Math.round(-4907 + (-4608 + 4907) * t); // -4708
|
||||
```
|
||||
|
||||
②가 필요한 것은 **관계가 순환할 때**다. "헌치가 두 면에 접하면서 벽 두께는
|
||||
유지" 같은 것. 우리 형상은 거의 직각·45° 라 순환이 잘 안 생긴다.
|
||||
|
||||
**결론: 파라미터 + 식 + 위상 정렬로 시작한다. 솔버는 필요한 자리를 실제로
|
||||
세어본 뒤에 결정한다.**
|
||||
|
||||
---
|
||||
|
||||
## 4. 핵심 구조 변경 — `params.json` 을 파이프라인 한가운데 끼운다
|
||||
|
||||
이 하나가 나머지를 거의 다 푼다.
|
||||
|
||||
```
|
||||
지금 DWG ──build.mjs──→ IR ──→ 3D 치수가 코드 안에 박혀 있다
|
||||
|
||||
바꿀 것 DWG ──fit──→ params.json ──build──→ IR ──→ 3D
|
||||
↑ 사람이 여기만 만진다 도면을 다시 안 본다
|
||||
```
|
||||
|
||||
**빌드가 도면을 안 보는 것이 핵심이다.**
|
||||
|
||||
지금 `assemble()` 은 `loop('단 면 B-B', 2700, 2750)` 로 **치수를 도면 조회 키로**
|
||||
쓴다. 사용자가 2700 을 3000 으로 바꾸면 그런 폐곡선이 없어 예외가 난다.
|
||||
도면에 묶여 있는 한 파라메트릭이 성립하지 않는다.
|
||||
|
||||
```
|
||||
① fit 도면에서 값을 뽑아 params.json 을 쓴다. 출처까지 기록
|
||||
② build params.json 만 읽어 IR 을 만든다. 도면 없이도 돈다
|
||||
```
|
||||
|
||||
부수 효과가 크다.
|
||||
|
||||
- `git diff params.json` 이 곧 "무엇을 바꿨나"
|
||||
- 설계안 A/B/C 를 파일 셋으로 두고 나란히 비교
|
||||
- **새 도면 설정 비용이 첫 도면 한 번으로 끝난다** — 변형은 도면을 안 읽는다
|
||||
|
||||
---
|
||||
|
||||
## 5. 파일을 셋으로 가른다
|
||||
|
||||
지금 `drawings/manhole1.mjs` 한 파일이 세 가지를 섞고 있다.
|
||||
|
||||
```
|
||||
types/전력구_박스.mjs 조립 로직. 파라미터를 받는다 ← 패밀리
|
||||
params/맨홀1.json 그 도면에서 뽑은 값 ← 타입 파라미터
|
||||
drawings/manhole1.mjs DWG 읽기 설정 (레이어·앵커·기준점) ← 추출 규칙
|
||||
```
|
||||
|
||||
**"비슷한 도면 가져와 치수만 바꾼다" = 같은 type + 다른 params.json.**
|
||||
|
||||
```sh
|
||||
cp params/맨홀1.json params/신규현장.json
|
||||
# 구체_외폭 3800 → 4200, 토피 2957 → 3500 수정
|
||||
node src/build.mjs --params 신규현장 # 도면 안 읽는다
|
||||
```
|
||||
|
||||
`src/core/*` 와 `src/ir.mjs` 에 도면 고유값이 들어가면 안 된다는 기존 경계는
|
||||
그대로 유지된다. `types/*` 는 도면 고유값이 아니라 **부재 종류**다.
|
||||
|
||||
---
|
||||
|
||||
## 6. 파라미터 스키마 — 값만으로는 부족하다
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"구체_외폭": { "v": 3800, "src": "measured", "from": "단면 C-C #1 폭" },
|
||||
"벽두께": { "v": 400, "src": "design", "min": 300, "max": 600, "step": 50 },
|
||||
"구체_내폭": { "expr": "구체_외폭 - 2*벽두께" },
|
||||
"헌치": { "v": 150, "src": "design" },
|
||||
"샤프트": [
|
||||
{ "x": 2550, "저부Z": -3157, "정상Z": 0 },
|
||||
{ "x": 13250, "저부Z": -3157, "정상Z": -39 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
넷이 필요하다.
|
||||
|
||||
| 항목 | 왜 |
|
||||
|---|---|
|
||||
| `expr` 식 | 파생값. 위상 정렬해 평가. 솔버 불필요 |
|
||||
| `src` 출처 | `measured` 는 도면과 묶여 있다. 바꾸면 "도면과 다름" 경고 |
|
||||
| `min`/`max`/`step` | 유효 범위. 검증이자 나중에 UI |
|
||||
| **배열** | 치수만이 아니라 **개수**가 바뀐다. 샤프트 2→3, 환기구 없음 |
|
||||
|
||||
배열이 특히 중요하다. `manhole1-trans.mjs` 의 샤프트를 이미
|
||||
`for (const s of shafts)` 로 짜놨다 — 그대로 파라미터로 올라간다.
|
||||
|
||||
### `src` 3분류가 도면과의 계약이다
|
||||
|
||||
```
|
||||
measured 도면에서 뽑았다. 바꾸면 도면과 어긋난다 → 경고하되 막지는 않는다
|
||||
design 사람이 정한다. 자유롭게 바꾼다
|
||||
derived 식으로 나온다. 직접 못 바꾼다
|
||||
```
|
||||
|
||||
기존 `datum.checks` 가 이미 이 자리를 갖고 있다. 확장하면 된다.
|
||||
|
||||
---
|
||||
|
||||
## 7. 설계 도구가 되는 지점 — 규칙과 물량
|
||||
|
||||
치수를 바꾸는 것보다 **바꾼 결과를 즉시 평가하는 것**이 설계다.
|
||||
지금 파이프라인에 없는 층이 이것이고, 실제 가치는 여기서 나온다.
|
||||
|
||||
```
|
||||
rules.mjs 벽두께 ≥ 최소, 내공 높이 ≥ 2,100, 피복 ≥ 기준,
|
||||
헌치가 부재보다 크지 않은가, 샤프트 보어가 벽 안에 있는가,
|
||||
개구부 최소 치수, 케이블랙 이격
|
||||
quantity.mjs 콘크리트 m³ · 굴착 m³ · 거푸집 m² · 되메움
|
||||
```
|
||||
|
||||
**물량은 이미 공짜로 나온다.** 오늘 OBJ 를 발산 정리로 재서 0.0003% 오차로
|
||||
검증했다. 그 코드가 그대로 물량 산출이다.
|
||||
|
||||
```
|
||||
안 A 구체 3,800×4,600 콘크리트 100.5 m³ ✓ 전 규칙 통과
|
||||
안 B 구체 4,200×4,600 콘크리트 108.2 m³ ✓
|
||||
안 C 구체 4,200×4,600 · 벽 300 — ✗ 최소 벽두께 미달
|
||||
```
|
||||
|
||||
이 표가 나오는 순간 도구가 쓸모를 얻는다.
|
||||
|
||||
---
|
||||
|
||||
## 8. 위험한 곳
|
||||
|
||||
**(a) 파라미터가 형상 위상(topology)을 바꾼다.**
|
||||
벽두께를 키우다 헌치보다 커지면 꼭짓점 수가 달라져 loft 대응이 깨진다.
|
||||
`validateIR` 의 꼭짓점 수 검사가 여기서 걸린다(교훈 #16). `min`/`max` 로
|
||||
미리 막고, 걸리면 명확한 메시지를 낸다.
|
||||
|
||||
**(b) 프로파일을 파라미터로 "생성"하면 도면의 실제 형상을 잃는다.**
|
||||
|
||||
```
|
||||
지금 loop('단 면 B-B', 2700, 2750).ring 도면이 준 실제 링
|
||||
이후 box(p.스터브_외폭, p.스터브_외고, p.헌치) 파라미터로 만든 링
|
||||
```
|
||||
|
||||
B-B 내부 링에 있는 **50mm 보도 단차** 같은 자잘한 것이 생성기로 재현이 안 되면
|
||||
조용히 빠진다. **fit 단계에서 "이 링이 생성기로 재현되는가"를 대조**해야 한다.
|
||||
그게 도면과의 마지막 끈이다.
|
||||
|
||||
#### 결정 (2026-08-06) — 3등급으로 기록한다
|
||||
|
||||
완전일치를 요구하지 않는다. `fit` 이 링마다 등급을 매겨 `params.json` 에 남긴다.
|
||||
|
||||
```
|
||||
exact 꼭짓점 집합이 mm 단위로 일치 → 파라미터로 완전 대체
|
||||
tolerant bbox · 면적 · 꼭짓점 수 일치 → 경고를 남기고 파라미터 사용
|
||||
개별 점은 ±ε
|
||||
opaque 생성기로 재현 불가 → 파라미터화하지 않는다.
|
||||
도면 링을 **리터럴로 얼려** params 에 박는다
|
||||
```
|
||||
|
||||
`opaque` 가 핵심이다. "재현 못 하면 파라미터화 안 한다"가 아니라 **"재현 못 하는
|
||||
링은 값으로 얼려 넣는다"** (`src: "measured"` + `ring` 배열). 그러면
|
||||
|
||||
- 4절 불변식(build 가 도면을 안 본다)이 안 깨진다
|
||||
- 50mm 보도 단차 같은 것이 조용히 빠지지 않는다
|
||||
- 그 링은 **못 바꾸는 것**일 뿐이고, 그게 정직하다
|
||||
|
||||
등급 분포가 곧 "이 도면이 얼마나 파라메트릭한가" 의 척도가 된다. `opaque` 가
|
||||
많으면 생성기가 부족한 것이지 도면이 이상한 게 아니다.
|
||||
|
||||
**(c) 재생성하면 모델러의 UID 가 전부 바뀐다.**
|
||||
이름·색은 우리가 다시 붙이니 괜찮지만 사용자가 모델러에서 직접 손댄 것은 날아간다.
|
||||
**"모델러에서 편집하지 않는다"를 규칙으로 못 박아야 한다.** 편집은 params 에서만.
|
||||
|
||||
**(d) 추출 설정은 여전히 도면당 반나절이다.**
|
||||
4절의 fit/build 분리가 이 비용을 **첫 도면 한 번**으로 묶어준다. 그래서 구조
|
||||
변경이 이 위험까지 같이 없앤다.
|
||||
|
||||
---
|
||||
|
||||
## 8.5. 모델러 밖 UI — 값을 바꾸고 "갱신"
|
||||
|
||||
요구사항으로 확정(2026-08-06). 파이프가 이미 CLI 단계 사슬이라 **새 아키텍처가
|
||||
아니라 얇은 껍데기**다.
|
||||
|
||||
### 1단계는 이미 있다 — 읽기 전용 뷰어 (`report.mjs`)
|
||||
|
||||
`node src/report.mjs <도면>` → `out/<도면>.html`. 의존성 없는 한 장짜리다.
|
||||
뷰별 링을 SVG 로 그리고 자기교차·꼭짓점 수·원·IR·부피를 같이 보여준다.
|
||||
|
||||
**만든 날 바로 값을 했다** — 맨홀 #2 의 부피가 2배로 나온 원인(`mh.outer`
|
||||
자기교차)을 숫자로 찾는 데 반나절 걸렸는데, 그림에서는 빨간 X 두 개로 즉시
|
||||
보인다(교훈 #18).
|
||||
|
||||
`build.mjs` 와 **같은 `projectViews()`** 를 쓴다. 뷰어가 자기 변환을 따로 갖고
|
||||
있으면 보여주는 것과 조립되는 것이 갈라진다 — **거짓말하는 뷰어는 없는 것보다
|
||||
나쁘다.**
|
||||
|
||||
편집은 아직 안 된다. `params.json` 이 없어서 편집할 대상이 없다.
|
||||
|
||||
```
|
||||
UI(로컬 웹앱) → params.json → build(도면 안 봄) → IR → emit/egm → run_egm.py → 모델러
|
||||
↘ three.js 프리뷰 (9절·나중)
|
||||
```
|
||||
|
||||
- **입력 위젯이 공짜로 나온다.** 6절의 `min`/`max`/`step`/`src` 가 그대로
|
||||
슬라이더·범위·경고다. 그러라고 스키마를 그렇게 잡았다.
|
||||
- **갱신 버튼이 검증을 태워야 도구가 된다.** 단순 실행이면 폼이고,
|
||||
`validateIR` → `rules.mjs`(7절) → `measure.mjs` 기준선까지 통과 못 하면
|
||||
거부하면 설계 도구다. 여기가 값이 나오는 지점이다.
|
||||
- 재생성 1~2분. 버튼 누르고 기다리는 UX 로 견딘다(1절).
|
||||
|
||||
못 박을 것 둘.
|
||||
|
||||
```
|
||||
갱신 = 씬 초기화 포함. Esc → SelAll → Delete → Esc. `!Cancel` 은 쓰지 않는다
|
||||
모델러에서 직접 편집 금지. 8절 (c) — 갱신하면 UID 가 전부 바뀐다. 편집은 params 에서만
|
||||
```
|
||||
|
||||
**순서상 위치: 10절 1~4 뒤.** 지금 만들면 편집할 `params.json` 이 없다.
|
||||
|
||||
---
|
||||
|
||||
## 9. 나중에 (필수 아님)
|
||||
|
||||
- **브라우저 프리뷰** — IR 은 이미 도구 중립이다. three.js + CSG(`manifold-3d` WASM 이
|
||||
빠르다고 알고 있으나 **미확인**)로 모델러 없이 확인. 속도가 요구사항이 아니므로 뒤로.
|
||||
- **선택 재생성** — 파라미터 → 파트 의존 그래프로 바뀐 파트만 다시. 마찬가지로 뒤로.
|
||||
- **구속 솔버** — 1~5 를 하고 나서 정말 필요한 자리를 세어본 뒤 결정.
|
||||
- **모델 → 도면 역방향** — DWG writer 가 필요하다. 현재 범위 밖.
|
||||
|
||||
---
|
||||
|
||||
## 10. 1차 목표 — **전부 됐다**
|
||||
|
||||
```
|
||||
✔ 1. params.json 스키마 확정 v / expr / src / grade / min·max·step / 배열
|
||||
✔ 2. build.mjs 를 fit / build 로 분리 --params 면 도면을 아예 안 읽는다
|
||||
✔ 3. manhole1 을 params 로 전환 egm 명령 목록이 **바이트 단위로 동일**했다
|
||||
✔ 4. 파라미터 바꿔 재생성 시연 본체_외폭 3800→4200, 종헌치 150→200
|
||||
✔ 5. 물량 measure.mjs 가 재질별로 낸다
|
||||
```
|
||||
|
||||
3번이 좋은 시험대다. `manhole1-trans.mjs` 에 이미 이름이 뚜렷한 값들이 있다 —
|
||||
**챔퍼 200×200, 헌치 150×150, 벽두께 200, 보어 Ø900, 칼라 900, 토피 2,957.**
|
||||
|
||||
5번은 [`../src/measure.mjs`](../src/measure.mjs) 로 **먼저 끝났다.** 실측·기준선
|
||||
대조·재질별 물량이 돈다. 남은 것은 굴착·거푸집·되메움 같은 파생 물량이다.
|
||||
|
||||
---
|
||||
|
||||
## 11. 순서 결정 (2026-08-06)
|
||||
|
||||
**본체(A)를 좁혀서 먼저, 그 다음 파라메트릭(B).** 근거 셋.
|
||||
|
||||
**① 인스턴스 1개로 추상화를 얼리게 된다.**
|
||||
5절의 가치 명제는 "같은 type + 다른 params" 인데 도면이 하나뿐이라 type/params
|
||||
경계를 **검증할 두 번째 인스턴스가 없다.** 맨홀 #2(격실·환기구·침사조)가 스키마에
|
||||
요구할 것 — 배열이 아니라 *선택적 존재*("환기구 없음"), 중첩 격실, 구간별 단면
|
||||
배정표 — 은 지금 `manhole1-trans` 3파트에 안 보인다.
|
||||
|
||||
재작업이 대칭이 아니다. A 먼저 → `assemble()` 본문이 늘어 변환 비용이 커지지만
|
||||
그 변환은 10절 3번 그 자체다(어차피 한 번은 한다). B 먼저 → 스키마를 **두 번** 짠다.
|
||||
|
||||
**② 8절 (b) 결정이 A 에 의존한다.**
|
||||
"어디까지 엄격하게 대조하나"는 *불규칙한 링이 몇 개냐*에 달렸다. 지금 아는
|
||||
사례(B-B 내부 50mm 보도 단차, C-C 외곽 샤프트 융합, 개구 기호로 정점 8,
|
||||
케이블랙 정점 114)는 전부 `manhole1-trans` 밖에서 나왔다. 등급 기준은 정했지만
|
||||
`ε` 와 등급 분포는 표본을 세어본 뒤에 확정한다.
|
||||
|
||||
**③ CIRCLE 파서가 B 의 전제다.**
|
||||
`manhole1-trans.mjs` 의 `BORE_R = 450` 은 원본 엔티티에서 눈으로 읽어 손으로 적은
|
||||
값이다. 8절 (b) 가 말하는 "도면과의 마지막 끈"이 보어에는 **아예 없다.**
|
||||
|
||||
```
|
||||
✔ 0. measure.mjs B 에서 유일하게 당겨온 항목(10절 5번).
|
||||
앞으로 만드는 모든 파트의 회귀 검사가 된다
|
||||
1. CIRCLE 파서 → circle() 헬퍼 손으로 적은 R450 을 대조로. Φ100 ×5 도 풀린다
|
||||
2. manhole1-trans 를 본편으로 통합 기초·잡석 이관. 지금 반쪽 모델이 둘이다
|
||||
3. 맨홀 #2 + 출구 스터브 파라미터 표본을 대표성 있게
|
||||
4. → 10절 1~4
|
||||
5. → 8.5절 UI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 부록 — 2026-08-06 기준 현재 상태
|
||||
|
||||
**되는 것**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `manhole1` | 11파트. 전이부는 X=250 계단 근사, **지붕 개구 없음**(결함) |
|
||||
| `manhole1-trans` | 3파트. 스터브 + 챔퍼 전이 + 본체 + 종방향 헌치 + 샤프트 2기(Ø900 원형 보어) |
|
||||
| 새 IR 연산 | `loft` (2단면, `Loft C=True`), `cylinder` (Z축 한정, `Cylinder S=True`) |
|
||||
| 새 유틸 | `normalizeRing` — loft 꼭짓점 대응용. `addProfile` 이 자동 적용 |
|
||||
| 검증 | 부피 대조 107.1425 실측 / 107.1422 기대 (0.0003%) |
|
||||
| `measure.mjs` | OBJ 실측 · 기준선 회귀 · 재질별 물량. 기준선 `baselines/manhole1-trans.volumes.json` |
|
||||
| CIRCLE | `circles(뷰, 지름, 레이어)`. 보어 R450 이 손으로 적은 수에서 도면 대조로 바뀌었다 |
|
||||
|
||||
**안 되는 것 / 남은 것**
|
||||
|
||||
```
|
||||
맨홀 #2 (X 15,400~18,200) 챔버·격실·환기구·침사조. 제일 크다
|
||||
출구 스터브 (X 18,200~19,200) 맨홀 #2 뒤라 그전에 맨홀을 해야 자리를 얻는다
|
||||
기초·잡석 manhole1.mjs 에 있다. trans 로 옮기면 됨
|
||||
Ø100 관통 5개 환기구 4 · 배수관 1. 평면도의 1개는 X=17,690 으로
|
||||
맨홀 #2 영역이라 그 형상을 세운 뒤에 뚫는다
|
||||
이음매 T 정점 열린 변 49개. 기하는 닫힘. IFC 갈 때 재검토
|
||||
IFC 출력 emit/ifc.mjs 미구현
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 12. 구현 결과 (2026-08-06)
|
||||
|
||||
### 만든 것
|
||||
|
||||
| 파일 | 하는 일 |
|
||||
|---|---|
|
||||
| [`../src/params.mjs`](../src/params.mjs) | 스키마 · 식 평가(위상 정렬) · 검증 · 도면 이탈 감지 |
|
||||
| [`../src/fit.mjs`](../src/fit.mjs) | 도면 → `params/<이름>.json`. 출처(`from`)와 원값(`fitted`)까지 |
|
||||
| [`../src/rules.mjs`](../src/rules.mjs) | 규칙 13개. 위상 8(막는다) · 설계 5(경고) |
|
||||
| [`../src/volume.mjs`](../src/volume.mjs) | IR 을 격자로 평가 — **모델러 없이** "의도" 부피 |
|
||||
| [`../src/ui.mjs`](../src/ui.mjs) | 편집 + 갱신. `node src/ui.mjs manhole1` → `localhost:7331` |
|
||||
| [`../src/core/pick.mjs`](../src/core/pick.mjs) | 도면 조회 도우미. **`fit()` 만 쓴다** |
|
||||
|
||||
### 확인된 것
|
||||
|
||||
```
|
||||
파라미터 스칼라 49 (measured 38 · design 3 · derived 8) + 배열 1(샤프트)
|
||||
링 11 (opaque 8 · exact 2 · tolerant 1)
|
||||
규칙 13개 중 위반 0
|
||||
기하 불변 전환 전후 egm.json **바이트 동일**
|
||||
도면 없이 views.json 을 치운 채 --params 로 빌드 → 역시 바이트 동일
|
||||
```
|
||||
|
||||
### 8절 (b) 결정이 실제로 어떻게 쓰였나
|
||||
|
||||
`opaque` 8개가 결정의 값을 증명한다. B-B 내부(50mm 보도 단차), C-C 내부(헌치),
|
||||
E-E 외곽(23꼭짓점 오목 윤곽) 같은 것은 파라미터로 재현이 안 된다. 좌표째 얼려
|
||||
넣으니 **도면 없이도 형상이 그대로** 나오고, 자잘한 형상이 조용히 빠지지도 않는다.
|
||||
그 링들은 못 바꿀 뿐이고, 그게 정직하다.
|
||||
|
||||
`exact` 2개는 개구부다 — 개구 기호의 네 모서리라 직사각형으로 완전히 재현된다.
|
||||
|
||||
### 규칙이 폼과 도구를 가른다
|
||||
|
||||
```
|
||||
✗ 맨홀 내벽이 뒤집혔다: 16900 ≥ 16700 (벽두께 1500)
|
||||
(맨홀 벽두께가 절반을 넘으면 내부가 사라진다)
|
||||
```
|
||||
|
||||
벽두께를 1,500 으로 바꾸면 **빌드가 거부한다**(exit 1). 모델러까지 가서 비틀린
|
||||
면으로 만나는 것보다 훨씬 싸다. 설계 규칙(내공 높이·토피·최소 벽두께)은 경고만
|
||||
하고 사람이 판단한다.
|
||||
|
||||
### 도면 이탈은 막지 않고 남긴다
|
||||
|
||||
```
|
||||
⚠ 도면에서 뽑은 값이 바뀌어 있다 — 이 모델은 원 도면과 다르다
|
||||
본체_외폭 도면 3800 → 지금 4200 C-C 구체 외폭
|
||||
```
|
||||
|
||||
설계를 바꾸는 게 이 층의 목적이니 막지 않는다. 다만 "도면대로 만든 모델"인 척하게
|
||||
두면 안 된다.
|
||||
|
||||
### 그림 위에서 치수를 고친다
|
||||
|
||||
`render.mjs --dims` 가 **파라미터를 가리키는 치수선**을 렌더에 얹는다. 2D 도면이
|
||||
치수를 적어 형상을 증명하듯이, 우리 렌더도 "이 길이가 이 파라미터다" 를 그림에서
|
||||
바로 보이게 한다.
|
||||
|
||||
```
|
||||
span 두 점 사이 **길이** 연장선 + 치수선 + 이름 상자
|
||||
level 한 좌표의 **위치** 그 자리를 가로지르는 선 + 이름 상자
|
||||
```
|
||||
|
||||
둘로 나눈 이유가 있다. 파라미터의 절반은 길이가 아니라 **좌표**다(`본체_상단Z`
|
||||
같은 표고). 그런 것을 억지로 길이로 그리면 거짓말이 된다 — 표고선으로 그린다.
|
||||
|
||||
같이 나오는 `model-<축>.dims.json` 이 각 라벨의 자리를 **캔버스 비율**로 담는다.
|
||||
UI 가 그 자리에 `<input>` 을 얹으므로 **그림에서 값을 고칠 수 있다**. 비율이라
|
||||
창 크기가 바뀌어도 따라간다. 표와 그림의 입력칸은 서로 동기화된다.
|
||||
|
||||
라벨이 많으면 겹치므로 위에서부터 훑으며 겹치는 것을 아래로 민다. 치수선 자체는
|
||||
안 움직인다 — 라벨만.
|
||||
|
||||
**47개**가 그림에 올라간다. 빠진 둘(`커터여유`·`면겹침_여유`)은 형상이 아니라
|
||||
수치 여유값이라 패널에만 둔다.
|
||||
|
||||
### UI 는 정말로 얇았다
|
||||
|
||||
파이프가 이미 CLI 단계 사슬이라, UI 가 한 일은 `params.json` 편집 + 그 사슬을
|
||||
순서대로 돌리는 것뿐이다. 갱신 사슬:
|
||||
|
||||
```
|
||||
build --params → emit → run_egm --reset --export → measure --ir → render --dims
|
||||
```
|
||||
|
||||
`--reset` 이 필수다. 안 비우면 갱신할 때마다 객체가 쌓여 `modelCount` 대조가
|
||||
무의미해진다. 다만 **연달아 여러 번 하면 안 된다** — 초기화를 10번쯤 반복했더니
|
||||
모델러 파이프가 죽었다. 갱신 1회당 1번이면 문제없다.
|
||||
|
||||
`min`/`max`/`step` 이 그대로 입력 위젯이 됐고, `src` 는 태그, `fitted` 는 변경
|
||||
표시가 됐다. **그러라고 6절에서 그렇게 설계했던 것이 그대로 맞았다.**
|
||||
|
||||
### 남은 것
|
||||
|
||||
- **맨홀 #2 부피 9.32 손실** — 우리 IR 은 맞고(74.68) 모델러가 흘린다(65.36).
|
||||
원인은 면으로만 맞닿은 union (교훈 #19). 제대로 된 해법은 맨홀을 **수평 단면에서
|
||||
Z 로 쌓는 것** — 조각이 Z 로 진짜 겹치고 평면 헌치도 같이 따라온다
|
||||
- 외부 헌치 5개 (평면 좌표 확정, Z 구간 미확정)
|
||||
- `quantity.mjs` — 굴착·거푸집·되메움 같은 파생 물량
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
# 로드맵 — 일반 도면 세트 → 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 | — | 기준선 없음. 통합 후 뜬다 |
|
||||
@@ -0,0 +1,535 @@
|
||||
<!doctype html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>교각 P9 — 촬영 런시트 & 대본</title>
|
||||
<style>
|
||||
html{color-scheme:light dark}
|
||||
/* ── 팔레트는 모델 자체에서 가져왔다 ────────────────────────────
|
||||
코핑 주황 · 기둥 파랑 · 기초 초록 · 말뚝 보라. 그 색이 곧 이 영상의 주인공이다. */
|
||||
:root{
|
||||
--ground:#F5F2EE; --surface:#FFFFFF; --slab:#181C22; --slab-ink:#D9E2ED;
|
||||
--line:#DED7CE; --line-soft:#EBE5DC;
|
||||
--ink:#191E25; --ink-2:#4A5462; --ink-3:#7C8794;
|
||||
--cap:#C2732F; --col:#3E7CBC; --ftg:#4E9750; --pil:#8B4A9A; --brg:#C4413F;
|
||||
--ok:#3E8F5C; --warn:#B07E14;
|
||||
--accent:var(--cap);
|
||||
--mono:ui-monospace,"Cascadia Mono","Consolas","D2Coding",monospace;
|
||||
--sans:"Pretendard","Malgun Gothic","Apple SD Gothic Neo",system-ui,sans-serif;
|
||||
}
|
||||
@media (prefers-color-scheme:dark){
|
||||
:root:not([data-theme="light"]){
|
||||
--ground:#0E1116; --surface:#151A21; --slab:#0A0D11; --slab-ink:#CBD6E3;
|
||||
--line:#252C36; --line-soft:#1C222B;
|
||||
--ink:#DDE5EE; --ink-2:#94A2B3; --ink-3:#65717F;
|
||||
--cap:#D68444; --col:#5894D0; --ftg:#74B06C; --pil:#A968B8; --brg:#DC5A58;
|
||||
--ok:#5FBF7F; --warn:#E0B33C;
|
||||
}
|
||||
}
|
||||
:root[data-theme="dark"]{
|
||||
--ground:#0E1116; --surface:#151A21; --slab:#0A0D11; --slab-ink:#CBD6E3;
|
||||
--line:#252C36; --line-soft:#1C222B;
|
||||
--ink:#DDE5EE; --ink-2:#94A2B3; --ink-3:#65717F;
|
||||
--cap:#D68444; --col:#5894D0; --ftg:#74B06C; --pil:#A968B8; --brg:#DC5A58;
|
||||
--ok:#5FBF7F; --warn:#E0B33C;
|
||||
}
|
||||
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0; background:var(--ground); color:var(--ink);
|
||||
font:15.5px/1.7 var(--sans); -webkit-font-smoothing:antialiased}
|
||||
.wrap{max-width:1080px; margin:0 auto; padding:36px 22px 90px}
|
||||
|
||||
/* ── 머리 ────────────────────────────────────────────────── */
|
||||
header{display:flex; flex-wrap:wrap; align-items:flex-end; gap:18px 28px;
|
||||
padding-bottom:20px; border-bottom:2px solid var(--ink)}
|
||||
h1{margin:0; font-size:29px; line-height:1.2; letter-spacing:-.02em; text-wrap:balance}
|
||||
h1 small{display:block; font:600 12px/1.6 var(--mono); letter-spacing:.16em;
|
||||
color:var(--accent); text-transform:uppercase; margin-bottom:7px}
|
||||
.facts{margin-left:auto; display:flex; gap:22px; font:600 12px/1.5 var(--mono);
|
||||
font-variant-numeric:tabular-nums; color:var(--ink-3)}
|
||||
.facts b{display:block; font-size:19px; color:var(--ink); letter-spacing:-.01em}
|
||||
|
||||
/* ── 탭 ──────────────────────────────────────────────────── */
|
||||
.tabs{display:flex; flex-wrap:wrap; gap:2px; margin:22px 0 0;
|
||||
border-bottom:1px solid var(--line)}
|
||||
.tabs button{appearance:none; border:0; background:none; cursor:pointer;
|
||||
font:600 13.5px/1 var(--sans); color:var(--ink-3);
|
||||
padding:12px 15px; border-bottom:2px solid transparent; margin-bottom:-1px;
|
||||
transition:color .12s}
|
||||
.tabs button:hover{color:var(--ink-2)}
|
||||
.tabs button[aria-selected="true"]{color:var(--ink); border-bottom-color:var(--accent)}
|
||||
.tabs button:focus-visible{outline:2px solid var(--accent); outline-offset:-2px; border-radius:3px}
|
||||
.panel{display:none; padding-top:26px}
|
||||
.panel.on{display:block}
|
||||
|
||||
/* ── 타임라인 띠 ─────────────────────────────────────────── */
|
||||
.tl{display:flex; height:34px; border:1px solid var(--line); border-radius:3px;
|
||||
overflow:hidden; margin-bottom:6px}
|
||||
.tl div{position:relative; display:grid; place-items:center; min-width:0;
|
||||
font:600 10.5px/1 var(--mono); color:#fff; letter-spacing:.02em;
|
||||
border-right:1px solid rgba(0,0,0,.28)}
|
||||
.tl div:last-child{border-right:0}
|
||||
.tl span{opacity:.92; white-space:nowrap; overflow:hidden}
|
||||
.tl-key{display:flex; justify-content:space-between; font:600 11px/1 var(--mono);
|
||||
color:var(--ink-3); font-variant-numeric:tabular-nums; margin-bottom:30px}
|
||||
|
||||
/* ── 컷 ──────────────────────────────────────────────────── */
|
||||
.cut{display:grid; grid-template-columns:118px 1fr; gap:0 22px;
|
||||
padding:22px 0; border-top:1px solid var(--line-soft)}
|
||||
.cut:first-of-type{border-top:0}
|
||||
.rail{font:600 12px/1.55 var(--mono); font-variant-numeric:tabular-nums;
|
||||
color:var(--ink-3); padding-top:3px}
|
||||
.rail .tc{display:block; font-size:15px; color:var(--ink); letter-spacing:-.02em}
|
||||
.rail .dur{display:block}
|
||||
.rail .clip{display:inline-block; margin-top:8px; padding:2px 7px; border-radius:3px;
|
||||
background:var(--line-soft); color:var(--ink-2); font-size:11px; letter-spacing:.04em}
|
||||
.cut h3{margin:0 0 3px; font-size:17.5px; letter-spacing:-.01em}
|
||||
.cut .sub{margin:0 0 13px; color:var(--ink-3); font-size:13px}
|
||||
.hookmark{color:var(--accent)}
|
||||
|
||||
pre{margin:0 0 13px; background:var(--slab); color:var(--slab-ink);
|
||||
border-radius:4px; padding:12px 14px; overflow-x:auto;
|
||||
font:12.5px/1.75 var(--mono)}
|
||||
pre .c{color:#6E7D8E}
|
||||
pre .h{color:#E9B872}
|
||||
|
||||
.say{margin:0; padding:14px 16px 14px 18px; background:var(--surface);
|
||||
border:1px solid var(--line); border-left:3px solid var(--accent);
|
||||
border-radius:0 4px 4px 0; font-size:15px}
|
||||
.say b{color:var(--accent)}
|
||||
.say .beat{display:block; height:9px}
|
||||
|
||||
.screen{margin:12px 0 0; padding:0; list-style:none;
|
||||
font:12.5px/1.85 var(--mono); color:var(--ink-2)}
|
||||
.screen li{padding-left:17px; position:relative}
|
||||
.screen li:before{content:"›"; position:absolute; left:3px; color:var(--accent); font-weight:700}
|
||||
.screen b{color:var(--ink); font-weight:600}
|
||||
|
||||
/* ── 표 ──────────────────────────────────────────────────── */
|
||||
table{width:100%; border-collapse:collapse; margin:0 0 24px; font-size:13.5px}
|
||||
th,td{text-align:left; padding:9px 12px; border-bottom:1px solid var(--line-soft);
|
||||
vertical-align:top}
|
||||
th{font:600 11px/1.5 var(--mono); letter-spacing:.09em; text-transform:uppercase;
|
||||
color:var(--ink-3); border-bottom:1px solid var(--line)}
|
||||
td code{font:12.5px/1.6 var(--mono); color:var(--accent)}
|
||||
.num{font-variant-numeric:tabular-nums; text-align:right; white-space:nowrap}
|
||||
.tw{overflow-x:auto}
|
||||
|
||||
h2{margin:34px 0 12px; font-size:20px; letter-spacing:-.01em}
|
||||
h2:first-child{margin-top:0}
|
||||
p{margin:0 0 14px; max-width:68ch}
|
||||
.lede{color:var(--ink-2); font-size:14.5px}
|
||||
.chip{display:inline-block; padding:1px 8px; border-radius:3px; font:600 11px/1.7 var(--mono);
|
||||
letter-spacing:.04em}
|
||||
.c-cap{background:color-mix(in srgb,var(--cap) 18%,transparent); color:var(--cap)}
|
||||
.c-ok{background:color-mix(in srgb,var(--ok) 18%,transparent); color:var(--ok)}
|
||||
.c-warn{background:color-mix(in srgb,var(--warn) 20%,transparent); color:var(--warn)}
|
||||
.note{border:1px solid var(--line); border-radius:4px; padding:14px 16px;
|
||||
background:var(--surface); margin:0 0 20px}
|
||||
.note b{display:block; margin-bottom:4px}
|
||||
@media (max-width:660px){
|
||||
.cut{grid-template-columns:1fr; gap:10px}
|
||||
.rail{display:flex; gap:12px; align-items:baseline; padding:0}
|
||||
.facts{margin-left:0}
|
||||
}
|
||||
@media (prefers-reduced-motion:reduce){*{transition:none!important}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="wrap">
|
||||
|
||||
<header>
|
||||
<h1><small>촬영 런시트 · 컷별 대본</small>2D 도면 한 장에서<br>교각 하나를 세운다</h1>
|
||||
<div class="facts">
|
||||
<span><b>11</b>컷</span>
|
||||
<span><b>5:54</b>총길이</span>
|
||||
<span><b>75</b>부재</span>
|
||||
<span><b>0.0000</b>오차</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="tabs" role="tablist">
|
||||
<button role="tab" aria-selected="true" data-p="p1">컷 순서 · 대본</button>
|
||||
<button role="tab" aria-selected="false" data-p="p2">실행 명령</button>
|
||||
<button role="tab" aria-selected="false" data-p="p3">화면 체크</button>
|
||||
<button role="tab" aria-selected="false" data-p="p4">사고 대응</button>
|
||||
<button role="tab" aria-selected="false" data-p="p5">업로드</button>
|
||||
</div>
|
||||
|
||||
<!-- ══════════ 1. 컷 순서 · 대본 ══════════ -->
|
||||
<section class="panel on" id="p1" role="tabpanel">
|
||||
|
||||
<div class="tl">
|
||||
<div style="flex:14; background:var(--cap)"><span>HOOK</span></div>
|
||||
<div style="flex:24.4; background:var(--ink-3)"><span>01 도면</span></div>
|
||||
<div style="flex:11.1; background:var(--col)"><span>02</span></div>
|
||||
<div style="flex:12.9; background:var(--col)"><span>03</span></div>
|
||||
<div style="flex:48.5; background:var(--col)"><span>04 진단</span></div>
|
||||
<div style="flex:24.8; background:var(--ftg)"><span>05</span></div>
|
||||
<div style="flex:16.7; background:var(--ftg)"><span>06</span></div>
|
||||
<div style="flex:82; background:var(--cap)"><span>07 모델링</span></div>
|
||||
<div style="flex:25.3; background:var(--pil)"><span>08</span></div>
|
||||
<div style="flex:44.3; background:var(--pil)"><span>09 IFC</span></div>
|
||||
<div style="flex:50.1; background:var(--brg)"><span>10 마무리</span></div>
|
||||
</div>
|
||||
<div class="tl-key"><span>0:00</span><span>도면 → 진단 → 파라미터 → 모델링 → 검증 → IFC</span><span>5:54</span></div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">0:00</span><span class="dur">14.0초</span>
|
||||
<span class="clip">07 발췌</span></div>
|
||||
<div>
|
||||
<h3 class="hookmark">HOOK — 결과부터 보여준다</h3>
|
||||
<p class="sub">07번에서 교각이 서는 12~15초만 잘라 맨 앞에. 자막·설명 없이 화면만.</p>
|
||||
<p class="say">이거, 사람이 만든 모델이 아닙니다.<span class="beat"></span>
|
||||
2D 도면 한 장을 읽어서, 명령 한 줄로 자동으로 서는 겁니다.<span class="beat"></span>
|
||||
교각 하나. 부재 <b>일흔다섯 개</b>. 오차 <b>0.0000</b>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">0:14</span><span class="dur">24.4초</span>
|
||||
<span class="clip">01.mp4</span></div>
|
||||
<div>
|
||||
<h3>도면 — 출발점</h3>
|
||||
<p class="sub">CAD 에서 교각 일반도. 뷰를 훑고 표까지.</p>
|
||||
<p class="say">시작은 이 도면입니다. 교각 일반도 한 장.<span class="beat"></span>
|
||||
A1 한 장에 평면도, 정면도, 단면도, 기초 평면도, 그리고 표 세 개.
|
||||
토목 하시는 분들껜 익숙한 화면이죠.<span class="beat"></span>
|
||||
그런데 이 파일 하나에 <b>도면이 놓이는 자리가 열일곱 개</b> 있습니다.
|
||||
옛 작업 흔적이 그대로 쌓여 있는 거죠.
|
||||
<b>출력용 도곽이 씌워진 건 그중 하나뿐</b>입니다.<span class="beat"></span>
|
||||
어느 게 진짜인지 고르는 것부터가 일입니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">0:38</span><span class="dur">11.1초</span>
|
||||
<span class="clip">02.mp4</span></div>
|
||||
<div>
|
||||
<h3>뷰를 가른다</h3>
|
||||
<pre><span class="c">1단계</span> node src/run.mjs pier-p9</pre>
|
||||
<p class="say">첫 명령입니다. 도면을 읽고 뷰를 가릅니다.<span class="beat"></span>
|
||||
평면도 <b>14,000 × 3,200</b>. 도면에 적힌 치수와 정확히 같습니다.
|
||||
여기가 안 맞으면 뒤는 볼 것도 없습니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">0:50</span><span class="dur">12.9초</span>
|
||||
<span class="clip">03.mp4</span></div>
|
||||
<div>
|
||||
<h3>끊김 진단</h3>
|
||||
<pre><span class="c">2단계</span> node src/gaps.mjs pier-p9</pre>
|
||||
<p class="say">다음은 끊김 진단입니다.<span class="beat"></span>
|
||||
윤곽이 안 닫히는 이유가 <b>레이어를 잘못 골랐다</b>인지
|
||||
<b>도면에 선이 없다</b>인지를 가릅니다.<span class="beat"></span>
|
||||
앞은 설정 한 줄, 뒤는 도면 수정. 대응 비용이 백 배 차이 납니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">1:02</span><span class="dur">48.5초</span>
|
||||
<span class="clip">04.mp4</span></div>
|
||||
<div>
|
||||
<h3>도면이 말하는 네 가지 방식</h3>
|
||||
<pre><span class="c">3단계</span> node src/build.mjs pier-p9 --loops
|
||||
node src/build.mjs pier-p9 --circles
|
||||
node src/build.mjs pier-p9 --blocks
|
||||
node src/table.mjs pier-p9 --title "교량받침 ELEVATION TABLE"</pre>
|
||||
<p class="say">도면은 형상으로만 말하지 않습니다.<span class="beat"></span>
|
||||
닫힌 윤곽, 원, 블록, 그리고 표.<span class="beat"></span>
|
||||
기둥은 지름 <b>2,200 원</b>으로 들어 있고,
|
||||
말뚝 <b>마흔네 본</b>은 폐곡선이 아니라 <b>블록</b>입니다.
|
||||
블록 배율 <b>254</b>가 곧 반지름이고요. 도면 주기의 Φ508 과 맞습니다.<span class="beat"></span>
|
||||
받침 여섯 기의 적층 높이와 절대표고는 도면 어디에도 안 그려져 있습니다.
|
||||
<b>표에만</b> 있습니다. 그래서 표도 읽습니다 — 이름표 아래를 찾아서, 병합 셀까지.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">1:51</span><span class="dur">24.8초</span>
|
||||
<span class="clip">05.mp4</span></div>
|
||||
<div>
|
||||
<h3>도면이 파라미터가 된다</h3>
|
||||
<pre><span class="c">4단계</span> node src/fit.mjs pier-p9
|
||||
<span class="c">5단계</span> node src/build.mjs pier-p9</pre>
|
||||
<p class="say">여기서 도면이 <b>파라미터</b>가 됩니다.<span class="beat"></span>
|
||||
서른 개 중 스물한 개는 도면에서 잰 값,
|
||||
다섯 개는 도면이 안 주는 설계값,
|
||||
네 개는 식으로 나오는 값입니다.<span class="beat"></span>
|
||||
어느 게 어디서 왔는지 전부 기록됩니다.
|
||||
<b>도면에서 읽은 척하지 않는 것</b> — 이게 핵심입니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">2:16</span><span class="dur">16.7초</span>
|
||||
<span class="clip">06.mp4</span></div>
|
||||
<div>
|
||||
<h3>3D 툴 없이 부피부터</h3>
|
||||
<pre><span class="c">6단계</span> node src/volume.mjs pier-p9</pre>
|
||||
<p class="say">3D 툴을 켜기 전에 부피부터 냅니다.<span class="beat"></span>
|
||||
<b>657.0569</b> 세제곱미터.<span class="beat"></span>
|
||||
이게 <b>우리 의도</b>입니다. 이따 모델러가 만든 것과 대조할 기준이죠.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">2:32</span><span class="dur">82.0초</span>
|
||||
<span class="clip">07.mp4</span></div>
|
||||
<div>
|
||||
<h3 class="hookmark">모델러에 교각이 선다</h3>
|
||||
<pre><span class="c">7단계</span> node src/emit/egm.mjs out/pier-p9.ir.json
|
||||
python src/run_egm.py out/pier-p9.egm.json --export=out/pier-p9.obj</pre>
|
||||
<p class="say">이제 실행입니다.<span class="beat"></span>
|
||||
78개 파트, <b>329단계</b> 명령이 모델러로 갑니다.<span class="beat"></span>
|
||||
코핑, 원형 기둥 두 본, 확대기초 두 기, 버림,
|
||||
강관말뚝 마흔네 본,
|
||||
받침 여섯 기 — 받침콘크리트, 무수축 모르타르, 탄성받침, 솔플레이트까지.<span class="beat"></span>
|
||||
사람 손은 안 들어갑니다.<span class="beat"></span>
|
||||
<em>(말 없이 20초 — 세워지는 걸 보여준다)</em><span class="beat"></span>
|
||||
중요한 건 속도가 아닙니다.<span class="beat"></span>
|
||||
같은 명령을 다시 돌리면 <b>같은 모델</b>이 나온다는 것.
|
||||
도면이 바뀌면 파라미터만 고쳐서 다시 세울 수 있다는 것입니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">3:54</span><span class="dur">25.3초</span>
|
||||
<span class="clip">08.mp4</span></div>
|
||||
<div>
|
||||
<h3>의도 vs 결과 — 이 영상의 핵심</h3>
|
||||
<pre><span class="c">8단계</span> egm status
|
||||
node src/measure.mjs pier-p9 --ir</pre>
|
||||
<p class="say">그리고 검증입니다.<span class="beat"></span>
|
||||
<b>우리가 뜻한 부피</b>와 <b>모델러가 실제로 만든 부피</b>를 부재마다 대조합니다.<span class="beat"></span>
|
||||
일흔다섯 개 전부 차이 <b>0.0000</b>. 열린 변 0.<span class="beat"></span>
|
||||
부피가 맞으면 형상이 맞습니다. 눈으로 보고 「비슷하네」로 끝내지 않습니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">4:20</span><span class="dur">44.3초</span>
|
||||
<span class="clip">09.mp4</span></div>
|
||||
<div>
|
||||
<h3>IFC 로 넘긴다</h3>
|
||||
<pre><span class="c">9단계</span> node src/emit/ifc.mjs out/pier-p9.ir.json</pre>
|
||||
<p class="say">마지막은 IFC 입니다.<span class="beat"></span>
|
||||
IfcBeam, IfcColumn, IfcFooting, <b>IfcPile 마흔네 개</b>, IfcPlate, IfcDiscreteAccessory.<span class="beat"></span>
|
||||
메시로 안 내보냈습니다. 원기둥은 <b>진짜 원</b>으로 나갑니다.
|
||||
그래야 받는 쪽에서 「왜 지름이 508이 아니냐」를 다시 겪지 않습니다.<span class="beat"></span>
|
||||
절대 위치는 <b>IfcMapConversion</b> 으로 넣었습니다.
|
||||
측량좌표와 방위각은 받침배치도 표에서 가져왔고요.<span class="beat"></span>
|
||||
뷰어에서 열면 이렇게 나옵니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cut">
|
||||
<div class="rail"><span class="tc">5:04</span><span class="dur">50.1초</span>
|
||||
<span class="clip">10.mp4</span></div>
|
||||
<div>
|
||||
<h3>그림으로도 본다 · 마무리</h3>
|
||||
<pre><span class="c">10단계</span> node src/render.mjs pier-p9 --png --width 900</pre>
|
||||
<p class="say">부피가 맞아도 형상이 맞는 건 아닙니다. 그래서 그림으로도 봅니다.<span class="beat"></span>
|
||||
정투영 세 방향. <b>검은 자리는 그 방향으로 재료가 없다</b>는 뜻입니다.
|
||||
관통구나 빠진 부재가 바로 드러나죠.<span class="beat"></span>
|
||||
정리하면 — 도면 한 장에서 부재 일흔다섯 개, 657 세제곱미터,
|
||||
오차 0.0000, IFC 까지.<span class="beat"></span>
|
||||
사람이 판단한 건 <b>「무엇을 어떻게 조립할까」 하나뿐</b>입니다.
|
||||
나머지는 전부 도면이 말한 겁니다.<span class="beat"></span>
|
||||
다음 편에서는 <b>꺾인 교각</b>을 해보겠습니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- ══════════ 2. 실행 명령 ══════════ -->
|
||||
<section class="panel" id="p2" role="tabpanel">
|
||||
<p class="lede">작업 디렉터리 <code>d:\MYCLAUDE_PROJECT\dwg2model</code> · PowerShell.
|
||||
씬은 비워 뒀고 기준선은 문양 제외본으로 갱신돼 있다. 0번부터 순서대로.</p>
|
||||
|
||||
<h2>0 · 촬영 전 확인 <span class="chip c-warn">필수</span></h2>
|
||||
<pre>egm guide | python -c "import sys,json;print('명령',len(json.loads(sys.stdin.buffer.read().decode('utf-8-sig'))))"</pre>
|
||||
<p><b>208</b> 이어야 한다. <b>39</b> 면 뷰어 모드 — 모델링 명령이 등록조차 안 된다.
|
||||
모델러 UI 에서 <code>Assistive Features → Working Mode Setting → Viewer & Modeler Use</code>.</p>
|
||||
|
||||
<h2>1–10 · 본편</h2>
|
||||
<pre><span class="c"># 1 도면 읽기 — 뷰 분리 · 표 색인 [02.mp4]</span>
|
||||
node src/run.mjs pier-p9
|
||||
|
||||
<span class="c"># 2 끊김 진단 [03.mp4]</span>
|
||||
node src/gaps.mjs pier-p9
|
||||
|
||||
<span class="c"># 3 도면이 말하는 네 방식 [04.mp4]</span>
|
||||
node src/build.mjs pier-p9 --loops
|
||||
node src/build.mjs pier-p9 --circles
|
||||
node src/build.mjs pier-p9 --blocks
|
||||
node src/table.mjs pier-p9 --title "교량받침 ELEVATION TABLE"
|
||||
|
||||
<span class="c"># 4+5 파라미터 → 조립 스펙 [05.mp4]</span>
|
||||
node src/fit.mjs pier-p9
|
||||
node src/build.mjs pier-p9
|
||||
|
||||
<span class="c"># 6 모델러 없이 부피 — 「의도」 [06.mp4]</span>
|
||||
node src/volume.mjs pier-p9
|
||||
|
||||
<span class="c"># 7 번역 · 실행 — 교각이 선다 [07.mp4] ★</span>
|
||||
node src/emit/egm.mjs out/pier-p9.ir.json
|
||||
python src/run_egm.py out/pier-p9.egm.json --export=out/pier-p9.obj
|
||||
|
||||
<span class="c"># 8 의도 vs 결과 [08.mp4] ★</span>
|
||||
egm status
|
||||
node src/measure.mjs pier-p9 --ir
|
||||
|
||||
<span class="c"># 9 IFC [09.mp4]</span>
|
||||
node src/emit/ifc.mjs out/pier-p9.ir.json
|
||||
|
||||
<span class="c"># 10 그림 [10.mp4]</span>
|
||||
node src/render.mjs pier-p9 --png --width 900</pre>
|
||||
|
||||
<h2>덤 · 파라메트릭 (다음 편 예고용)</h2>
|
||||
<pre>node src/ui.mjs pier-p9 --port 7333
|
||||
<span class="c"># 브라우저 http://localhost:7333 → 값 수정 → 갱신 → 검증 사슬이 돈다</span></pre>
|
||||
|
||||
<div class="note">
|
||||
<b>미관 문양은 뺐다</b>
|
||||
단면(50 띠 + 하단 100 돌출)은 도면에서 나왔지만 정면도의 내부 능선을 아직 못 살렸다.
|
||||
<code>params/pier-p9.json</code> 의 <code>미관문양_포함</code> 을 <code>1</code> 로 바꾸면 다시 선다.
|
||||
지금 기준선은 <b>문양 제외 · 75파트 · 657.0569 m³</b> 기준이다.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════ 3. 화면 체크 ══════════ -->
|
||||
<section class="panel" id="p3" role="tabpanel">
|
||||
<p class="lede">컷마다 <b>화면에 반드시 보여야 할 것</b>. 안 나오면 다시 찍는다.</p>
|
||||
<div class="tw">
|
||||
<table>
|
||||
<tr><th>컷</th><th>화면에 나와야 하는 것</th><th class="num">길이</th></tr>
|
||||
<tr><td><b>HOOK</b></td><td>모델러 뷰포트에 교각이 서는 순간. 색이 부재별로 갈려 있어야 한다 —
|
||||
코핑 주황 · 기둥 파랑 · 기초 초록 · 말뚝 보라</td><td class="num">14.0</td></tr>
|
||||
<tr><td><b>01</b></td><td>도곽 · 평면도 · 정면도 · 단면도 · 기초평면도 · 표. 한 화면에 다 보이는 장면 하나</td><td class="num">24.4</td></tr>
|
||||
<tr><td><b>02</b></td><td><code>평면도 14000 3200 ✓</code> 와 <code>✓ 검증 통과</code>, 그리고 <code>표 3개</code></td><td class="num">11.1</td></tr>
|
||||
<tr><td><b>03</b></td><td>「레이어 오분류 0 / 선 누락 n」 갈라지는 줄</td><td class="num">12.9</td></tr>
|
||||
<tr><td><b>04</b></td><td><code>Ø2200</code> 원 2개 · <code>CSPILEH 배율 254</code> 44개 ·
|
||||
표 6행 18열(NO./h1~h4/A/B/S1/S2)</td><td class="num">48.5</td></tr>
|
||||
<tr><td><b>05</b></td><td><code>measured 21 · design 5 · derived 4</code> · <code>최종 산출 75</code></td><td class="num">24.8</td></tr>
|
||||
<tr><td><b>06</b></td><td><code>합계 657.0569</code></td><td class="num">16.7</td></tr>
|
||||
<tr><td><b>07</b></td><td><code>파트 78 → 단계 329</code> · 뷰포트에 부재가 쌓이는 과정 ·
|
||||
끝에 <code>modelCount 75</code></td><td class="num">82.0</td></tr>
|
||||
<tr><td><b>08</b></td><td><b>차이 0.0000 열이 쭉 이어지는 화면</b> · <code>열린변 0</code> · 재질별 물량</td><td class="num">25.3</td></tr>
|
||||
<tr><td><b>09</b></td><td><code>IFCPILE 44</code> 등 클래스 목록 · IFC 뷰어에서 열린 모델</td><td class="num">44.3</td></tr>
|
||||
<tr><td><b>10</b></td><td>정투영 X·Y·Z 세 장. 검은 배경과 부재 색이 대비되는 것</td><td class="num">50.1</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2>영상에서 쓸 숫자</h2>
|
||||
<div class="tw">
|
||||
<table>
|
||||
<tr><th>말할 것</th><th>값</th></tr>
|
||||
<tr><td>도곽 한 장 안에</td><td>뷰 7 + 표 3.<br>
|
||||
그런데 파일에는 도면 자리가 <b>17개</b> — 도곽이 씌워진 건 <b>1개</b>,
|
||||
나머지는 구조선만 남은 옛 작업 흔적</td></tr>
|
||||
<tr><td>단위 확정</td><td>독립 근거 4개로 <b>1단위 = 1 mm</b></td></tr>
|
||||
<tr><td>파단선</td><td>그려진 기둥 6,100 ↔ 실제 <b>33,800</b>. 생략량 27,700 을 도면에서 되찾는다</td></tr>
|
||||
<tr><td>말뚝</td><td>5×5=25 가 아니라 <b>22본</b> — 둘레 16 + 내부 3등분점 6</td></tr>
|
||||
<tr><td>받침</td><td>형상 × 표 × 다른 도면 <b>세 겹 검산</b>, 6/6 일치</td></tr>
|
||||
<tr><td>결과</td><td><b>75 파트 · 657.0569 m³ · 차이 0.0000 · 열린 변 0</b></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════ 4. 사고 대응 ══════════ -->
|
||||
<section class="panel" id="p4" role="tabpanel">
|
||||
<p class="lede">녹화 중 걸릴 만한 것만. 전부 실제로 겪었다.</p>
|
||||
<div class="tw">
|
||||
<table>
|
||||
<tr><th>증상</th><th>원인</th><th>대응</th></tr>
|
||||
<tr><td><code>run_egm</code> 이 「명령이 끝나지 않는다」</td>
|
||||
<td>이전 명령이 물려 있다. <code>egm status</code> 의 <code>command</code> 가 남는다</td>
|
||||
<td><code>egm "Esc"</code> — 접두 <code>~</code> <b>없이</b>. 그리고 재실행</td></tr>
|
||||
<tr><td>씬에 이전 모델이 남음</td><td>—</td>
|
||||
<td><code>egm "Esc"</code> → <code>"SelAll"</code> → <code>"Delete"</code> → <code>"Esc"</code></td></tr>
|
||||
<tr><td><code>modelCount</code> 가 75 가 아님</td>
|
||||
<td>boolean 이 인자를 흘렸다</td>
|
||||
<td>씬 비우고 재실행. 반복되면 촬영 멈추고 확인</td></tr>
|
||||
<tr><td>명령이 조용히 무시됨</td><td>뷰어 모드</td>
|
||||
<td>0단계로 돌아간다. <b>연결 정상 ≠ 모델링 가능</b></td></tr>
|
||||
<tr><td><code>Access to the path is denied</code></td>
|
||||
<td>모델러가 다른 권한으로 떠 있어 파이프에 못 붙는다</td>
|
||||
<td>모델러를 종료하고
|
||||
<code>C:\Program Files\Baron\EG-BIM Modeler\EG-BIM_Modeler.exe</code> 로 다시 띄운다</td></tr>
|
||||
<tr><td>파이프가 죽음 (창은 멀쩡)</td><td>씬 초기화를 여러 번 반복했다</td>
|
||||
<td>재시작 외에 방법 없다. 초기화는 갱신당 1회</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="note">
|
||||
<b><code>--reset</code> 은 붙이지 않는다</b>
|
||||
지난번 그것 때문에 <code>Select</code> 가 물렸다. 씬은 촬영 전에 미리 비워 둔다.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ══════════ 5. 업로드 ══════════ -->
|
||||
<section class="panel" id="p5" role="tabpanel">
|
||||
<h2>제목 후보</h2>
|
||||
<div class="tw">
|
||||
<table>
|
||||
<tr><th>안</th><th>제목</th></tr>
|
||||
<tr><td>A</td><td>2D 도면 한 장으로 교각 3D 모델 자동 생성 — 부재 75개, 오차 0.0000</td></tr>
|
||||
<tr><td>B</td><td>토목 도면을 BIM 으로 바꾸는 법 : 손으로 안 그리고 IFC 까지</td></tr>
|
||||
<tr><td>C</td><td>도면이 말하는 네 가지 방식 — 윤곽 · 원 · 블록 · 표 | 2D→3D 전환설계</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2>설명란</h2>
|
||||
<pre>교각 일반도(DWG) 한 장을 읽어 3D 솔리드와 IFC 까지 만드는 과정입니다.
|
||||
|
||||
부재 75개 · 콘크리트 657.06 m³ · 모델러 실측 대비 오차 0.0000 · 열린 변 0
|
||||
|
||||
00:00 결과 먼저
|
||||
00:14 도면 — 한 파일에 도형 17벌
|
||||
00:38 뷰 가르기
|
||||
00:50 끊김 진단 — 레이어 오분류 vs 선 누락
|
||||
01:02 도면이 말하는 네 방식 : 윤곽 · 원 · 블록 · 표
|
||||
01:51 도면이 파라미터가 된다
|
||||
02:16 3D 툴 없이 부피부터
|
||||
02:32 모델러에 교각이 선다
|
||||
03:54 의도 vs 결과 — 부재마다 대조
|
||||
04:20 IFC 로 넘긴다
|
||||
05:04 그림으로도 본다 · 정리
|
||||
|
||||
다룬 것
|
||||
· 도곽 블록으로 시트 경계를 계산한다 (한 파일에 여러 벌이 쌓여 있다)
|
||||
· 파단선 — 그려진 길이가 실제가 아니다. 생략량을 도면에서 되찾는 법
|
||||
· 말뚝은 폐곡선이 아니라 INSERT 블록. 배율이 곧 치수다
|
||||
· 받침 적층·절대표고는 형상에 없고 표에만 있다
|
||||
· IFC 는 메시가 아니라 해석 솔리드로. 원기둥은 진짜 원으로</pre>
|
||||
|
||||
<h2>태그</h2>
|
||||
<pre>토목엔지니어, BIM, 3D전환설계, 토목BIM, IFC, 교량, 교각, 도면자동화,
|
||||
DWG, 캐드, 파라메트릭모델링, 스마트건설, civil engineering, BIM automation</pre>
|
||||
|
||||
<h2>썸네일</h2>
|
||||
<p>왼쪽 <b>흑백 2D 도면</b>(01.mp4 한 프레임), 오른쪽 <b>색 입은 3D 교각</b>(07.mp4 마지막 프레임).
|
||||
가운데 화살표. 카피는 숫자 하나만 — <b>「오차 0.0000」</b> 또는 <b>「부재 75개, 자동」</b>.</p>
|
||||
|
||||
<div class="note">
|
||||
<b>다음 편 훅</b>
|
||||
마지막 컷에서 <b>꺾인 교각(P11)</b> 을 예고했다. 꺾임각 6.30° —
|
||||
코핑 축선이 중간에 꺾여 P9 방식이 그대로는 안 통한다. 그게 다음 편 주제다.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const tabs = document.querySelectorAll('.tabs button');
|
||||
tabs.forEach(b => b.addEventListener('click', () => {
|
||||
tabs.forEach(x => x.setAttribute('aria-selected', String(x === b)));
|
||||
document.querySelectorAll('.panel').forEach(p => p.classList.toggle('on', p.id === b.dataset.p));
|
||||
window.scrollTo({ top: 0, behavior: 'instant' });
|
||||
}));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
# 프로젝트 목표(주제)
|
||||
|
||||
2D기반의 Dxf도면을 분석하여 3D모델로 구현하고 구현된 모델을 웹상에서 검토할 수 있게 하고 싶다.
|
||||
|
||||
## 절차
|
||||
|
||||
0. 절차는 반드시 지킨다. 각 단계마다 작업전 작업내용을 리마인드를 시켜주고 다음단계로의 진행여부를 확인 받아야한다.
|
||||
|
||||
1. {주제}를 만들기를 원한다. 일단 심도 있게 웹 조사를 하고 어떤 방법으로 할지 하나씩 agent를 만드는 작업을 해볼 수 있을까?무엇을 할지 메모리에 저장해라.
|
||||
|
||||
2. 우리가 이러한 {주제}를 기술들을 구현하는 과정에서 고려해야 할 점들은 무엇일까요?
|
||||
|
||||
3. 위를 구현하기 위한 프로젝트를 셋업 하려고 합니다. 지금 셋업을 하지 말고 이러한{주제}을 위한 CLAUDE.md 작성해주세요.
|
||||
|
||||
4. 일을 여러 에이전트들이 나눠서 할 때, 어디가지 진행되고 무슨 일을 해야 하는지에 대한 내용들을 각각 PROGRESS.md 와 PLAN.md 에서 관리하도록 합시다. 그리고 새로 시작할 때 두 파일을 읽어서 내가 무슨 일을 해야 하는지 에이전트들이 알 수 있게 합시다. 이렇게 CLAUDE.md 를 업데이트 합시다.
|
||||
|
||||
5. 그러면 이제 이런 일들을 할 때 필요한 에이전트, 커맨드, 스킬, Hook 들이 무엇이 있을지 고민해 보고, 아이디어들을 알려주세요.
|
||||
|
||||
6. 그러면, Claude code의 agent, command, skill, hook 구조를 조사한 후, 그에 따라서 정확한 포맷을 지켜서.cluade 하위에 위에서 제안한 것들을 만들어 주세요.
|
||||
단, 추가 하네스 == 이제 “ [https://www.anthropic.com/engineering/harness-design-long-running-apps](https://www.anthropic.com/engineering/harness-design-long-running-apps) ” 이 사이트를 읽으세요.
|
||||
|
||||
7. 이 방향으로 CLAUDE.md / 에이전트 구조를 보강해 주세요.
|
||||
|
||||
8. 지금까지 작성한 계획으로 workflow 를 구현하세요. 다이나믹 agent를 사용하여 병렬화가 가능한 부분은 병렬로 해주세요. 병렬로 하더라도 안정된 구현을 해주기 원합니다.
|
||||
|
||||
9. 어떤 모델을 사용할 것인지 확인이 필요합니다.
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user