toolx blog

2D 도면 세트 → 파라메트릭 3D 모델
일반 방법론

평면도 · 입면도 · 좌/우측면도 · 종단면 · 횡단면 · 수평단면을 한 좌표계로 묶어
솔리드와 설계 파라미터를 만드는 절차와 판단 규칙.

버전 v0.2 — 교량 삽도 실증 반영 작성 2026-08-07 근거 전력구·맨홀 일반도 4매 (평면 1 + 단면 10) 전 구간 관통
+ 교량 설계지침 삽도 7장 (1장 관통 · 6장 어디서 왜 막혔는지 기록)
다음 표기 치수가 있는 교량 일반도 — 11.1 기준 체인과 sweep이 아직 미검증이다
이 문서를 읽는 법 각 주장에 신뢰 등급을 붙였다. 검증 실제 도면으로 끝까지 돌려봤다 · 부분 원리는 확인했으나 표본이 하나다 · 가설 아직 안 해봤다 — 다음 도면에서 확인할 것.
기존 문서와의 관계: docs/2d-3d-process.md는 이 저장소의 명령 절차, docs/2d-3d-conversion.md사례별 교훈, 이 문서는 그 둘에서 도면 고유값을 걷어낸 방법론이다.

0한 장 요약

도면 세트를 3D로 옮기는 일은 형상 작업이 아니라 좌표계 통일 작업이다. 뷰마다 따로 노는 로컬 좌표를 하나의 프로젝트 좌표로 묶고 나면, 나머지는 기계가 한다.

도면 세트 ─┬─ 기준점(datum)  ─→ 전 뷰 공통 Z (또는 X·Y)
           ├─ 뷰 분리        ─→ 뷰마다 로컬 (u,v)
           └─ 뷰 앵커        ─→ 프로젝트 (X,Y,Z)
                                    │
                          프로파일(폐곡선) · 원 · 개구부
                                    │
                    fit ─→ params.json ─→ build ─→ IR ─→ 백엔드(3D/IFC)
                              ↑ 사람은 여기만 만진다      ↓
                                                  부피·물량·규칙 검사

변하지 않는 규칙 12개

  1. 게이트에 넣기 전에 「이 도면이 솔리드 대상인가」를 먼저 판정한다. 표기 치수를 숫자형/기호형으로 세고, 구조 윤곽이 닫히는지 본다. 기호 치수뿐이거나(L·β·θ·VAR) 윤곽이 안 닫히는 도면은 어느 게이트에서도 안 통과한다 — 교량 삽도 7장 중 6장이 그랬다. 이 판정은 몇 초면 된다.
  2. 단위와 축척을 도면에서 되찾고 두 치수로 교차검증한다. DWG 모델단위는 도면군마다 다르고(1m vs 1mm), 도형마다 배율이 또 다를 수 있다(5.805배). 상수로 두면 모든 값이 조용히 배수만큼 틀린다 — 폐곡선도 부피도 정상으로 보인다.
  3. 기준점을 먼저 확정한다. 형상보다 앞이다. 기준점 없이 뽑은 형상은 정합 단계에서 전부 다시 한다. 단, 기준선이 아예 없는 도면이 실재한다 — 그때는 검출을 끄고 뷰별 v0로 간다. 아무 선이나 자동으로 고르지 않는다.
  4. 기준은 텍스트가 아니라 선에서 잡고, 도면 치수 2개 이상으로 교차검증한다. 라벨은 후보를 좁히는 힌트일 뿐이다.
  5. 뷰 하나는 [좌표평면 · 반전 · 원점 · 축척 · 용도] 다섯 속성으로 서술된다. 도면 종류는 9가지지만 좌표평면은 XY·XZ·YZ 셋뿐 — 나머지 차이는 보는 방향(좌우 반전)이다. 종류마다 코드를 늘리지 마라.
  6. 입면도·측면도로 솔리드를 만들지 않는다. 잘린 면이 아니라 투영 윤곽이라 깊이가 없다. 검증과 위치에만 쓴다.
  7. 구간 배정표는 종방향 뷰에만 있다. 횡단면은 "그 지점의 모습"일 뿐 어디까지 유효한지 말해주지 않는다.
  8. 뽑아낸 도형 목록에서 무엇을 쓸지 고를 때, 목록 순서가 아니라 치수로 지정한다. "2,700×2,750 인 것"처럼. 순서로 집으면 도면이 조금 바뀔 때 아무 말 없이 다른 도형을 집는다.
  9. 손으로 적은 수를 넣지 않는다. 도면과의 끈이 없는 값은 도면이 바뀌어도 안 바뀌고, 파라미터로 올릴 자격도 없다.
  10. 속을 파낼 때는 빈 곳 없이 꽉 찬 덩어리를 먼저 만들고, 거기서 뺀다. 외곽선이 오목하면 파인 자리에 애초에 재료가 없어 벽을 만들 수 없다. 빼는 솔리드는 한 번에 하나씩, 대상보다 조금 크게.
  11. 의도와 결과를 따로 잰다. IR을 직접 평가한 부피와 백엔드 결과 부피를 대조해야 "우리가 틀렸나 툴이 흘렸나"가 갈린다.
  12. 조용히 틀리느니 예외를 던진다. 못 찾거나 여럿이면 멈춘다. 자동 선택은 나중에 몇 시간짜리 추적으로 돌아온다.

1범위와 계층

1.1 입력과 출력

항목내용상태
입력 형식DWG (acadrust wasm, read-only). 한 모델스페이스에 여러 뷰가 나열된 형태검증 R2018
입력 형식 — DXF파서가 DWG 전용이다. DXF는 ① 변환(ODA File Converter 등) 후 투입 ② DXF 리더 추가 중 하나. 엔티티 모델이 같으므로 하류는 그대로가설
읽는 엔티티LINE · LWPOLYLINE → 선분, CIRCLE → 원(따로), TEXT/MTEXT → 표제·주기·치수검증
버리는 엔티티ARC · ELLIPSE · SPLINE · 해치 · 블록 내부 로컬 좌표부분 비중은 쟀다 — 교량 도면 7장에서 ARC 0~17%(거더배치 249/1,433). 원호가 형상인 도면은 아직 미검증
모델단위DWG 1단위가 몇 mm인가. 도면군마다 다르다 — 맨홀군 1m, 교량 삽도군 1mm. 게다가 도형마다 배율이 또 다를 수 있다(5.805배 사례)검증 cfg.unitMm · viewBoxes[뷰].unitMm
치수의 성격표기 치수가 숫자인가 기호(L·β·θ·VAR)인가. 기호뿐이면 방법론 전체가 기대는 「도면 치수와 대조」가 성립하지 않는다검증 세어서 판정한다 (11.0)
출력솔리드 파트(이름·재질 부착) · 설계 파라미터 · 재질별 물량 · 부피 기준선검증
출력 — IFCIR의 extrudeIfcExtrudedAreaSolid, union/differenceIfcBooleanResult와 1:1. 매핑 초안은 있고 emit은 미구현가설

1.2 계층 — 무엇이 어디에 있어야 하는가

이 경계가 방법론의 뼈대다. 무너지면 두 번째 도면에서 파이프라인이 아니라 복사본이 생긴다.

계층아는 것절대 몰라야 하는 것
도면 설정 drawings/*.mjs레이어명 · 뷰 제목 · 임계값 · 앵커 · 기준점 검증항목 · 조립 판단
코어 core/*파싱 · 뷰 분리 · 좌표 변환 · 폐곡선 추출 · 개구 기호 · 자기교차도면 고유값 일체. '-전력구' 같은 문자열이 들어가면 설계가 틀린 것
파라미터 params.mjs · fit.mjs · rules.mjs스키마 · 식 · 검증 · 규칙도면도 3D도 모른다
이 경계는 두 곳에서 이미 새 있었다(교량 도면에서 드러남).
core/datum.mjsUNIT_MM = 1000도면 고유값이 코어에 상수로 있었다. 같은 파일의 라벨 대역(±3)·뷰 분리 문턱(2)도 「1단위=1m」를 전제한 길이였다.
rules.mjs는 "도면도 3D도 모른다"고 적혀 있었지만 실제로는 챔퍼_시작X · 샤프트 · 맨홀_벽두께처럼 첫 도면의 파라미터 이름에 묶여 있었다. 두 번째 도면에서 undefined 비교가 전부 위상 위반으로 떨어져 build가 죽었다.
교훈: 경계 위반은 두 번째 도면을 넣기 전에는 안 보인다. 문서에 "안 들어간다"고 쓰는 것으로는 안 지켜진다.
IR ir.mjs"이 프로파일을 이 축으로 밀고 저걸 뺀다"백엔드 사정 · 도면 사정
백엔드 emit/*모델러 명령 순서 · 비동기 대기 · boolean 이항 접기도면 사정
IR을 중간에 둔 이유 도면 해석과 3D 툴을 직접 붙이면 툴을 바꿀 때 전부 다시 짠다. IR은 도구 중립이라 3D 툴 없이도 검증·diff·부피 평가가 된다. 실제로 이 성질 하나가 "모델러가 흘리는가"를 판정하는 유일한 수단이 됐다(7장).

2좌표계 · 원점 · datum

셋을 구분한다 — datum은 프로젝트 원점이 아니다 datum은 Z 축 하나만 잡는 장치다. 3축 원점 전체가 아니다. Z는 datum이, X·Y는 뷰 앵커가 준다. 갈라놓은 이유는 도면 관행 때문이다 — 토목 도면은 모든 단면을 같은 표고선에 맞춰 배치하므로 Z는 전 뷰 공통으로 한 번에 잡히지만, 가로축 원점은 뷰마다 제각각이라 뷰별로 잡아야 한다.
개념무엇을 정하는가이 저장소Revit 대응
프로젝트 원점3축 원점 전체. 선언한다frame.originProject Base Point
datum그중 Z=0 평면 하나. 도면에서 검출한다(점이 아니라 )datum.levelLabel + checksLevel (기준 레벨)
앵커뷰별 가로·세로축 원점 (X·Y)anchors.u0 / v0없음 — Revit은 뷰가 원점을 공유한다
도면 월드 좌표측량 좌표. 빼고 버린다DWG x,y (예 y=483623.477)Survey Point / 공유 좌표

선형 구조물이면 X 원점을 측점에 맞추는 것이 유리하다(측점 0k000의 좌표를 프로젝트 원점으로). 그건 datum이 아니라 앵커 u0 로 준다 — 그 측점 선의 뷰 좌표를 u0에 넣고, frame.origin에 "측점 0k000"이라고 적어 근거를 남긴다. 대상 도면은 측점이 아니라 구조물 최좌단을 X=0으로 잡았다(u0: 1000). 부분 측점 기반 원점은 미검증 — 곡선 선형·구배와 함께 12장 항목이다. 교량은 11장을 볼 것.

2.1 프로젝트 좌표계를 먼저 선언한다

축 셋과 원점을 문장으로 적고 시작한다. 이걸 안 적으면 뷰마다 다른 해석이 섞인다.

frame: {
  x: '길이방향 (기점 → 종점)',
  y: '폭방향 (중심선이 0, 평면도 위쪽이 +)',
  z: '표고 (기준고가 0, 아래로 음수)',
  origin: '구조물 최좌단 × 중심선 × 기준고',
}
구조물 종류XYZ 원점 후보
선형 토목(전력구·암거·터널)측점 방향중심선 기준 폭도로 계획고 · 토공 계획고 · GL · EL 기준선
점형 토목(맨홀·수조·기초)도면 가로도면 세로GL · 상단 슬래브 상면
건축그리드 X 통심선그리드 Y 통심선1FL · 기준층 FL

단위는 내부 mm 정수. 백엔드에 넘기기 직전에만 m로 나눈다. mm 정수 반올림이 DWG의 부동소수 노이즈(-500.00000000001455)를 자동으로 흡수한다. 반올림을 뒤로 미루면 boolean 단계에서 터진다. 검증

2.2 datum(Z=0 기준선) 검출 — 4단계

  1. 라벨이 한 무리인지 먼저 본다. 신규 라벨 y를 정렬해 2m 이상 벌어진 곳에서 끊는다. 무리가 둘 이상이면 공통 기준선이 없는 도면이므로 여기서 예외를 던진다. 아래 2단계의 숨은 전제가 바로 이것이다.
  2. 후보 수집. 여러 뷰에 반복해서 나타나는 수평선(또는 수직 그리드선)을 모은다. 출현 횟수는 잡음 문턱으로만 쓴다.
  3. 라벨 근접으로 확정. 후보가 둘 이상이면(계획고는 보통 도로/토공 두 줄이다) 라벨 바로 아래·옆의 선을 고른다. 라벨은 자기 선을 가리킨다.
  4. 선에서 값을 읽는다. 텍스트 삽입점이 아니다. 실제로 713mm 틀렸다.
  5. 도면 치수 2개 이상과 대조. 하나만 두면 우연히 맞을 수 있다. 하나라도 어긋나면 datum이 틀린 것이므로 다음 단계로 가지 않는다.
왜 1단계가 추가됐나 — 검출기가 예외 없이 틀린 답을 냈다 검증 3단계는 라벨 y를 평균내고 「그 평균 바로 아래 선」을 고른다. 숨은 전제는 「라벨 하나가 선 하나를 가리킨다」, 즉 라벨이 한 곳에 모여 있다는 것이다. 전력구 도면은 11개 뷰가 같은 계획고 선을 공유해 그 전제가 참이었고, 그래서 안 보였다.
유형 삽도는 같은 라벨을 도형마다 반복한다. 횡단경사 삽도에서 교량 계획고·토공 계획고 라벨 10개가 y 27,533~81,177에 흩어져 평균 56,453은 어느 도형에도 속하지 않는 값이 됐다. 결과:
교량 계획고 → y=54,885.8
토공 계획고 → y=54,885.8      ← 정의상 다른 표고인데 같은 답
라벨별 국소 선 → 9개가 전부 다르다. 54,885.8 은 그중 어느 것도 아니다
예외가 아니라 그럴듯한 숫자가 나왔다. 규칙 12(조용히 틀리느니 예외)는 검출기 자신에게도 적용된다 — 전제가 깨졌는지 스스로 검사하지 않으면 실패가 답의 모습으로 나온다.
datum: {
  levelLabel: /도로\s*계획고/,          // 후보를 좁히는 힌트
  checks: [                             // 최소 2개. 도면에 적힌 치수를 그대로
    ['B-B 구체 상단', (v) => v['단 면 B-B']?.layerZ['-전력구']?.[1], -4907],
    ['B-B 기초 하단', (v) => v['단 면 B-B']?.layerZ['!-기초']?.[0],  -7757],
  ],
}
공통 datum이 있으면 무조건 그것부터 찾는다 검증 단면도를 배치할 때 표고선을 맞춰 그리는 관행이 그대로 3D 정합 데이터가 된다. 대상 도면은 11개 뷰가 같은 y에 계획고 선을 공유해 뷰별 Z 오프셋 계산이 통째로 사라졌다. 건축이면 FL/층레벨, 선형이면 EL 기준선이 같은 역할을 한다.
먼저 확인할 것: 뷰별로 검출한 기준선 y가 전부 같은 값인가. 다르면 뷰마다 Z 오프셋이 필요하고, 방법론 비용이 한 단계 올라간다.
공통 datum이 없는 도면이 실재한다 검증 교량 삽도 7장 전부가 그랬다. 지반 레이어는 7장 중 1장(CS-GRND)뿐이고 계획고 라벨은 1장(10개)뿐이다. 나머지는 표고선 자체가 안 그려져 있고, 도형마다 제 바닥이 서로 다른 y에 앉는다.
당시 코드는 이 경우 예외로 죽었다표고 기준선을 찾지 못했다. 그 자리에서 아무 수평선이나 자동으로 고르는 것은 틀린 대응이다(조용히 어긋난다).
대응(구현됨): datum: {mode:'none'} 으로 검출을 끄고 DWG y를 그대로 두되, 표고는 뷰마다 anchors[뷰].v0 로 준다. 위 후보 ①이 그대로 맞았다 — 앵커 규칙을 세로축으로 확장한 것 이상이 필요하지 않았다.
중앙분리대 삽도에서 두 단면의 기준면 y가 실제로 달랐다(포장면 48,812.1 vs 바닥판면 49,096.5). 그 차이가 곧 「토공용은 포장에 49mm 묻히고 교량용은 바닥판 위에 얹힌다」라는 형상 정보였다.
datum이 없으면 G2의 교차검증도 같이 사라진다 부분 위 4단계의 마지막 항목(도면 치수 2개 이상과 대조)은 datum이 있을 때의 절차다. datum을 끄면 대조할 것이 없어져 datum.checks가 빈 배열이 되고, G2가 「통과」가 아니라 「해당 없음」이 된다. 방법론은 이 구멍을 안 다뤘다.
대신 검증을 G3로 미룬다 — 폐곡선의 폭·높이가 도면 표기 치수와 맞는지로 옮긴다. 중앙분리대에서는 단면 폐곡선이 585 × 1,270으로 나온 것이 곧 기준·축척·앵커를 한꺼번에 검증한 것이었다. 다만 이건 늦은 검증이다 — 틀렸을 때 원인 후보가 기준·축척·앵커 셋으로 늘어난다.

3뷰의 일반 모델

도면 한 장을 3D 공간에 스티커처럼 붙인다고 보면 된다. 붙이려면 네 가지를 알아야 한다.

속성묻는 것
plane어느 에 붙이나평면도 → XY면, 정면도 → XZ면, 측면도 → YZ면
flip뒤집어 붙였나배면도는 정면도를 좌우 뒤집은 것
anchor어디에 맞춰 붙이나이 그림의 가로 1,000 자리가 X=0
role붙여서 뭘 하나형상을 만든다 / 검증만 한다
핵심 일반화 — 도면 종류는 9가지, 좌표평면은 3가지 plane평면도가 아니라 좌표평면이다(용어가 겹치니 주의). 그림이 놓이는 면은 셋뿐이다.
XY면 ← 평면도 · 저면도 · 수평단면
XZ면 ← 정면도 · 배면도 · 종단면
YZ면 ← 좌측면도 · 우측면도 · 횡단면
같은 면에 놓인 것들끼리의 차이는 보는 방향뿐이고 그건 좌우 반전이다. 정면도와 배면도는 둘 다 XZ면에 놓이고 X 방향만 반대다. 도면 종류가 9개여도 처리 코드는 3개면 된다 — 종류마다 코드를 늘리지 마라.
현재 코드의 plan/long/cross/horizontal이라는 kind 이름은 이 사실을 가린다.

3.1 뷰 → 평면 대응표

보는 방향평면도면 (u,v) →반전절단면?상태
평면도−Z (위에서)XY(X, Y)아니오검증
저면도+ZXY(X, −Y)flipV아니오가설
수평 단면−ZXY(Y, X) swapUV도면마다검증
정면도+YXZ(X, Z)아니오가설
배면도−YXZ(−X, Z)flip아니오가설
종단면±YXZ(X, Z)절단 방향검증
좌측면도+XYZ(Y, Z)투상법아니오가설
우측면도−XYZ(−Y, Z)flip아니오가설
횡단면±XYZ(Y, Z)절단 방향검증

3.2 뷰 역할 — 무엇을 주는 뷰인가

평면만 정해서는 부족하다. 같은 XZ 평면이라도 종단면과 정면도가 하는 일이 전혀 다르다. 역할을 배정하지 않으면 입면도로 압출하는 사고가 난다.

역할주는 것전형적인 뷰쓰는 법
생성 generator재료 영역 폐곡선 → 그대로 압출·로프트횡단면 · 종단면 · 수평단면loop(뷰, 폭, 높이).ring
배정 assigner어느 구간에 어느 단면이 유효한가종단면 (선형은 필수)수평선을 Z 내림차순 × X 범위로 늘어놓는다
위치 locator개구부·관통·부속물의 좌표평면도 · 수평단면 · 입면도opening() · circles() · rect()+expect()
검증 validator만든 3D가 맞는지 대조할 윤곽·치수입면도 · 좌/우측면도 · 상세도3D를 그 방향으로 정투영해 윤곽 비교
입면도·측면도로 솔리드를 만들지 마라 부분 단면도는 잘린 면만 그리지만 입면도는 보이는 모든 것을 그린다. 그래서 입면도의 폐곡선은 재료 영역이 아니라 여러 깊이가 겹친 투영 윤곽이다. 압출하면 깊이가 거짓이 된다. 실제 압출은 평면도(footprint) + 단면도(높이)로 하고, 입면도는 ① 외곽 검증 ② 개구부의 XZ/YZ 위치 ③ 마감선·레벨선 확인에만 쓴다.
판별법: 그 뷰에 해치(절단면 표시)가 있으면 단면, 없으면 투영이다. 제목만 믿지 말 것.

3.3 앵커와 flip 판정 절차 검증

뷰 안의 좌표는 뷰 좌단이 0인 u기준고가 0인 v다. 프로젝트 축으로 옮기려면 뷰마다 "어느 u가 프로젝트 0인가"를 정해야 한다. 투상법(1각/3각)을 가정하지 마라 — 도면마다 다르고, 틀려도 치수만 보는 동안은 안 걸린다.

  1. 뷰 폭·높이를 도면 표기 치수와 대조. 여기가 안 맞으면 뷰 분리부터 틀린 것이다.
  2. 앵커를 지어내지 말고 유도한다. 예: 뷰 세로 범위 −11,678~−1,478이 전폭 10,200이고 아래 끝이 Y=−1,900이면 v0 = -11,678 + 1,900 = -9,778.
  3. 비대칭 특징 하나로 flip을 판정한다. 중심선 대칭 형상만 보면 뒤집힘이 안 드러난다. 샤프트·개구부·노치처럼 한쪽에만 있는 것을 고른다.
  4. 다른 뷰에서 이미 확정한 좌표와 교차검증. 최소 2개. 세 개면 확정이다.
// 실제로 이렇게 확정했다 — 셋이 동시에 맞으면 앵커는 틀릴 수 없다
샤프트 사각 1,300×1,300   v -10,428..-9,128 → Y -650..+650     중심선 대칭 ✓
Ø900 보어 2개             v -9,778          → Y 0               ✓
맨홀 내부 2,000×7,200     v -11,278..-4,078 → Y -1,500..5,700   ✓
치수만 보는 동안은 틀린 앵커도 안 걸린다 검증 평면도에서 expect(뷰, 폭, 높이)로 치수만 확인하는 동안은 v0가 없어도 아무 문제가 없었다. 원(CIRCLE) 좌표를 쓰는 순간 보어가 Y=−9,778로 튀어나왔다. 좌표를 쓰기 시작하면 숨어 있던 앵커가 드러난다. 수평 단면에서 이미 겪은 문제를 평면도에서 반복했다 — "세로축이 표고겠거니" 하고 넘어갔기 때문이다.

축을 뒤집거나 맞바꾸면 감김 방향이 반대가 된다. 뒤집기 횟수가 홀수면 꼭짓점 순서를 되돌려 면적을 양수로 유지한다. 코어가 자동으로 하지만, 새 평면을 추가할 때 잊기 쉬운 자리다.

3.4 뷰 분리 알고리즘 부분

여러 뷰가 한 모델스페이스에 나열돼 있으면 먼저 갈라야 한다. 간격 임계값 하나로는 절대 안 된다 — 넓게 잡으면 이웃이 딸려오고 좁게 잡으면 한 뷰가 쪼개진다. 둘 다 실제로 터졌다.

배지를 검증 → 부분으로 내린다 — 이 알고리즘은 전제가 둘 있다 아래 절차는 (가) 뷰 사이에 간격이 존재하고 (나) 뷰마다 유일한 제목이 있다를 전제한다. 전력구 도면 4매에서는 둘 다 참이었다. 교량 삽도 7장에서는 둘 다 거짓이었다.
· (가) 실패 — 상세 확대 테두리 상자가 상세행과 단면행을 세로로 잇는다. 임계값을 10mm까지 좁혀도 조각이 1개였다. 구조선과 같은 레이어·같은 색이라 걸러낼 수도 없다.
· (나) 실패 — 표제 중복률 47~84%. 단면A가 4벌, 교량 시·종점이 6벌. 교량폭원은 뷰 제목이 아예 없다(표제는 시트명 하나, 나머지는 A·B·L of Road).
대응(구현됨): cfg.viewBoxes — 뷰마다 {box:[x0,y0,x1,y1], kind}를 설정에 적는다. 선분 단위로 나눈다(조각 단위로 나누면 뷰를 잇는 다리 조각이 통째로 한쪽에 붙는다). 양 끝이 다 들어오는 선만 취해 경계를 넘나드는 선을 자동으로 버리고, 상자가 겹치면 예외를 던진다.

제목이 있고 간격이 있는 도면에서는 아래가 여전히 최선이다 — 좌표를 설정에 적지 않아도 되기 때문이다.

1. 구조 레이어 기하만 모은다 (넉넉한 struct 정규식)
2. x ↔ y 를 번갈아 가며 더 이상 갈라지지 않을 때까지 잘게 쪼갠다 (임계 0.2m)
   ↳ y로 나눈 뒤에야 드러나는 x 간격이 있다. 한 번씩만 하면 부족하다
3. 조각마다 "바로 위에 있는 표제"를 찾아 귀속시킨다
4. 같은 표제를 가진 조각끼리 합치면 그게 뷰다
장치튜닝 값
표제 최소 글자 높이부재 방향 라벨(h=0.30)이 표제로 잡히면 뷰를 훔쳐간다minHeight — 도면의 글자 높이 분포를 먼저 세어본다
표제 세로 여유크게 잡으면 옆 표제가 뷰를 통째로 가져간다 (0.6m→0.2m로 해결)ySlack
상세도·재료표도 표제 후보에 넣기자기 조각을 가져가므로 뷰로 새어들지 않는다. 뷰가 아닌 표제에 귀속된 조각은 버린다
시트 영역 밖 버리기유령 기하와 블록 로컬 좌표가 bbox·축척을 깨뜨린다sheet: {x0,x1,y0,y1}
다중 시트 가설 · 축척 혼재 검증 현재 sheet는 사각형 하나다. 도면이 여러 장으로 나뉘어 각각 다른 좌표대에 있으면 배열로 확장하고 시트별 오프셋을 둬야 한다. 대상 도면은 4매가 한 좌표대에 있어 필요 없었고, 교량 삽도도 도형이 한 덩어리라 필요 없었다(빈 시트 테두리가 옆에 하나 더 있었지만 유령이다).
축척 혼재는 실재한다. 같은 삽도 묶음 안에서 교량폭원은 1:1인데 중앙분리대 방호벽 단면은 5.805배였다. unitMm을 뷰 스펙에 두는 것으로 해결했다.
DWG를 뷰별로 미리 쪼개지 마라 검증 "뷰마다 별도 파일로 나누면 편하지 않나"는 손해다. 가장 큰 이득이었던 "모든 단면이 같은 표고선에 맞춰 배치돼 있다"는 한 모델스페이스에 함께 있어야만 성립한다. 분리하면 3D 정합의 절반을 버린다. 절단기호 ↔ 단면 매핑도 끊긴다.

4절차 — 11개 게이트

3D부터 세우면 어디가 틀렸는지 알 수 없다. 아래 순서를 건너뛰지 않는다. 각 게이트는 통과 기준이 있고, 실패하면 그 자리에서 멈춘다.

게이트통과 기준실패 시 도구대표 함정
G0 백엔드 준비 모델링 명령이 등록돼 있는가 (연결 여부가 아니다) egm guide 개수 — 39면 뷰어 모드 파이프는 살아 있고 status도 정상인데 생성만 조용히 실패
G1 파싱·시트 엔티티 수가 나오고, 시트 밖 좌표가 걸러졌는가 inspect — 레이어 무관 전수 유령 기하 · INSERT 블록 로컬 좌표 · 캐시 파일명 슬러그 충돌
G1.5 도면 적격 신규 표기 치수가 숫자인가(기호 L·β·θ·VAR 비율) · 모델단위·축척이 확정되는가 · 구조 윤곽이 닫히는가 치수 텍스트 분류 계수 · DIMENSION.actualMeasurement ↔ 치수 글자 대조 · gaps의 「선 없음」 비율 기호 치수뿐이라 대조할 상대가 없다 · 단위가 1000배 · 구성 도해라 애초에 안 닫힌다
G2 기준점 도면 치수 2개 이상과 일치. 기준선이 없는 도면이면 「해당 없음」으로 명시하고 검증을 G5로 미룬다 datum.checks 확장 · datum.mode:'none' + 뷰별 v0 텍스트 위치로 잡음(713mm) · 계획고 후보 둘(420mm) · 기준선이 아예 없는데 아무거나 자동 선택
G3 뷰 분리 뷰 폭·높이가 도면 표기와 일치. 서로 다른 뷰의 심도가 같게 나오는가 임계값·minHeight 조정 → 안 되면 viewBoxes(명시 영역) 이웃 뷰 혼입(폭 부풀음) · 뷰 잘림(하단 누락) · 제목 없음/중복 · 테두리 상자가 뷰를 이어 조각이 1개
G4 평면·앵커·flip 비대칭 특징 좌표가 다른 뷰와 일치 (2개 이상). 뷰별 축척이 다르면 여기서 확정한다 — 표기 치수 2개로 역산 3.3 절차 · viewBoxes[뷰].unitMm 수평 단면의 세로축을 Z로 봄 · 평면도 v0 누락 · 도형마다 축척이 다름
G5 프로파일 품질 자기교차 0. 꼭짓점 수가 예상과 맞는가. 끊김의 원인이 분류됐는가. 폐곡선의 폭·높이가 도면 표기와 맞는가 — G2를 건너뛴 도면은 여기가 유일한 검증점이다 gaps · --loops · report(그림) 개구 기호가 링 오염 · 가구(케이블랙) 혼입 · 레이어 오분류 · 끊김 0인데 폐곡선 0(겹치는 동일선상 선분) · 윤곽이 진짜로 안 닫힘
G6 조립(IR) 참조 무결성 · 소모 파트 keep 플래그 · loft 단면 꼭짓점 수 일치 validateIR loft 위상 불일치 · 중간 파트가 최종에 남음
G7 파라미터화 등급 분포가 납득되는가. 위상 규칙 위반 0 fitparams.json · rules 도면과 끈 없는 값을 파라미터로 올림
G8 좌표 검산 --dry 출력의 좌표가 예상과 같은가 명령 목록 육안 검산 압출 방향 미지정 · 단위 환산 누락
G9 생성·부피 파트 수 == modelCount. IR 의도 부피 == 실측 부피. 기준선 회귀 통과 measure --ir · --primitives boolean이 인자를 흘림 · 면으로만 맞닿은 union · 커터가 자기 부피보다 많이 뺌
게이트를 CI로 걸어둔다 검증 G2·G3 단계는 실패 시 exit 1을 낸다. 도면이 갱신될 때마다 자동으로 돌려두면 기준점이나 뷰 분리가 깨지는 순간 바로 잡힌다. G9의 기준선 회귀도 마찬가지다.

4.1 새 도면 인테이크에서 실제로 드는 시간

단계사람 판단비용
파싱 · 끊김 진단 · 폐곡선 추출 · 명령 생성없음0 — 도면이 바뀌어도 그대로 돈다
레이어 · 뷰 제목 · 앵커 · 기준점 검증항목설정값 채우기설정 파일 하나. 반나절
조립 스펙필요 — 여기 한 군데뿐형상 복잡도에 비례
변형 도면(같은 형식, 다른 치수)params 값만도면을 아예 안 읽는다

4.2 그림으로 읽는다 — 기하가 못 주는 의미

기하 파싱은 "이 선이 무엇인지" 모른다. 구체 외곽선인지 치수보조선인지, 여기가 벽인지 개구인지 좌표만으로는 안 갈린다. 실제로 맨홀 좌측 X=15,400 이 벽인지 개구인지 선만 보고는 판정이 안 됐다. 사람은 그림을 보면 즉시 안다.

그래서 그림과 좌표를 한 쌍으로 묶는다. 이게 조립(5장) 판단의 재료다 — 조립이 "사람 판단이 들어가는 유일한 자리"인데, 그 판단을 그림 없이 하면 추측이 된다.

          ①캡처                    ②사이드카                ③조회
도면 ────────────→ 이미지 ──── 픽셀↔좌표 변환 ────→ 프로젝트 mm ────→ 엔티티·링·레이어
                     ↑                                                      │
                     └──────────── ④오버레이(추출 결과를 그림 위에) ─────────┘

사람: 이미지에 표시  →  ②로 좌표 확정  →  ③으로 "그 자리에 무슨 엔티티가 있나"

캡처 규칙 셋

규칙
전 레이어를 그린다우리가 버린 것까지 보여야 "왜 안 잡혔나"를 판단한다. 프로파일 레이어는 진하게, 나머지는 흐리게. 파싱이 버리는 ARC·ELLIPSE도 그린다 — 그게 빠진 자리가 보여야 한다
축척은 지정하고 캔버스를 역산렌더 결과에서 축척을 되짚으면 여백·DPI·레터박싱 어딘가에서 반드시 어긋난다. 뷰 bbox는 이미 아니까 "5 mm/px"을 정하고 캔버스 크기를 거기서 계산한다 → unitsPerPx가 계산값이 아니라 내가 정한 값이 된다
사이드카를 같이 떨군다이미지만 있으면 "여기"를 말로 설명해야 한다. 변환식이 붙어 있으면 픽셀이 곧 좌표가 된다

사이드카 — 그림과 좌표를 잇는 다리

{ "view": "단 면 B-B", "kind": "cross",
  "image": { "w": 1675, "h": 1388 },
  "originDwg": [-48351.647, 483619.770],   // 이미지 좌상단 픽셀의 도면 좌표
  "unitsPerPx": 0.004,                     // 내가 정한 값 (역산 아님)
  "yFlipped": true,                        // 화면 y는 아래로, 도면 y는 위로
  "datumY": 483623.477,                    // 프로젝트 Z=0
  "viewLeftDwgX": -48350.447,              // 뷰 좌단 = 로컬 u=0
  "anchor": { "u0": 2150 },
  "howTo": [ "dwgX = originDwg[0] + px * unitsPerPx",
             "dwgY = originDwg[1] - py * unitsPerPx",
             "u(mm) = round((dwgX - viewLeftDwgX) * 1000)",
             "z(mm) = round((dwgY - datumY) * 1000)",
             "프로젝트 좌표 = anchor 적용 (u0/v0/flip/swapUV)" ] }
핵심 — 사람이 표시한 자리를 엔티티로 되찾는다 이 경로가 있어야 협업이 성립한다. 사람이 이미지에서 동그라미 친 자리가 픽셀 → 도면 좌표 → 프로젝트 mm 으로 내려가고, 거기서 그 자리의 선분·레이어·소속 폐곡선을 찾아낸다. 그래야 "여기 이상하다"가 "레이어 -환기구의 이 선분 때문에 링이 안 닫힌다"로 확정된다. 말로 주고받으면 서로 다른 곳을 본다.

지금 되는 것 / 없는 것

단계수단상태
① 뷰별 캡처 (SVG·PNG)capture.mjs. --crop으로 접합부만 확대있다
② 픽셀 → 프로젝트 좌표사이드카 .json있다
③ 좌표 → 엔티티 조회inspect.mjs(뷰 전수) · probe.mjs --ring(링 좌표) — 사람이 목록에서 눈으로 찾는다거칠다
③′ 점·영역으로 엔티티 집기"이 좌표 반경 200mm 안의 선분·링·원·개구부를 나열" 하는 도구없다
④ 추출 결과를 도면 위에 겹쳐 그리기report.mjs는 링만 따로 그린다. 캡처 위 오버레이는 아니다없다
3D 결과를 같은 규칙으로 렌더render.mjsmodel-X/Y/Z.svg + 치수선있다

③′와 ④가 다음에 만들 것이다. 둘이 있으면 왕복이 닫힌다 — 사람이 그림에 표시 → 엔티티 확정 → 설정 한 줄 수정 → 다시 그림으로 확인. 지금은 ③에서 목록을 눈으로 훑느라 끊긴다.

3D 렌더도 같은 축척 규칙으로 뽑아야 도면과 나란히 놓고 대조된다. 입면도·측면도 검증(3.2 validator)이 붙는 자리가 여기다.

5조립 스펙(IR) — 사람 판단이 들어가는 유일한 자리

5.1 IR 연산

op필드쓰는 곳상태
boxmin[x,y,z], max[x,y,z]순수 직육면체검증
extrudeprofile, axis, from, to, cap, drift구간 내 단면 불변. drift빗각 기둥(단면이 평면 안에서 미끄러짐)검증
loftsections:[{profile, at}, …]두 지점 사이 단면 선형 변화boolean 금지 결과가 안 닫힌다 → 11.4.6
intersectmembers:[id,…]두 방향이 동시에 맞아야 하는 형상 — 평면 윤곽 ∩ 정면 윤곽검증
cylinderradius, from, to원형 관통·기둥부분 Z축 한정
unionmembers:[id,…]봉투 만들기 · 구간 합치기검증
differencebase, cutters:[id,…]공동·개구부검증
sweep(측점 기반. 미구현)곡선 선형·구배가설

5.2 연산 결정 트리

이 형상을 어떻게 만들까?

┌ 단면이 구간 내내 같은가?
│   예 → extrude.  압출축 = 단면 평면의 법선
│   아니오 ↓
├ 두 지점 사이에서 선형으로 변하는가?
│   예 → loft.  ★ 꺾이는 자리마다 단면을 놓고 구간을 끊는다
│   아니오 ↓
├ 축이 곡선이거나 구배가 있는가?
│   예 → sweep (미구현). 지금은 구간을 잘게 끊어 loft/extrude로 근사
│   아니오 ↓
├ 원형 관통·기둥인가?
│   예 → cylinder.  지름으로 집는다. 선분과 섞지 않는다
│   아니오 ↓
└ 층 구조가 수평 단면들로 주어지는가?
    예 → 층별 XY 프로파일을 Z로 쌓아 union (조각이 Z로 진짜 겹치게)

5.3 조립 5원칙

① 치수로 집는다

순서(loops[0])로 집으면 도면이 조금만 바뀌어도 조용히 다른 면을 집는다. 면적 순위는 흔들리고 치수는 안 흔들린다. 못 찾거나 여럿이면 예외를 던진다.

loop('단 면 B-B', 2700, 2750).ring
circles('평 면 도', 900, /^-전력구$/)
opening('단 면 H-H', 1200, 2000)

② 꽉 찬 덩어리부터 만든다

외곽선이 오목하면(ㄷ자·계단형) 그대로 압출한 솔리드는 파인 자리가 비어 있다. 그 자리에 벽을 세우려고 공동을 빼도 뺄 재료가 없어 아무 일도 안 일어난다. 파인 면을 따로 압출해 합쳐서 빈 곳 없는 덩어리를 만든 다음에 뺀다.

shell = 오목한 외곽 압출
fill  = 파인 면 압출        ← 폐곡선 추출이 이미 뽑아준 면
solid = union(shell, fill)  ← 여기서 비로소 꽉 찬다
body  = solid − 공동들      ← 이제 벽이 남는다

③ 구간은 합친 뒤 한 번만 뺀다

단면이 다른 구간을 각각 빼면 경계에서 반드시 구멍이 난다 — 큰 쪽 공동이 여유만큼 작은 쪽으로 넘어가 단차 벽면을 파먹는다. 공동끼리는 전이점에서 겹치지도 벌어지지도 않게 나눈다.

④ 커터는 하나씩, 밖으로

떨어진 커터끼리는 교차하지 않아 union이 죽는다. 커터는 하나씩 먹인다. 대상 면에서 정확히 시작하면 boolean이 불안정해지므로 모든 방향으로 여유(OVER)를 준다.

⑤ 꺾이는 자리마다 단면

loft는 두 단면 사이를 곧게 이을 뿐 꺾인 자리를 만들지 못한다. 꺾이는 좌표가 방향마다 다르면(옆·위 −300, 아래 −100) loft를 또 끊는다. 중간 단면 값은 상수로 박지 말고 내분점을 코드가 계산하게 둔다.

보조: 수직 단차는 저절로 생긴다

앞 구간이 작게 끝나고 뒤 구간이 크게 시작하면 그 차이가 곧 단차 벽면이다. 따로 만들 것이 없다. 종방향 헌치만 별도 쐐기로 되붙인다.

5.4 압출축과 벽 방향 검증

YZ 단면을 X축으로 밀면 → Y 방향 벽만 생긴다. X 방향은 열린다
XZ 단면을 Y축으로 밀면 → X 방향 벽만 생긴다. Y 방향은 열린다

나머지 방향 벽은 두 단면을 교집합할 필요 없이 공동의 압출 범위를 좁혀서 만든다. 외곽은 전 구간을 채우고 공동만 안쪽으로 줄이면 앞뒤로 벽이 남는다. 공동의 끝이 솔리드 내부라 면이 겹치지 않아 여유도 필요 없다.

단면이 어느 평면인지는 절단 기호가 결정한다. 절단선 양끝 두 점의 x가 같으면 YZ, y가 같으면 XZ다. 폭 치수만으로는 구분이 안 되는 경우가 있다(X도 2,600, Y도 2,600).

5.5 프로파일이 못 쓸 때 — bbox 재구성

링은 못 믿어도 bbox는 믿을 수 있다. 형상이 직사각형이라는 걸 알면 bbox만으로 복원된다. 단, expect()를 남겨 도면과의 끈을 유지한다 — 값이 어긋나면 거기서 걸린다.

expect('단 면 H-H', 1200, 2000, '환기 OPEN부 (2.0x1.2)');   // 실재 확인만
profile('mh.ventHole', 'XY', rect(15800, -500, 17000, 1500)); // 실제 프로파일

오목한 외곽은 rect()로 못 만든다. 그때는 X자 교차 분할이 필요하거나, 수평 단면에서 층별로 다시 세우는 쪽이 낫다.

6파라메트릭화

DWG ──fit──→ params/<이름>.json ──build --params──→ IR ──→ 3D
              ↑ 사람은 여기만 만진다.   build 는 도면을 안 본다
불변식: build가 도면을 안 본다 검증 이것 하나가 나머지를 거의 다 푼다. 조립이 loop('단 면 B-B', 2700, 2750)처럼 치수를 도면 조회 키로 쓰는 한, 사용자가 2700을 3000으로 바꾸면 그런 폐곡선이 없어 예외가 난다. 도면에 묶여 있으면 파라메트릭이 성립하지 않는다.
검증: views.json을 치운 채 --params로 빌드해 명령 목록이 바이트 단위로 동일했다.

6.1 값 하나의 생김새

{
  "구체_외폭": { "v": 3800, "src": "measured", "from": "단 면 C-C 외곽 폭",
                "fitted": 3800, "grade": "exact" },
  "벽두께":    { "v": 400,  "src": "design", "min": 300, "max": 600, "step": 50 },
  "구체_내폭": { "expr": "구체_외폭 - 2*벽두께" },
  "샤프트":    [ { "no":1, "x0":1900, "x1":3200 }, { "no":2, … } ]
}
필드파생 효과
src: measured도면에서 뽑았다바꾸면 "도면과 다름" 경고. 막지는 않는다 — 설계를 바꾸는 게 목적이다
src: design사람이 정한다자유롭게 바꾼다
expr식 → 자동으로 derived위상 정렬로 평가. 순환이면 예외(구속 솔버가 아니다)
min/max/step유효 범위검증이자 UI 위젯이 그대로 나온다
fitted도면에서 뽑은 원값현재값과 비교해 도면 이탈 표시
배열치수가 아니라 개수가 바뀌는 것샤프트 2→3, 환기구 없음

6.2 재현 등급 — 파라미터로 못 만드는 형상 다루기 검증

프로파일을 파라미터로 "생성"하면 도면의 실제 형상을 잃는다. 50mm 보도 단차 같은 자잘한 것이 생성기로 재현이 안 되면 조용히 빠진다. 그래서 완전일치를 요구하지 않고 등급을 매긴다.

등급조건처리
exact꼭짓점 집합이 mm 단위로 일치파라미터로 완전 대체
tolerantbbox·면적·꼭짓점 수 일치, 개별 점 ±ε경고를 남기고 파라미터 사용
opaque생성기로 재현 불가도면 링을 좌표째 얼려 params에 박는다

opaque가 핵심이다. "재현 못 하면 파라미터화 안 한다"가 아니라 "재현 못 하는 링은 값으로 얼려 넣는다". 그러면 build가 도면을 안 봐도 되면서 자잘한 형상이 빠지지도 않는다. 그 링은 못 바꾸는 것일 뿐이고, 그게 정직하다. 등급 분포가 곧 "이 도면이 얼마나 파라메트릭한가"의 척도다 (대상 도면: opaque 8 · exact 2 · tolerant 1).

6.3 파라미터로 올릴 자격 검증

도면과의 끈이 없는 값은 파라미터가 아니다 const BORE_R = 450; // 원본 엔티티에서 눈으로 읽어 적음 — 이런 값은 바꿔도 도면과 대조할 방법이 없다. 도면이 바뀌어도 안 바뀐다. 먼저 circles()·loop()· opening()으로 도면에서 집게 만들고, 다른 값과 대조해 어긋나면 빌드가 죽게 한 뒤에 파라미터로 올린다.

6.4 규칙 층 — 폼과 도구를 가르는 것

종류동작
위상 topology형상을 만들 수 없게 된다막는다 (exit 1)loft 단면 위치 역전 · 벽두께가 절반 초과 · 보어가 벽을 뚫음 · 구간이 안 맞닿음
설계 design만들어지지만 기준 미달경고. 사람이 판단내공 높이 < 2,100 · 토피 < 1,000 · 최소 벽두께 · 개구 Ø600

규칙은 부재 종류에 붙는 것이지 도면에 붙는 게 아니다. 도면별 예외가 필요하면 문턱 자체를 파라미터로 노출한다. 모델러까지 가서 비틀린 면으로 만나는 것보다 훨씬 싸다.

6.5 편집 UI는 얇다 검증

build --params → emit → run --reset --export → measure --ir → render --dims

파이프가 이미 CLI 단계 사슬이라 UI가 한 일은 params 편집 + 그 사슬 순서대로 실행뿐이다. min/max/step이 그대로 입력 위젯이 됐고 src는 태그, fitted는 변경 표시가 됐다. 갱신 버튼이 검증을 태워야 도구가 된다 — 단순 실행이면 폼이다.

못 박을 것 둘모델러에서 직접 편집하지 않는다. 갱신하면 UID가 전부 바뀌어 날아간다. 편집은 params에서만.
갱신 1회당 씬 초기화 1번. 초기화를 연달아 반복하면 모델러 파이프가 죽는다.

7검증 체계

7.1 의도와 결과를 따로 잰다 검증

부피가 이상할 때 물어야 할 것은 둘이다. 이걸 못 가르면 엉뚱한 데를 판다 — 실제로 손으로 기대값을 세 번 조립했는데 세 번 다 커터 범위를 놓쳐 틀렸고, 그 값으로 모델러를 의심하며 시간을 버렸다.

우리 조립(IR)이 틀렸나?         ← 의도 : IR을 격자로 CSG 평가 (모델러 없이)
백엔드가 IR대로 안 만들었나?     ← 결과 : OBJ 삼각형을 발산 정리로 실측

파트                    부피 m³     IR 의도       차이
전력구_구체             100.5403   100.5350     0.0053 ✓
맨홀2_구체               65.3577    74.6819    −9.3242 ✗  ← 여기만 백엔드가 흘렸다

격자 평가는 25mm 격자에서 0.1% 안팎이라 소수 셋째 자리는 못 보지만, boolean이 죽는 사고는 언제나 m³ 단위로 어긋나므로 충분하다.

「의도」를 재는 쪽이 근사면 대조가 무너진다 검증 IR을 격자로 평가하던 방식은 얇은 부재에서 몇 %가 틀린다. 25mm 격자로 두께 240을 재면 셀 중심이 10개 잡혀 250 두께로 계산된다(+4.2%). 교량 상부공 바닥판(240)·마모층(50)· 방호울타리에서 그대로 나왔고, 멀쩡한 모델 6파트 중 5개에 ✗가 찍혔다. 같은 부재 3기가 서로 다른 값(8.4625 / 8.7125 / 8.4625)으로 나온 것도 격자 정렬 탓이다.
대응: boolean이 없으면 격자를 안 쓴다 — box는 변의 곱, extrude는 신발끈 면적 × 길이, loft는 심프슨(꼭짓점 선형 보간이면 단면적이 2차식이라 정확), union은 멤버 bbox가 안 겹치면 합. 전부 0.0000 ✓로 떨어졌다. 출력에 해석/격자를 같이 찍는다.
교훈: 검사기가 거짓 경보를 내면 사람이 ✗를 무시하게 되고, 그때 진짜 사고가 지나간다.

7.2 이상 신호 우선순위

#신호확정력
1자기교차 링확정그 자체가 결함. 압출하면 솔리드가 쓰레기가 되고 이후 boolean이 조용히 무력화된다
2커터가 자기 부피보다 많이 뺌확정물리적으로 불가능 → boolean이 죽었다. 형상 논쟁이 필요 없다
3파트 수 ≠ modelCount확정boolean이 인자를 흘렸다. 남은 커터가 겹쳐 있어 겉보기엔 멀쩡하다
4IR에 없는 그룹이 결과에 등장확정3과 같은 사고인데 어느 커터가 남았는지까지 알려준다
5뷰 폭·높이 ≠ 도면 치수강함뷰 분리 또는 앵커 문제
6꼭짓점 수 이상의심4=정상 사각형 · 8=개구 기호 오염 · 114=가구 혼입 · 10=헌치 있는 정상
7의도 vs 실측 부피 차강함차이가 일정하면 union 조각 손실, 커터마다 다르면 커터 문제
8기준선 회귀 실패강함이전에 사람이 확인한 형상이 바뀌었다
9열린 변(비다양체)참고이음매 T 정점. 부피·렌더링은 정상이나 IFC에서 걸릴 수 있다

7.3 기대값은 자동으로 안 나온다 — 그리고 그게 맞다

커터는 관통을 확실히 하려고 대상 밖으로 튀어나와 있고 공동끼리 겹치기도 한다. 그래서 Σ멤버base − Σ커터도 틀린 값이 된다. 틀린 기대값은 기대값이 없는 것보다 나쁘다. 새 형상의 기대값은 원시 파트 부피표를 재료로 사람이 한 번 조립하고, 맞으면 기준선으로 얼린다.

두 단면 사이 면적은 t의 2차식이므로 심프슨 V = L·(A0 + 4·A(½) + A1)/6근사가 아니라 정확하다. loft 검산에 그대로 쓴다.

기준선은 커밋한다 baselines/<도면>.volumes.jsonout/과 달리 재생성으로 복구되지 않는다. 사람이 한 번 확인한 부피가 남아 있어야 다음 변경이 형상을 건드렸는지 알 수 있다.

7.4 그림으로 보는 검증 검증

뷰어는 조립과 같은 변환 함수를 써야 한다 뷰어가 자기 변환을 따로 가지면 보여주는 것과 조립되는 것이 갈라진다. 거짓말하는 뷰어는 없는 것보다 나쁘다. 캡처 변환도 역산하지 말고 "뷰 박스를 지정하고 캔버스를 축척에서 역산"한다.

8함정 사전

전부 실제로 밟은 것이다. 증상 → 원인 → 대응 순.

8.1 도면·데이터

증상원인대응
bbox·축척이 통째로 이상유령 기하가 먼 좌표대에 있다sheet 영역 밖을 먼저 버린다
원점 근처 뷰에 남의 원이 무더기INSERT 블록 로컬 좌표같은 시트 필터로 거른다
뷰가 통째로 빠진다구조 외곽선이 뷰마다 다른 레이어에 있다후보 레이어를 넉넉히. struct는 넓게
프로파일 꼭짓점이 100개 넘음케이블랙·철근 같은 가구가 섞임body는 좁게. struct와 분리
폐곡선이 안 닫힘대부분 레이어 오분류(선은 있다)진단 도구로 "오분류 / 누락"을 가른다 — 대응 비용이 100배 차이난다
기존 닫힌 폴리라인이 쓸모없음전부 해치·심볼 조각기대하지 말 것. 좌표만 뽑아 새로 만든다
치수 정의점이 0으로 옴파서 한계actualMeasurement·textMidPt는 정상. DEFPOINTS 활용
그려진 길이가 실제가 아니다파단선. 기둥이 6,100 으로 그려져 있는데 실제 33,800. 폐곡선·부피가 그럴듯해 숫자로 안 걸린다CS-CUTL 류가 뷰 안에 있으면 의심한다. 생략량은 표고 텍스트 차 − 도형 길이 로 되찾는다
한 파일에 도형이 여러 벌 쌓여 있다도면집 스택. 제목·치수 없는 잔재가 65,000 간격으로 17벌뷰 상자를 눈으로 잡지 말고 도곽 블록에서 계산한다 — INSERT 위치 × scale × 용지(A1 841×594)
「단면도」 안쪽 선을 다른 부재로 읽음절단면이 아니라 투영이다. 먼 쪽 모서리가 겹쳐 보인다그 치수가 외곽 − 2×R 로 떨어지면 투영이다
평면 모서리가 45° 모따기파서가 LWPOLYLINE bulges 를 버려 90° 호가 현 하나로 눌린다호 끝점은 정확하므로 R 은 되찾는다. 링 면적을 그대로 쓰면 코너당 71,350 mm² 부푼다
구조 형상이 로 잡힌다격자로 보면 평면도가 73행×83열짜리 표다표 색인에 레이어 필터(CS-TABL-*)를 준다
다른 DWG인데 엔티티 수·좌표가 똑같다파싱 캐시 키 충돌. 두 번 다르게 밟았다. ① 슬러그 [^\w.-]→_\w가 한글을 안 먹어 거더배치·교대배치·교량폭원이 같은 이름이 됐다. ② 고쳐서 쓴 목록 인덱스 — 폴더에 파일이 하나 늘자 전부 한 칸씩 밀려 [6]이 옆 도면 캐시를 읽었다 캐시 키는 파일 경로 해시. 인덱스는 목록 순서에, 슬러그는 문자 집합에 의존한다. 캐시는 틀린 답을 조용히 재사용하므로 "같은 결과가 나온다"를 우연으로 넘기지 말 것
모든 치수가 정확히 1000배DWG 모델단위가 도면군마다 다르다. 맨홀군 1단위=1m, 교량 삽도군 1단위=1mmunitMm을 설정으로. DIMENSION.actualMeasurement와 치수 글자를 비교하면 즉시 확정된다(3000.00 ↔ 3.000m)
도면 표기 치수와 대조가 불가능유형별 삽도는 치수가 기호다 — L · L1 · β · θ · VAR · n@3,600숫자 치수 대 기호 치수를 세어서 먼저 판정한다. 기호뿐이면 G2를 통과할 방법이 없으므로 그 도면은 대상에서 뺀다
구조선과 치수선이 같은 레이어표준 레이어(CS-CONC-MAJR)에 둘 다 올린 도면이 있다레이어 말고 이 가른다 — colorIndex 0(ByBlock, 치수 블록 안) vs 7(ByLayer, 구체). 걸 수 있는 축을 레이어 하나로 두면 안 된다
뽑힌 형상이 어느 도면에도 없는 조합 한 시트에 날짜 다른 작업본이 겹쳐 그려져 있다. 교량시종점 삽도는 TYPE1~4 한 벌(주황 테두리)과 「교량 시·종점 …전면」 한 벌(자홍)이 서로 어긋나게 포개져 있다. 뷰 상자가 그 경계에 걸치면 두 벌이 섞인다 시트 전체를 먼저 뜬다 → 테두리·표제로 벌을 가른다 → 도형 하나를 떠서 눈으로 확인 → 그 다음 상자. 숫자로는 안 걸린다 — 폐곡선도 치수도 그럴듯하게 나온다. 날짜 도장은 개정 이력이 아니라 작업본 구분일 수 있다
같은 뷰에 축척이 다른 도형 확대 상세가 같은 도형 안에 들어 있다(교좌받침 상세). 가로·세로 배율이 서로 다르기도 하다 — 받침이 153×182 인데 상세에서는 461×196 치수로 집으면 저절로 갈리지만 갈렸는지 확인한다. fit() 에 좌표 범위 검사를 넣는다
같은 부재가 1 mm 다르게 나온다 DWG 부동소수를 꼭짓점마다 따로 반올림한다. 대칭 배치된 부재에서만 드러난다 (교대 5,192/5,191 · 받침 154/153×3) loops(…, tol) 로 열되 기본값은 0. 여는 것은 부르는 쪽의 판단이고 1~2 mm 는 형상이 아니라 잡음이라는 뜻이다
표제·개정 도장이 같은 좌표에 여러 개개정판을 지우지 않고 겹쳐 둔다(240912/241031/241115)기하는 대체로 안 겹친다(중복률 1~10%). 표제 개수로 뷰 수를 세지 말 것

8.2 좌표·뷰

증상원인대응
Z가 713mm 어긋남기준을 텍스트 위치로 잡음선에서 잡는다
Z가 420mm 어긋남계획고 선 후보가 둘(도로/토공)라벨 바로 아래 선
서로 다른 두 표고 라벨이 같은 선을 가리킨다라벨 y를 평균내는데, 같은 라벨이 도형마다 반복돼 평균이 어느 도형에도 안 속한다. 교량 계획고·토공 계획고 10개가 y 27,533~81,177에 흩어져 있었다라벨 y를 무리로 끊어보고 둘 이상이면 던진다. 예외가 아니라 그럴듯한 숫자가 나오는 실패라 대조 항목이 없으면 영영 안 잡힌다
뷰 폭이 부풀음이웃 상세도 조각이 붙어옴교대 분할 + 표제 귀속. 상세도도 표제 후보에
뷰 하단이 잘림부재 방향 라벨이 표제로 잡힘minHeight 상향
좌표가 엉뚱한 값수평 단면·평면도의 세로축을 Z로 봄v0·swapUV. 3.3 절차로 판정
면적이 음수 / 면이 뒤집힘반전·맞바꿈으로 감김 방향이 반대뒤집기 홀수면 링 역순
임계값을 10mm까지 좁혀도 조각이 1개상세 확대 테두리 상자(Δy=5,117)가 상세행과 단면행을 세로로 잇는다. 구조선과 같은 레이어·같은 색이라 못 거른다임계값 조절을 포기하고 명시 뷰 영역으로 간다. 「간격이 존재한다」는 전제 자체가 깨진 경우다
같은 제목이 N벌 — 뷰가 하나로 뭉침유형별 삽도는 사례마다 같은 제목을 붙인다 (단면A×4 · 교량 시·종점×6)제목은 뷰의 유일 키가 아니다. (제목, 위치) 쌍이거나 명시 영역이 필요하다. 표제 중복률을 먼저 센다 — 7장 전부 47~84%였다
뷰 제목 자체가 없다표제가 시트명 하나뿐이고 나머지는 A · B · L of Road 같은 기호글자 높이 하한을 어떻게 잡아도 안 나온다. 명시 영역 외에 길이 없다
도형마다 축척이 다르다모델스페이스가 1:1이라는 전제가 삽도에서 깨진다. 중앙분리대 방호벽 단면은 5.805배로 그려져 있었다배율은 도면 하나가 아니라 뷰마다 받는다. 값은 표기 치수 2개로 역산해 교차검증한다 (높이 7,372.3↔1,270 · 바닥폭 3,393.9↔585, 차이 0.06%)

8.3 프로파일

증상원인대응
부피가 정확히 2배개구 기호(X 표시)가 링을 자기교차시킴기호를 기하 서명(같은 bbox·반대 기울기 대각선 쌍)으로 걷어낸다. 레이어로는 못 거른다
사람 눈엔 멀쩡한데 안 잡힘모서리가 몇 mm 안 닫혀 있다bbox → rect() 재구성 + expect()
재료가 한 덩어리로 뭉침경계선 레이어를 추출에서 뺐다면이 갈리려면 경계선이 있어야 한다 — 함께 넣고 배정은 나중에
폐곡선이 원 윤곽을 따라 돔원을 다각형으로 근사해 선분에 섞음원은 따로 모아 지름으로 집는다
X자 교차가 안 쪼개짐평면 분할이 T자 교차만 처리기호는 사전 제거. 남으면 X자 분할 추가 필요 부분
끊김이 0인데 폐곡선도 0같은 직선 위에서 겹치는 두 선(끝점은 다르다). 중복 제거는 T자 분할 전에만 돌아서, 분할이 겹친 구간을 양쪽에서 똑같이 잘라 같은 변을 두 벌 만든다 → 반변이 4개가 되어 면 순회가 엉킨다T자 분할 뒤에 한 번 더 중복 제거. 증상이 "닫혔는데 안 나온다"라 끊김 진단으로는 절대 안 잡힌다
폭·높이만 틀리고 면적은 맞다 끝이 아무 데도 안 닿는 매달린 변이 있으면 면 순회가 거기까지 갔다 되돌아온다. 왕복이라 면적은 0 인데 bbox 는 부푼다. 게다가 bbox 를 collinear 제거 전 링으로 재고 있었다 (상부공 폭 12,752 → 12,951) bbox 는 collinear 를 뺀 링으로 잰다. area 만 보면 절대 못 잡는다
진단 도구와 본편이 다른 값 진단 도구가 projectViews 를 안 거치고 buildLoops 를 직접 불렀다 — 개구 기호 제거·앵커·평면 변환이 빠진다 본편과 같은 함수를 쓴다. 다르면 도구를 못 믿게 되고, 그 순간 검증 체계 전체가 죽는다
윤곽이 진짜로 안 닫혀 있다구성 도해(폭원·배치)는 닫힌 단면을 그리지 않는다. 띠와 열린 외곽선만 있다끊김 원인 분류에서 「선 없음」 비율을 본다. 교량폭원은 56곳 중 54곳이 그랬다 — 설정으로 못 고친다. 그 도면은 솔리드 대상이 아니다

8.4 조립

증상원인대응
전 구간이 같은 단면으로 나옴횡단면 하나를 전체에 압출종단면이 구간 배정표다. 수평선을 Z 내림차순 × X 범위로 읽는다
안이 들여다보임한 평면 단면만 압출해 반대 방향 벽이 없다공동의 압출 범위를 좁혀 벽을 남긴다
구간 경계에 구멍구간별로 따로 difference몸통을 union한 뒤 한 번만 뺀다
union이 예외로 죽음떨어진 커터끼리 union 시도커터는 하나씩. union하는 건 "구간 몸통"이지 커터가 아니다
커터가 46 m³를 파먹음커터를 대상 바깥면에서 시작모든 방향으로 OVER 여유
difference가 조각을 통째로 흘림면으로만 맞닿은 솔리드를 union부피로 겹치게 만든 뒤 union. 단 압출축 방향으로만 늘린다 (통째로 부풀리면 더 나빠진다)
같은 커터 재사용 실패boolean이 피연산자를 소모조각 수만큼 커터를 따로 만든다. 안 겹치는 조각엔 아예 넣지 않는다
경사면 하나가 끝까지 올라감loft로 두 번 꺾으려 함꺾이는 자리마다 단면. 방향별로 꺾이는 좌표가 다르면 또 끊는다
loft 면이 비틀림두 단면의 시작 꼭짓점이 어긋남링 정규화(반시계 · v최소→u최소 시작) + 꼭짓점 수 일치 강제
loft가 부풂단면 3개 이상 → 스플라인 보간2단면씩. 결과 정점에 중간 행이 없으면 직선 룰드다
두 번째 도면의 build가 위상 위반으로 죽음설계 규칙이 첫 도면의 파라미터 이름에 묶여 있다. 없는 값이 undefined로 비교돼 전부 실패로 떨어진다규칙에 needs(요구 파라미터)를 붙여 해당 없으면 건너뛴다. 규칙 층은 "도면 고유값 없음"을 자처했지만 실제로는 지켜지지 않았다

8.5 백엔드(모델러)

백엔드 특이사항은 전부 emit/ 안에 가둔다. 아래는 EGModeler 사례지만, 다른 툴로 바꿔도 같은 성격의 함정이 그 자리에 온다.

증상원인대응
명령이 조용히 무시됨, created:[]뷰어 모드라 모델링 명령이 등록조차 안 됐다작업 시작 전에 등록 명령 개수 확인. 연결 정상 ≠ 모델링 가능
커터 8개가 씬에 남음boolean이 이항이다 — 셋 이상은 무시둘씩 접는다. modelCount 대조로 즉시 잡힌다
압출이 엉뚱한 방향Cap 단독은 항상 +Z로 민다항상 방향을 명시. Cap 플래그는 방향 지정
서피스가 나옴loft 기본이 서피스Cap으로 막아 솔리드. 원본 삭제 플래그는 건드리지 않는다
부피는 맞는데 boolean 이 샌다loft 결과가 안 닫힌다. Cap 을 덧대도 4각형 단면조차 열린 변 12개. 발산 정리 부피는 정확해서 부피 검사로는 절대 안 걸린다loft 를 boolean 인자로 쓰지 않는다. 단면이 평행이동만 하면 자유방향 압출(drift)로 대체 — 그건 닫힌다. → 11.4.6
이후 명령이 전부 무시선택 명령을 안 닫음Esc로 닫는다
파일이 안 생기는데 오류도 없음경로의 _가 스크립트 특수문자큰따옴표 필수 + 파일 존재·mtime을 직접 확인
씬 초기화 명령이 조용히 무시됨뷰 조작 명령을 ~ 접두로 보내 끝나지 않는 상태로 물렸다. status.command가 그 이름으로 남는다명령 상태를 매번 확인. 접두 없는 Esc로 푼다. 연결 정상 ≠ 명령 수용은 뷰어 모드 말고 여기서도 성립한다
파이프가 죽음(프로세스는 살아 있음)씬 초기화 반복초기화는 갱신당 1회. 죽으면 재시작 외에 방법 없다

9새 도면 인테이크 워크시트

9.1 채워야 할 것 (순서대로)

  1. 도면 적격 판정 먼저 — 표기 치수를 숫자형/기호형으로 세고, 구조 윤곽이 닫히는지 본다. 기호뿐이거나 안 닫히면 솔리드 대상이 아니다. 여기서 걸러야 나머지 아홉 항목을 헛되이 채우지 않는다
  2. 모델단위DIMENSION.actualMeasurement ↔ 치수 글자를 비교해 unitMm 확정. 도면군마다 다르다
  3. 구조물 종류·좌표계 선언 — X·Y·Z 방향과 원점을 문장으로
  4. 시트 영역 — 전체 좌표 분포를 히스토그램으로 보고 유령 기하를 가른다
  5. 레이어 4갈래struct(넓게) / body(좁게) / material / ground. body ⊆ struct. 레이어가 구조선과 치수선을 안 가르면 색·선종으로 거른다(entityFilter)
  6. 표제 글자 높이 분포 — 시트명 / 뷰 제목 / 부재 라벨의 h를 세어 minHeight 결정. 표제 중복률도 같이 센다 — 높으면 제목으로 뷰를 못 가른다
  7. 뷰 목록 — 제목 → {plane, flip, role}. 단면은 절단 기호 좌표로 평면 판정. 제목이 없거나 중복이면 viewBoxes로 좌표를 짚는다
  8. 기준점 — 라벨 정규식 + 도면 치수 검증 2개 이상. 기준선이 없으면 mode:'none'으로 명시하고 검증을 G5로 미룬다
  9. 앵커 — 뷰별 u0/v0/flip/flipV/swapUV/unitMm. 비대칭 특징으로 교차검증. 축척이 다르면 표기 치수 2개로 역산해 교차검증한다
  10. 구간 배정표 — 종방향 뷰에서 X 범위 × 단면 대응
  11. 조립 스펙 — 5장의 결정 트리와 5원칙
  12. 규칙 — 이 부재 종류의 위상 규칙 · 설계 기준

9.2 설정 파일 스켈레톤

export default {
  name: '<도면이름>',
  dwg: path.join(DRAWINGS_SRC, '<파일>.dwg'),

  // 이 밖의 좌표는 버린다 (유령 기하 · 블록 로컬 좌표)
  sheet: { x0: …, x1: …, y0: …, y1: … },

  // DWG 1단위가 몇 mm인가. **도면군마다 다르다** (맨홀군 1000, 교량 삽도군 1).
  // DIMENSION.actualMeasurement 와 치수 글자를 비교해 확정한다.
  unitMm: 1000,

  // 레이어로 못 가르는 것을 거른다. colorIndex 0 = ByBlock = 치수 블록 안.
  // 구조선과 치수선이 같은 레이어인 도면에서만 쓴다.
  entityFilter: (e) => (e.entityHeader?.colorIndex ?? -1) === 7,

  layers: {
    struct:   /…/,   // 뷰 분리용. 넉넉하게 — 가구·주기가 들어가도 된다
    body:     /…/,   // 프로파일용. 좁게 — 가구가 섞이면 링이 오염된다
    material: /…/,   // 기초·잡석 등 별개 재료. 추출엔 함께 넣는다
    ground:   /…/,   // 기준선(계획고·GL·FL) 검출용
  },

  titles: {
    minHeight: 0.32,             // 부재 라벨과 뷰 제목을 가르는 글자 높이
    views: {
      '평 면 도':  'plan',        // → XY
      '단 면 A-A': 'long',        // → XZ  (절단 기호 두 점의 y가 같다)
      '단 면 B-B': 'cross',       // → YZ  (두 점의 x가 같다)
      '단 면 H-H': 'horizontal',  // → XY  (다른 단면 위에 찍힌 수평 절단)
      // 입면도·측면도를 넣을 때: 평면은 XZ/YZ지만 role은 validator다.
      // 절단면이 아니므로 여기서 프로파일을 뽑아 압출하면 안 된다.
    },
  },

  segment: { gap: 0.2, xTol: 0.5, ySlack: 0.2 },   // 단위는 DWG 단위다 (unitMm 에 맞춘다)

  // 제목이 없거나 중복이면 **좌표로 짚는다**. titles.views 와 둘 중 하나만 쓴다.
  // y 값은 눈대중이 아니라 구조선 좌표 뭉치의 경계에서 뽑고, 상자는 그 빈틈 안에 둔다.
  viewBoxes: {
    '<뷰>': { box: [x0, y0, x1, y1], kind: 'cross',
              unitMm: 1 / 5.805 },   // 도형마다 축척이 다르면 여기서 준다
  },

  datum: {
    mode: 'none',                // 기준선이 도면에 없을 때. 표고는 뷰별 v0 가 준다
    levelLabel: /…/,             // 기준선 후보를 좁히는 힌트. 값은 선에서
    checks: [                    // 최소 2개. 도면에 적힌 치수 그대로
      ['<설명>', (v) => v['<뷰>']?.layerZ['<레이어>']?.[1], -0000],
    ],
  },

  frame:  { x: '…', y: '…', z: '…', origin: '…' },

  anchors: {                     // 유도하고 교차검증한다. 지어내지 않는다
    '평 면 도':  { u0: …, v0: … },        // 평면도도 v0가 필요하다
    '단 면 B-B': { u0: … },                // 수직 단면은 v가 이미 표고
    '단 면 H-H': { u0: …, v0: …, swapUV: true },
  },

  expectExtents: { '<뷰>': [폭, 높이] },   // 분리 자동 확인

  fit({ loop, circles, opening, expect }) {
    // 도면을 보는 **유일한** 통로. 여기서 params.json이 나온다
    expect('<뷰>', 폭, 높이, '왜 이게 있어야 하는가');
    return { params: { … }, rings: { … } };
  },

  assemble({ p, ring, profile, part, rect }) {
    // 도면 조회 도우미를 주지 않는다 — 주면 다시 도면에 묶인다
  },
};
현재 구조의 알려진 거친 부분 뷰 하나의 서술이 titles.views(평면)와 anchors(앵커) 두 곳에 흩어져 있다. 3장의 모델대로 { plane, u0, v0, flip, flipV, swapUV, role } 한 덩어리로 합치는 것이 맞다. 뷰 종류를 늘리는 작업(입면도·측면도)을 시작하기 전에 정리하는 편이 싸다.

10도면 작성자에게 요청할 것

효과 대비 비용이 큰 순서. 1번 하나로 검출 로직 전체가 사라진다.

요청없앨 수 있는 것비용
레이어 3D-ORIGIN에 뷰마다 기준점 POINT 하나기준점 검출 · 앵커 유도 · 텍스트/선 혼동 사고 전부뷰당 클릭 한 번
구조체 외곽선 레이어 통일레이어 오분류 진단(끊김 50곳 중 20곳이 이것이었다)낮음
개구 기호를 별도 레이어로자기교차 링 · bbox 재구성 우회낮음
가구(케이블랙·철근)를 구조 레이어에서 분리body/struct 이중 정의낮음
시트 영역 밖 기하 정리유령 기하 필터낮음
뷰 제목 표기·글자 높이 규약표제 임계값 튜닝낮음
단면 절단 기호를 모든 단면에 표기평면 판정을 제목 추측에 의존하는 것낮음
도면을 뷰별 파일로 쪼개달라고 하지는 말 것. 표고 정합과 절단기호 매핑을 같이 잃는다(3.4).

11구조물 유형별 차이

1~4장(정렬 · 뷰 · 게이트)과 7장(검증)은 구조물이 뭐든 안 바뀐다. 바뀌는 것은 좌표 기준쓰는 연산이다.

선형 토목
전력구·터널·도로
교량점형 토목
맨홀·수조·기초
건축
좌표 기준중심선 + 계획고선형(측점) + 받침
둘로 나뉜다
구조물 외면 + GL그리드 통심선 + FL
주 연산extrude · loftsweep · loft · 프리미티브 · revolveextrude · 프리미티브extrude (층별)
구간 배정 뷰종단면측면도(일반도)없음 — 단면이 하나층 평면도
반복 단위구간경간 · 거더 · 말뚝층 · 스팬
상태검증부분검증가설

11.0 실증 결과 — 교량 도면 7장에서 실제로 일어난 일 검증

먼저: 대상이 예상과 달랐다 받은 7장은 교량 일반도가 아니라 설계지침 삽도였다 — 번호가 붙은 유형 도해 (03 교량시종점 · 04 교량폭원 · 05 중앙분리대 · 09 거더배치 · 10 횡단경사 · 13 교대배치). 한 구조물을 여러 방향에서 본 좌표가 물린 도면 세트가 아니라, 서로 다른 개념을 각각 N벌 변형으로 그린 낱장들이다. 아래 결론은 그 조건에서 나온 것이고, 실제 교량 일반도(측면도+평면도+횡단면이 물린 것)에는 11.1~11.3이 그대로 남아 있다.
도면엔티티숫자 치수기호 치수ARC막힌 곳
거더배치1,433262249 (17%)G1 — 치수가 L·β
교대배치2,1385137181 (8%)G1 — θ 가변 도해
교량시종점4,43206492 (11%)관통 — 2지간 교량 95파트 820.36 m³ (11.0.4). 「치수 0개 → 대상 아님」은 오판이었다
교량폭원2,824151100관통 — 상부공 7파트 180.36 m³ (11.0.3). 처음엔 G5에서 죽었다 — 폐곡선 버그를 고치자 나왔다
교면포장1,3041420G1 — 층상 구성표
중앙분리대2,15910870관통 — 방호벽 4.8058 m³ (11.0.1)
횡단경사5,63515613964 (1%)G1 — S% · TL 가변
가장 값싼 사전 판정 — 숫자 치수와 기호 치수를 세어본다 방법론 전체가 「도면 표기 치수와 대조한다」에 걸려 있다(G2·G3·7.3). 치수가 기호(L · β · θ · VAR · n@3,600 · S%)면 대조할 상대가 없다. 파싱 직후 TEXT/MTEXT를 숫자형/기호형으로 나눠 세는 것만으로 「이 도면은 솔리드 대상이 아니다」가 몇 초에 판정된다. 위 표가 그 결과다.
이 판정은 게이트 이전에 온다 — G0.5쯤이다. 방법론에 없던 단계다.

11.0.1 통과한 것 — 중앙분리대 방호벽

7장 중 닫힌 구조 단면을 가진 유일한 도면이었다. 세운 것은 토공용 구간 → 변화구간(2m) → 교량용 구간의 방호벽 한 줄이다.

단면A (토공용, 585×1319)  ──extrude X 0→5,000──┐
                                               ├─ loft 5,000→7,000  ← 변화구간
단면B (교량용, 584×1270)  ──extrude 7,000→12,000┘
                    union → 중앙분리대_방호벽

부피  모델러 4.8058 m³   IR 격자(25mm) 4.7970   해석 프리즈모이드 4.8058
modelCount 1 = 최종 파트 수 1

11.0.3 교량 상부공 — 폐곡선 버그를 고치자 나왔다

교량폭원은 처음에 G5에서 죽었다 — 끊김 56곳 중 54곳이 「도면에 선 없음」이었다. 그런데 겹치는 동일선상 선분 버그(8.3)를 고치고 다시 돌리자 폐곡선이 새로 나왔다. 「도면이 안 닫는다」의 상당 부분이 실은 우리가 못 닫은 것이었다. 판정을 내리기 전에 도구부터 의심할 것.

폭원 띠 상    24,300 × 240   바닥판 전폭   ↔ 도면 표기 24,300
분리교량      12,300 × 240 · 15,900 × 240   좌·우 상판
                 440 × 1,320 ×3            방호울타리
              11,400 ×  50   마모층        ↔ 도면 표기 11,400 (도로 폭)
이 도면에서다른 도면에서
바닥판 두께폐곡선 240교면포장 삽도 「콘크리트 교량 바닥판 240mm」
마모층 두께폐곡선 50교면포장 삽도 「마모층 50mm」
방호울타리 높이폐곡선 1,320 (포장면 위 1,270)중앙분리대 삽도 표기 1,270

서로 다른 삽도가 같은 값을 준다. 유형 삽도 묶음은 좌표가 물려 있지 않아 뷰 사이 교차검증이 안 된다고 봤는데(11.0), 치수 값 수준에서는 물려 있다. 공통 datum이 없는 도면군에서 쓸 수 있는 교차검증 경로가 이것이다.

세운 것: 좌·우 상판 · 마모층 · 방호울타리 4기를 경간 20m(설계값)로 직선 압출. 7파트 180.356 m³, 의도 대비 전부 0.0000. 넷째 방호울타리는 도면 윤곽이 안 닫혀 재구성했다 — 들임(10mm) 규칙을 측정된 두 부재로 확인한 뒤 적용했고, 그렇게 놓은 외면 좌표가 gaps가 짚은 끊김 좌표와 같은 값으로 떨어지는 것이 검증이다. 등급은 tolerant — 도면 좌표를 옮긴 게 아니라 만든 것이므로 opaque가 아니다.

11.0.4 교량 한 기 — 「표기 치수 0개」를 잘못 잘랐다

이 문서가 두 번 틀렸다 11.0 표에서 교량시종점을 「숫자 치수 0개 → 솔리드 대상 아님」으로 잘랐다. 표기 치수가 없으면 검증을 못 하는 것이지 추출을 못 하는 게 아니다. 모델스페이스가 1:1 이면 좌표가 곧 mm 다.
「대조할 상대가 없다」도 틀렸다 — 그 도면 안에 없다는 뜻일 뿐이고, 다른 도면과 표준 부재 치수는 여전히 상대가 된다.

1:1 인지는 크기를 아는 표준 부재로 확정했다. 도면 밖에서 온 눈금이다.

폐곡선 153×182 이 4개    ← 탄성받침 150×180. 다른 게 이 치수로 4개 나란할 이유가 없다
교대 벽체 4,680×6,506     교량 교대 자릿수
상부공 형고 1,421         지간 12,752 에 L/h≈9 — 반일체식으로 타당
접속슬래브 두께 383        표준 300~400

넷이 **동시에** 타당해지는 배율은 1 뿐이다. 10배만 달라도 받침이 1.5 m 나 15 mm 가 된다.

그 도면 하나로 2지간 교량 한 기가 열렸다 — 이 도면군에서 하부공이 부재로 그려진 유일한 도면이다.

바닥판 26,178×277 · 거더 12,303/12,748×1,144 ×5본씩
교대(벽체+확대기초) 4,680×7,953 ×2 · 날개벽 4,563×6,932 ×4
교각 두부 2,244×1,334 · 기둥 1,586×3,904 · 확대기초 5,081×1,334
교좌받침 153×182 ×8열 · 받침콘크리트 ×3 · 접속슬래브 3,705×383 ×2
말뚝 Ø518 ×10위치 (연직이라 IR 의 Z축 cylinder 가 그대로 맞았다)

95파트 · 820.36 m³ · 의도 대비 전부 0.0000
뷰 상자를 두 번 잘못 잡았다 — 숫자로는 안 걸렸다 처음 상자가 날짜 다른 두 작업본의 경계에 걸쳐 있었다. 한 시트에 TYPE1~4 한 벌(주황 테두리)과 「교량 시·종점 …전면」 한 벌(자홍)이 서로 어긋나게 포개져 있다. 뽑힌 것은 두 도형의 혼합이었고 — 교대라고 부른 것이 실은 옆 도형의 날개벽이었으며 기초·교각이 통째로 빠졌다.
폐곡선 25개가 나왔고 치수도 그럴듯했다. 검증표는 전부 통과했다. 그림을 보고서야 알았다. 4.2(캡처)가 선택이 아니라 필수인 이유다.

11.0.5 도면이 정보를 주는 방식 — 형상만이 아니다

부재도면이 주는 형태읽는 법현재
구체·교대·교각닫힌 윤곽폐곡선있다
관통구·기둥CIRCLE지름으로 집는다있다
개구부X 기호기하 서명으로 되살린다있다
말뚝해치 + 중심선중심선 x = 위치, 윤곽 두 줄 간격 = 지름없다pick 이 선을 못 집는다
철근·수량주기 텍스트없다

형상이 없다고 정보가 없는 게 아니다. 개구 기호를 되살린 것과 같은 종류의 이득이 중심선·해치에 남아 있다. circles() 를 만든 것과 같은 이유로 centerlines() 가 필요하다.

11.0.2 범위에서 뺀 것 — 명시

뺀 것
상부공(거더·바닥판)·하부공(교대·교각·말뚝)표기 치수가 있는 도면이 없다. 교량시종점은 측면도가 6벌 있지만 숫자 치수가 0개
교량 바닥판 횡단면(교량폭원)폭원 구성 도해라 닫힌 단면을 안 그린다. 끊김 54곳이 「도면에 선 없음」 — 설정으로 못 고친다
방호벽 설치 연장도면이 「중앙분리대 설치 범위」로만 표시한다. 각 5,000mm를 설계값으로 명시했다 — 도면에서 읽은 척하지 않는다
변화구간 2,000의 기하 교차검증평면도 쪽 표기 치수가 하나뿐이라 그쪽 축척을 독립으로 되찾을 수 없었다. 출처를 「도면 주기 글자」로 남겼다
ARC · SPLINE모델링한 도면에는 0개였다(운이 좋았다). 버린 도면들에는 8~17%가 있다 — 11.2 참고

11.1 교량 — 기준이 하나가 아니라 체인이다 가설

이 절은 아직 실증되지 않았다 — 확인할 도면이 없었다 받은 7장 중 하부공을 받침 중심 좌표 + 받침 표고로 기술한 도면은 없었다. 교량시종점 삽도가 교대·교각·말뚝을 측면으로 그리긴 하지만 표기 치수가 0개라 기준 체인이 실제로 그렇게 기술되는지 확인할 수 없었다. 아래는 그대로 가설이다.

전력구는 프로젝트 원점 하나로 전부 기술된다. 교량은 안 된다. 상부공은 선형을 타고(곡선·편경사로 기울어짐) 하부공은 연직으로 선다. 두 좌표계가 다르므로 잇는 지점이 필요하고, 그 지점이 교좌받침이다.

프로젝트 원점
  └─ 선형 (측점 s · 오프셋 t · 표고)          ← 상부공은 전부 여기서 나온다
       └─ 받침 (측점 + 오프셋 + 받침표고)      ← 두 좌표계를 잇는 유일한 접점
            └─ 교각 로컬 (연직 · 사각)         ← 하부공은 전부 여기서 나온다
                 └─ 기초 · 말뚝 배치 격자

도면이 이미 이렇게 기술한다 — 하부공 도면은 받침 중심 좌표와 받침 표고로 교각을 잡고, 거기서 아래로 교각·확대기초·말뚝을 내린다. 그래서 받침을 앵커로 삼는 것이 도면을 그대로 옮기는 것이 된다. 받침을 안 쓰고 절대좌표로 잡으면 사각(skew)·편경사가 들어오는 순간 값이 전부 손계산이 된다.

일반화 — 앵커는 뷰에만 붙는 게 아니다 3장의 앵커는 를 3D에 정렬하는 장치였다. 교량에서는 같은 개념이 부재군에도 필요하다. 상부공군 · 교각군 · 기초군이 각자 로컬 프레임을 갖고, 받침이 그 사이의 변환을 준다. 이 개념은 현재 방법론에 없다.

11.2 교량에 필요한 확장

항목현재실증
측점 기반 sweep평면곡선 · 종단곡선 · 편경사. 직선축 from/to로는 표현 불가없음. IFC4.3 IfcSectionedSolidHorizontal과 의미가 같다미확인 — 곡선 선형을 준 도면이 없었다. 삽도는 전부 직선 구간 도해다
revolve원형 교각 두부 · 정착부없음불필요했다 — 교각은 사각 + 벌어진 두부다. 세웠다(11.0.4)
임의축 cylinder경사 말뚝 · 사교 교각Z축 한정불필요했다 — 말뚝이 전부 연직이라 Z축 cylinder 가 그대로 맞았다. Ø518 ×10위치를 세웠다
부재군 로컬 프레임상부(선형) ↔ 하부(연직) 좌표계 전환없음 — 단일 좌표계 전제미확인
ARC · SPLINE 파싱곡선 거더 · 원형 단면버린다비중 측정됨 — 거더배치 17% · 교량시종점 11% · 교대배치 8% · 횡단경사 1%. 모델링한 도면(중앙분리대)은 0%
배열 파라미터경간 N · 거더 M본 · 말뚝 배치있다 — 6장 배열이 그대로 맞는다미확인
뷰별 축척 신규삽도는 도형마다 배율이 다르다추가됨viewBoxes[뷰].unitMm검증 — 5.805배 사례
명시 뷰 영역 신규제목이 없거나 중복인 도면추가됨cfg.viewBoxes검증
레이어 아닌 필터 신규구조선과 치수선이 같은 레이어추가됨cfg.entityFilter(색·선종)검증
복수 선택기 신규같은 부재가 여러 벌인 것이 정상 (거더·받침·말뚝)추가됨loops(뷰, w, h, tol)검증
중심선 선택기 신규말뚝처럼 해치 + 중심선으로만 그려지는 부재없다 — 스크립트로 재서 설정에 적었다구멍
예측 성적 — 11.2가 맞춘 것과 빗나간 것 맞음: ARC·SPLINE 비중이 실제로 컸다(최대 17%). 배열 파라미터가 필요한 구조(거더 M본·말뚝 배치)가 실재했다.
빗나감: revolve와 임의축 cylinder는 필요 없었다. 원형 교각도 경사 말뚝도 7장 어디에도 없다. 「교량이면 revolve가 필요하다」는 교량 일반론이지 이 도면군의 사실이 아니었다.
못 예측한 것: 실제로 막은 것은 위 목록에 하나도 없었다 — 단위(1mm vs 1m) · 뷰 제목 부재 · 뷰별 축척 · 레이어가 치수선을 안 가름 · 폐곡선 중복 변 버그. 전부 연산이 아니라 입력 해석 층의 문제다. 11.2는 「무슨 연산이 더 필요한가」만 물었는데, 실제 병목은 「도면을 읽어들이는 가정」이었다.

11.3 교량에서는 측면도의 지위가 다르다 부분

3.2에서 입면도·측면도는 검증(validator) 역할로 못박았다. 교량에서도 솔리드를 만들면 안 되는 것은 같지만, 교량 일반도의 측면도는 구간 배정표(assigner)를 겸한다 — 경간 분할 · 교각 위치 · 형고 변화 · 받침 표고가 전부 거기 있다. 전력구에서 종단면이 하던 일을 교량에서는 측면도가 한다.

확인된 것과 확인 못 한 것 확인: 교량시종점 삽도의 측면도 6벌에 경간 분할(지간) · 신축유간 · 접속슬래브 · 말뚝 배치가 전부 있었다. 측면도가 배정 정보를 든다는 주장은 형태상 맞다.
확인 못 함: 그 측면도에 숫자 치수가 하나도 없다(기호 라벨뿐). 배정표로 쓸 수 있는지는 표기 치수가 있는 실제 일반도가 있어야 판정된다.
새로 드러난 것: 삽도에서는 측면도가 세 번째 역할을 한다 — 유형 카탈로그(TYPE1 반일체식 · TYPE2 단부슬래브 · TYPE3 일체식 · TYPE4 골조식). 같은 제목이 6벌 반복되는 원인이 이것이고, 그래서 제목 기반 뷰 분리가 깨졌다(3.4).

11.4 삽도(유형 도해)는 별도의 구조물 유형이다 검증

일반도와 삽도는 같은 파이프라인으로 다룰 수 없다. 표로 갈라둔다.

일반도 전력구 4매유형 삽도 교량 7장
치수숫자. 대조 가능기호(L·β·θ·VAR)가 섞인다. 도면마다 비율을 세어야 한다
뷰 제목유일 (단 면 B-B)없거나 N벌 중복
축척모델스페이스 1:1도형마다 다르다. 표기 치수 2개로 역산
표고 기준전 뷰 공통 계획고선없다. 뷰별 v0
윤곽닫힌 재료 영역구성 도해는 안 닫는다(띠·열린 외곽선)
레이어구조/치수/지반이 갈림표준 레이어 하나에 구조선과 치수선이 같이 올라간다
솔리드 대상전부일부만 — 7장 중 1장

11.4 실증 결과 — 교각 P9 한 부재를 끝까지 검증

이번엔 진짜 일반도였다 산외교_파이형_교각일반도(울산P9).dwg — 평면도 · 정면도 · 단면도 · 단면 A-A · 기초 평면도 · 교량받침 상세 · 솔플레이트 상세 + 표 3개가 좌표가 물린 채 한 도곽에 있다. 11장이 「교량 일반도에는 11.1~11.3이 그대로 남아 있다」고 유보해둔 그 조건이다. 부재 하나(교각)를 코핑→기둥→기초→말뚝→받침→문양 순으로 끝까지 밀었다.
파트 77 · 660.4154 m³ · 모델러 실측 대비 불일치 0건 · 열린 변 0
  코핑 1(intersect) · 원형기둥 2 · 확대기초 2 · 버림 2 · 강관말뚝 44
  받침콘크리트 6 · 모르타르 6 · 교좌받침 6 · 솔플레이트 6 · 미관문양 2

구체 콘크리트 fck=27MPa   359.3411      미관 문양            3.3585
기초 콘크리트 fck=27MPa   177.4500      받침콘크리트          1.8438
강관말뚝 Φ508.0×9T       108.7954      탄성받침             0.3469
버림 CON'C fck=15MPa       8.9780      무수축 모르타르        0.1555
                                       솔플레이트            0.1299

11.4.1 방법론 판정 — 「해봤다」가 아니라 참/거짓으로

방법론 주장교각에서근거
2.2 표고 기준은 전 뷰 공통거짓 → 그런데 되찾을 수 있다 공통 기준선이 없어 datum.mode:'none' 으로 시작했다. 그런데 받침 6기의 표 EL.'X' = 코핑상면 + h1 + h26기 모두 같은 절대표고 79.447을 낸다. 기준선이 없어도 표가 기준을 준다
3.4 제목으로 뷰를 가른다이나 안 썼다 제목이 있다(CZ-TEX1 h=700). 그런데 뷰끼리 치수선으로 이어져 있어 제목 그룹핑이 안 갈린다. 도곽 안 좌표(viewBoxes)로 짚었다
5.2 연산 결정 트리부족했다 intersect 가 트리에 없었다. 코핑은 「평면 윤곽 ∩ 정면 윤곽」이라 어느 한 방향 압출로도 안 나온다. 추가함
11.1 기준 체인 (받침 → 교각 로컬)참 · 처음 검증 받침배치도 「교량받침 좌표」의 절대 측량좌표 + 방위각으로 로컬 원점을 못 박았다. 역산 오차 원점 2 mm · 끝단 37 mm. IFC IfcMapConversion 으로 나간다
11.2 revolve 필요불필요 기둥이 Ø2,200 연직 원기둥이라 cylinder 로 그대로 선다. 회색 보조선(ci=8) 8줄이 원기둥 모선이라 각기둥이 아님을 재확인해준다
11.2 임의축 cylinder해당없음경사말뚝이 없다. 44본 전부 연직
11.0.5 「형상이 없어도 정보는 있다」참 · 메웠다 말뚝 44본이 CSPILEH INSERT 블록이다. 블록이 위치와 치수를 둘 다 준다 — scale 254 = 반지름, 도면 주기 Φ508.0X9T 와 일치. blocks() 를 만들었다

11.4.2 도면이 정보를 주는 방식 — 표가 추가됐다

부재도면이 주는 형태읽는 법현재
코핑·기둥·기초닫힌 윤곽폐곡선있다
기둥 단면CIRCLE지름으로 집는다있다
말뚝INSERT 블록삽입점 = 위치, 배율 = 치수있다blocks()
받침 적층·표고이름표로 표를 집고 열 이름으로 값을있다tables
미관 문양다른 의 윤곽뷰별 entityFilter있다
기둥 높이치수 텍스트 (형상은 파단)없다 — 텍스트 셀렉터
표는 형상만큼 중요한 입력이다 검증 받침 6기의 적층고(h1~h4) · 절대표고(EL.'X') · 교축 위치(S1/S2) · 솔플레이트(L·W·T·T1·T2)전부 표에만 있다. 정면도에 그려진 적층은 대표 하나고 기당 값이 다르다 (h1 = 168/195/197).
그래서 run.mjs 가 도면을 읽을 때 (이름표, 표) 쌍으로 색인해 out/<도면>.tables.json 에 얼려두고, fit()pick.tables열 이름으로 꺼낸다. 없는 표·없는 열이면 던진다.

11.4.3 세 갈래가 서로를 검산한다

형상 · 표 · 다른 도면이 같은 값을 서로 다른 길로 낸다. fit() 이 매번 확인하고 어긋나면 던진다.

대조결과
S1/S2 → 교축 위치 ↔ 평면도 폐곡선 중심6/6 ≤3 mm
h4 ↔ 솔플레이트 표 T6/6 완전일치
h1+h2+h3+h4 ↔ 표 E6/6
S1+S2 ↔ 코핑 교축폭 3,2006/6
솔플 T(T1+T2)/26/6
솔플 경사쪽 판정: T2−T1=16 ↔ 전/후열 총고차 29 ÷ 1,600 × L 840 = 15.2가정 없이 유도됐다
파단 생략량: 표고 텍스트 · 치수 8.816/10.916 · 기둥 도형길이 6,100세 갈래 모두 27,700
단위: 도곽 A1×100 · 블록 scale 254 ↔ Φ508 · 격자 1,300 ↔ 4@1.300 · 받침배치도 A1×300넷 다 1단위 = 1 mm

11.4.4 파단선 — 이 도면 유형의 최대 함정 검증

그려진 길이가 실제가 아니다. 그리고 숫자로는 안 걸린다 정면도의 기둥은 6,100 으로 그려져 있는데 실제는 33,800 이다. 폐곡선도 멀쩡히 나오고 부피도 그럴듯하게 나온다 — 24 m 를 잃은 채로.
신호는 CS-CUTL 레이어다. 가로 파단선(정면도·단면도 같은 y)과 말뚝마다의 파단 원호(R=655.6 ×45)가 거기 있다.
대응 — 생략량을 손으로 적지 않는다. 파단_생략량 = 기둥_높이 − 기둥_도형길이derived 가 된다. (기둥_높이는 치수 텍스트라 아직 design 이다)

11.4.5 코어에 새로 들어간 것

무엇왜 필요했나일반성
intersect 연산코핑 = 평면 윤곽 ∩ 정면 윤곽. 한 방향 압출로는 안 나온다「두 방향이 동시에 맞아야 하는 형상」 전부
extrude.drift (빗각 기둥)단면이 평행이동만 하는 전이부. Loft 를 못 쓰기 때문테이퍼 코핑·확폭부
blocks() 셀렉터말뚝이 INSERT 블록. 배율이 곧 치수다블록으로만 그린 부재 전부
표 추출 (core/table.mjs)받침 적층·표고가 표에만 있다모든 DWG. 격자·이름표·병합셀 자동
뷰별 entityFilter미관 문양이 본체와 다른 색이다「뷰마다 무엇이 구조선인가가 다르다」
dropCollinear 중복점 제거매달린 변 왕복이 길이 0 변을 남긴다전 도면
교집합 해석 부피격자로는 measure --ir 합격선 0.05 m³ 를 못 넘긴다압출∩압출 · 종단∩평면(높이 가변)
emit/ifc.mjsIFC 출력이 없었다IFC4 · 해석 솔리드 우선

11.4.6 Loft 는 boolean 에 못 쓴다 — 가장 비싼 발견 검증

부피는 맞는데 껍질이 안 붙는다 EGModeler 의 Loft 는 가이드상 서피스만 만든다. C=True 는 조용히 무시되고 Cap 을 덧대도 안 닫힌다 — 4각형 단면조차 열린 변 12개다.
발산 정리로 재는 부피는 정확히 맞으므로 부피 검사만으로는 절대 안 걸린다. 그런데 boolean 인자로 넣으면 샌다 — 코핑이 102.38 → 98.65 가 됐다.
대안Extrude C=True D F {기준점} {방향점} 는 자유방향을 받고 결과가 닫힌 솔리드다(정점 8·면 12·열린 변 0 확인). 단면이 평행이동만 하면 loft 대신 이것을 쓴다.
기존 모델 재검증 필요manhole1 이 loft 결과를 union·difference 인자로 쓴다.

11.4.7 새로 밟은 함정

증상원인대응
한 파일에 도형이 17벌 쌓여 있다도면집 스택. 제목·치수가 없는 잔재도곽 블록에서 상자를 계산한다 — CXBLKA1 INSERT 위치 × scale × A1(841×594)
「단면도」 안쪽 선을 다른 부재로 읽었다절단면이 아니라 투영이다. 먼 쪽 모서리가 겹쳐 보인다그 선의 치수가 외곽 − 2×R 로 떨어지면 투영이다 (3,200−2×500=2,200)
평면 모서리가 45° 모따기로 나온다파서가 LWPOLYLINE 의 bulges 를 버린다. 90° 호(bulge 0.41421)가 현 하나로 눌린다호 끝점은 정확하므로 R 은 되찾을 수 있다. 링 면적을 바로 쓰면 코너당 71,350 mm² 부푼다
평면 윤곽이 두 줄인데 하나만 썼다바깥 윤곽(Y±7,000)과 상면 단차선(Y±6,700)이 둘 다 R=500 필렛두 호의 중심 X 가 같으면 그 사이는 평면 띠다 → loft/빗각기둥
적분값이 0.2 m³ 샜다구간 끝점이 링 꼭짓점이라 스캔라인 교차 수가 어긋난다내부 노드 구적(가우스)을 쓴다. 심프슨은 끝점을 밟는다
구조 형상이 로 잡힌다평면도 격자가 73행×83열짜리 「표」가 된다표 색인에 레이어 필터(CS-TABL-*)를 준다
DIMENSION.actualMeasurement 로 단위를 정하면 틀린다주요 치수는 m 표기(8.816), 상세는 mm 표기(950). 표시값이 온다도곽 블록 배율·블록 scale·격자 간격으로 교차검증한다

11.4.8 IFC 출력

node src/emit/ifc.mjs out/pier-p9.ir.json   →  out/pier-p9.ifc  (IFC4, 170 KB)

IFCBEAM 1(코핑) · IFCCOLUMN 2 · IFCFOOTING 4 · IFCPILE 44
IFCPLATE 6(솔플레이트) · IFCDISCRETEACCESSORY 6(받침) · IFCBUILDINGELEMENTPROXY 14

해석 솔리드를 우선한다. 원기둥은 IfcCircleProfileDef 로 나가 진짜 원이다 — 메시로 내면 검증하는 쪽이 「왜 Ø508 이 아니냐」를 다시 겪는다. boolean 결과(코핑·문양 2)만 이미 검증된 IfcFacetedBrep 이다.

절대 위치는 IfcMapConversion 으로 준다. 모델은 로컬 원점에 두고 좌표를 3억 mm 로 부풀리지 않는다 — 뷰어가 정밀도를 잃는다.

IFC 파일을 다시 읽어 검증했다 내보낸 파일의 자체 형상(압출 74 + Brep 3)으로 부피를 다시 재서 660.4154 m³ = IR 총부피. 왕복이 닫힌다.

12미검증 영역 — 다음 도면에서 확인할 것

실증하며 채울 목록. 각 항목에 확인 방법예상 대응을 미리 적어뒀다.

항목확인 방법예상 대응
입면도 · 좌/우측면도 가설 해치 유무로 단면/투영을 가른다. 폐곡선을 뽑아 재료 영역이 아닌 것이 확인되는지 본다 role=validator로 고정. 3D 정투영 렌더와 윤곽 대조하는 경로를 만든다
flip 판정 가설 비대칭 특징 하나로 3.3 절차 적용 투상법을 설정값으로 두지 말고 도면에서 판정. 판정 결과를 앵커에 기록
DXF 입력 가설 같은 도면을 DXF로 받아 엔티티 목록이 동등한지 대조 변환 후 투입이 먼저. 상시 필요하면 DXF 리더를 parse.mjs 뒤에 붙인다 — 하류는 그대로
공통 datum이 없는 도면 검증 뷰별 검출 기준선 y가 서로 다른가 실재했다 — 교량 삽도 7장 전부. datum:{mode:'none'} + 뷰별 anchors.v0로 해결. 예상 대응 ①이 그대로 맞았다. 다만 G2의 교차검증이 같이 사라져 검증이 G3로 밀린다(2.2).
예상 못 한 것: 「기준선이 없다」가 예외로 드러나지 않는다. 계획고 라벨이 있는 도면 (횡단경사)에서 검출기가 그럴듯한 틀린 y를 돌려줬다 — 서로 다른 두 표고 라벨이 같은 답을 냈다. 라벨 무리 검사를 넣어 던지게 고쳤다
다중 시트 가설 · 축척 혼재 검증 좌표 분포가 여러 덩어리인가. 같은 부재의 치수가 뷰마다 배수 관계인가 다중 시트는 여전히 미확인(빈 시트 테두리만 봤다). 축척 혼재는 실재. 교량폭원 1:1 · 중앙분리대 방호벽 5.805배. viewBoxes[뷰].unitMm으로 해결 — 예상대로 「뷰별 축척 계수를 앵커에」가 맞았다. 추가로 드러난 것: DWG 모델단위 자체가 도면군마다 다르다(1m vs 1mm). 이건 예상 목록에 없었고 core에 상수로 박혀 있었다
원호·곡면 구조 부분 ARC/ELLIPSE 엔티티 비중을 센다 비중 측정됨: 거더배치 17% · 교량시종점 11% · 교대배치 8% · 횡단경사 1% · 나머지 0%. 세는 것만으로는 부족했다 — 비중이 큰 도면들은 ARC 이전에 치수(기호)에서 먼저 막혔다. 선분 근사는 아직 안 했다
곡선 선형 · 구배 가설 종단이 직선 from/to로 표현되는가 IR이 측점(station)을 다뤄야 한다. sweep 연산 추가
제목 없는 뷰 검증 표제 귀속에 실패하는 조각이 남는가 실재했다. 교량폭원은 제목이 아예 없고(조각 1개 → 뷰 0개 · orphan 1,810선), 나머지는 제목이 N벌 중복이다(중복률 47~84%). 「절단 기호 좌표로 역귀속」은 못 썼다 — 절단 기호 자체가 없는 도면이었다. cfg.viewBoxes(위치 기반 수동 매핑)가 실제 해법이었다. 예상 대응 중 fallback 쪽만 맞았다
교량 도면 부분 상부공이 직선 from/to로 표현되는가. 하부공 도면이 받침 좌표·표고로 기술돼 있는가 7장 중 1장(중앙분리대)만 끝까지 통과 — 4.8058 m³, 모델러·해석 일치. 상세는 11.0. 상부공·하부공 질문은 답을 못 얻었다(표기 치수가 있는 일반도가 없었다). 실제로 막은 것은 연산이 아니라 입력 해석이었다 — 단위 · 제목 · 축척 · 레이어 · 폐곡선 버그. 11.2의 예측(sweep·revolve·경사 말뚝)은 하나도 병목이 아니었다
유형 삽도(도해) 검증 신규 치수가 숫자인가 기호인가를 세어본다. 구조 윤곽이 닫히는가 일반도와 다른 유형으로 갈라 다룬다(11.4). 기호 치수뿐이거나 윤곽이 안 닫히면 솔리드 대상이 아니다 — 게이트로 밀어넣기 전에 걸러낸다
DWG 모델단위 혼재 검증 신규 DIMENSION.actualMeasurement와 치수 글자를 비교한다 cfg.unitMm. 상수로 두면 두 번째 도면군에서 모든 값이 1000배로 조용히 틀린다 — 폐곡선도 부피도 정상적으로 나오기 때문에 알아채기 어렵다
건축 도면 가설 datum이 FL, 앵커가 그리드 통심선으로 바뀌는가 규칙 층을 부재 종류별로 분리(벽·슬래브·보). 그리드는 datum의 X·Y 확장
IFC 출력 가설 partifcClass 추가 후 왕복 civil 계열 엔티티명은 스키마 직접 확인. 열린 변(T 정점) 처리 방침 결정
수평 단면 기반 층 스택 부분 층별 XY 프로파일을 Z로 쌓았을 때 union 손실이 사라지는가 조각이 Z로 진짜 겹치게 만든다. 평면 헌치가 자동으로 따라온다

12.1 실증할 때 기록할 것

13용어·필드 사전

13.1 뷰 스펙

필드
plane이 뷰가 그리는 평면. XY · XZ · YZ
u0가로축 원점. 프로젝트 = u − u0
v0세로축 원점. 수직 단면은 생략(표고가 이미 기준)
flip / flipV축 방향이 반대. 뒤집기 홀수면 링 감김을 되돌린다
swapUV도면 가로축이 프로젝트 Y, 세로축이 X (수평 단면)
rolegenerator · assigner · locator · validator (3.2)

13.2 도면 조회 도우미 — fit()만 쓴다

도우미용도실패 시
loop(뷰, 폭, 높이)그 치수의 폐곡선0개·2개 이상이면 예외. 자기교차면 예외
circles(뷰, 지름, 레이어)원(관통·기둥). u→v 정렬없으면 예외 + 있는 목록 제시
opening(뷰, 폭, 높이)개구 기호에서 되찾은 개구부0개·2개 이상이면 예외
rect(u0,v0,u1,v1)직사각 프로파일— 값은 반드시 다른 뷰의 실측치
expect(뷰, 폭, 높이, 이유)실재 확인만. rect 교차검증용없으면 예외

13.3 등급·출처

src: measured / design / derived도면에서 뽑음 / 사람이 정함 / 식으로 나옴
grade: exact / tolerant / opaque파라미터로 완전 재현 / ±ε / 재현 불가 → 좌표째 동결
kind: topology / design규칙 종류 — 막는다 / 경고한다
keep: falseboolean에 소모될 중간 파트. 최종 산출물에만 이름·색을 준다

이 문서의 위치docs/methodology.html. 절차는 docs/2d-3d-process.md, 사례별 교훈은 docs/2d-3d-conversion.md, 파라메트릭 설계 노트는 docs/parametric.md, 남은 일은 docs/roadmap.md.

개정 방침 — 새 도면을 실증할 때마다 12장의 항목을 검증 등급으로 승격시키고, 새로 밟은 함정을 8장에 3열로 추가한다. 표본 하나로 일반화한 자리를 표시해두는 것이 이 문서의 정직함이다.