Files

13 KiB
Raw Permalink Blame History

Model / Layout (Paper) 뷰어 이슈 — 원인 분석 및 처리 이력

항목 내용
작성 목적 샘플에서 재현·수정한 이슈를 원본 hmwebviewer 에 이식하기 위한 기술 메모
샘플 dwg-dxf-viewer-sample
원본 hmwebviewer (src/viewer2d/ …)
주 재현 도면 C0060202-001-평면및종단면도(1)(대산방향STA.18+492.08-19+411.50).dwg
관련 도면 C0060203-*, BasicSample.dwg (회귀)
최종 정리 2026-07-29
상태 샘플 패치 완료 / 원본 뷰어 UI·Viewer2D 이식은 확인 후

제약

대상 정책
오픈소스 파서 본체 (acadrust 등 crates.io) 수정 금지 (unmodified 사용)
SORTENTSTABLE / 헤더 확장 export 파서 수정 없이 뷰어 규칙으로 대체
한글 인코딩 (CP949 mojibake) 별도 문서 korean-dwg-text-encoding.md본 문서와 독립, 둘 다 필요

0. 이슈 한눈에 보기

# 증상 원인 처리 (샘플) 수정 위치
1 글자·선이 한곳에 뒤섞여 겹침 Model + Paper 동시 렌더 공간 필터 + Model/Layout 탭 cadSpaces.ts, Viewer2D.js, main.ts, index.html
2 Layout에 도곽만 있고 평면/종단 비어 있음 VIEWPORT 미투영 Layout 시 Model을 VP 창에 투영·클립 Viewer2D.js
3 Fit / 좌표가 CAD와 다름, (0,0)에 없음 WCS 표시 + 이상치 bbox Model UCS 좌표 + 백분위 Fit Viewer2D.js
4 선형·종단에서 글자만 거대 minTextH = diag×0.0002 ≈ 250u min(diag×0.0002, medianHeight) Viewer2D.js
5 Layout에서 VP 내용이 도곽·주석 위 VP를 paper 뒤에 append VP 먼저 + z=-1 + underlay 텍스트 Viewer2D.js
6 커서 좌표 표시 우하단 X/Y (Model=UCS) #coords, screenToWorld

1. DWG 공간 개념 (배경)

공간 블록 이름 예 역할
Model Space *Model_Space 실좌표(측량 등) 본도면
Paper Space / Layout *Paper_Space, *Paper_Space0 출력 시트, 도곽, 주석, VIEWPORT
  • 엔티티 ownerHandle → 소속 블록 핸들.
  • Layout은 보통 VIEWPORT 로 Model 일부를 시트 좌표에 투영한다.
  • Model에는 원거리 이중 좌표가 흔함 (예: 원점 근처 종단 + X≈-436k 근처 선형).

재현 도면 규모 (C0060202-001, 참고)

Space handle (dec / hex) 엔티티 수 (대략) 좌표
*Model_Space 31 / 1f ~17,377 측량·다중 군집
*Paper_Space 210 / d2 ~200+ 시트 (~1.7e32.6e3)
VIEWPORT paper 소유 3 overall 1 + 종단·평면 창 2

2. 이슈 #1 — Model + Paper 동시 렌더

2.1 현상

다색 TEXT가 중앙에 뭉치고, 기하·주석이 읽기 불가.
CAD에서는 Layout 활성 시 정상 시트.

2.2 원인

기존 Viewer2D.load():

  1. *Model_Space / *Paper_Space 를 space 로 인식
  2. 사용자 블록 정의만 메인 루프에서 스킵 (INSERT 전개용)
  3. Model·Paper 둘 다 메인 루프에서 그림

→ 좌표계·스케일이 다른 두 공간을 한 씬에 합치고 fit() → 파국.

2.3 처리

파일 내용
src/viewer2d/cadSpaces.ts listCadSpaces, pickDefaultSpace, buildAllowedOwnerHexes
Viewer2D.js allowedOwners 필터, setSpace / getSpaces / getActiveSpace
main.ts + index.html Model / Layout 탭, 로드 시 기본 공간

기본 탭: Paper에 엔티티 있으면 Layout, 없으면 Model.

C0060202-001 → Layout
BasicSample (paper 0) → Model

3. 이슈 #2 — Layout이 비어 보임 (VIEWPORT)

3.1 현상

공간 분리 후 Layout은 도곽·주석만 있고, CAD처럼 평면·종단이 없음.

3.2 원인

  • Paper 엔티티만으로는 시트 장식/주석 수준.
  • 본도면은 Model에 있고, CAD는 VIEWPORT 로 비춤.
  • 뷰어가 Layout에서 Model을 VP에 투영하지 않으면 창이 비어 보임.

3.3 VIEWPORT 데이터

acadrust 타입에는 Viewport 가 있음.
뷰어는 parseResult 의 type: "VIEWPORT" 필드를 사용한다.

재현 도면 VP 예:

역할 size (대략) twist 비고
overall paper 시트 전체 0 스킵 (모델 창 아님)
종단 창 ~840×302 0 Model 투영
평면 창 ~840×215 ~1.28 rad Model 투영

overall 판별: id===1 또는 (scale≈1 ∧ viewTarget≈0 ∧ viewCenter≈paper center).

3.4 처리 (Viewer2D.js)

Layout 활성 시:

  1. (순서: 아래 이슈 #5) Model을 각 활성 VIEWPORT에 투영
  2. 변환 (2D / top, ODA·acadrust writer 규약):
DCS   = R(+twist) * (model  viewTarget)
paper = center + (paperHeight / viewHeight) * (DCS  viewCenter)
  1. paper 사각형 CohenSutherland 클리핑
  2. _isModelViewport / _viewportModelToPaper / _emitModelThroughViewport

3.5 파서 정책

  • acadrust(오픈소스 본체)는 수정하지 않는다.
  • VIEWPORT JSON 방출이 래퍼/기존 빌드에 이미 있으면 뷰어만 사용.
  • 추가 파서 기능(SORTENTS 등)은 넣지 않음 → 뷰어 규칙으로 충분.

4. 이슈 #3 — Zoom Fit

4.1 확정: 가시 엔티티 AABB

항목 내용
범위 활성 Model/Layout + 숨긴 레이어 제외, 렌더 시 expand
이상치 샘플 0.5%99.5% 로 극단 점 제거 → _contentBox
fit() _contentBox 우선 (씬 재계산보다 로드 시점과 동일)

4.2 가로로 매우 긴 Model (C0060202 / bb.dwg)

실측 기하(백분위 후) 대략:

WCS CAD UCS
~438000 ~-437000 … ~1000
높이 ~2900 ~-2950 … 0
종횡비 ~150:1

화면 비율(~2:1)로 classic contain 하면:

  • 세로 시야를 폭에 맞춰 키움 → 내용 높이가 화면의 ~1%
  • 수 픽셀 두께의 가로 선처럼 보임 (하늘색 박스도 상단에 얇은 선)

bb.dwg는 같은 종횡비의 단순 박스 2개라 식별 가능했고, 원본 1.7만 엔티티는 한 줄로 뭉개짐.

4.3 처리 (극단 스트립 Fit)

contentAspect = bw / bh
if contentAspect > screenAspect × 8:   // 매우 가로로 김
    vh = bh × pad          // Y를 화면에 채움
    vw = vh × screenAspect // 좌우는 잘라 보고 패닝
else if contentAspect < screenAspect / 8:
    // 매우 세로로 김 → 폭 채움
else:
    // 일반 contain

→ 선형/종단 구간이 세로로 화면에 채워짐. 전체 연장은 좌우 팬.

CAD status 참고 extents(Y ±10만)와 파서 실측(Y 약 3천)이 다를 수 있음 — Fit은 파서가 그린 가시 점 기준.


5. 이슈 #4 — 글자만 거대 (minTextH)

5.1 현상

선형(~-436802, -1949) 및 종단 근처에서 MOT/FLOW/수치가 등고선보다 훨씬 큼.

5.2 원인

항목 C0060202-001 Model
CAD TEXT height ~0.3 ~ 3.5 (중앙값 ~3, FLOW≈0.3)
전체 bbox 대각선 ~1.25×10⁶
minTextH = diag × 0.0002 ~250

_drawTextsMath.max(t.height, minTextH)모든 라벨이 높이 ~250 강제.

작은 시트 도면용 “fit 시 가독성” floor가 측량 Model에서 폭주한 것.

5.3 처리

minTextH = Math.min(diagSize * 0.0002, medianNativeHeight);
  • 측량 Model: floor ≤ median → 사실상 CAD 높이 유지
  • 작은 용지 좌표: diag floor가 작으면 기존과 유사

6. 이슈 #5 — Layout draw order (VIEWPORT가 위)

6.1 현상

VIEWPORT로 올린 Model 기하/라벨이 도곽·NOTE 위에 그려짐.

6.2 원인 (뷰어)

기존: paper 패스 후 VP 투영을 버퍼 뒤에 append → VP가 위.

6.3 DWG draw-order 메타 (참고만)

소스 의미 정책
SORTENTSTABLE / ACAD_SORTENTS sort handle 낮을수록 아래 acadrust에 타입 있음
Header SORTENTS 정렬 플래그
parseResult 엔티티 zOrder 등 없음

오픈소스 파서를 고치지 않으므로 SORTENTS export는 하지 않는다.
Layout 관례로 고정:

VIEWPORT 안 Model 내용 < Paper 주석·도곽

6.4 처리

  1. VP Model 투영을 paper 엔티티 루프보다 먼저 방출
  2. VP 선분 z = -1, paper z = 0 (카메라 +Z 기준 뒤/앞)
  3. 텍스트: underlay (VP) / 일반 (paper) 분리, renderOrder 0 → 1
  4. slug/스프라이트 배치도 underlay 먼저 추가

7. 커서 좌표 / Fit 좌표계 (UCS)

7.1 현상

  • Model에서 우하단 좌표로 (0,0) 근처를 찾아도 기하가 없음
  • Fit 후 표시 좌표가 CAD status bar 와 다름

7.2 원인

프레임 내용
기하 저장 (파서 WCS) 예: 선형 클러스터 ≈ (162065, 476725)
CAD Model UCS 원점 (vars.ucsOrigin) ≈ (598948, 478643)
CAD에 보이는 좌표 UCS = WCS ucsOrigin → 선형 ≈ (-436883, -1918)

뷰어가 WCS를 그대로 읽어 주면 CAD 사용자 좌표와 어긋난다.
또한 Fit bbox에 극단 이상치(수 점)가 포함되면 중심이 빈 공간으로 갈 수 있다.

CAD 참고 extents (Model, 사용자 측정):

X: -439601.13 … 4412.05
Y: -100418.91 … 99422.03

7.3 처리

  1. 좌표 표시 (Model): WCS → model UCS
    cad = project(WCS ucsOrigin) (축 단위 직교 시 subtract origin)
    Layout/Paper: identity (시트 좌표)
  2. Pick/measure: 내부 WCS (_screenToWcs)
  3. Fit: 가시 기하 0.5%99.5% 백분위 AABB (이상치 제거)
  4. 스크린→WCS: ortho frustum × camera right/up (view-twist 포함)

7.4 검증용 심플 도면 bb.dwg

Model 엔티티 5개 (사각형 2 + 연결 poly + hatch 2). ucsOrigin ≈ (598948, 478643).

덩어리 WCS (대략) CAD UCS (대략)
선형 쪽 박스 (161969…162448, 475696…476795) (-436979…-436500, -2947…-1848)
원점 쪽 박스 (598948…600030, 477765…478643) (0…1081, -878…0)UCS (0,0)에 모서리
Fit CAD 범위 X ≈ -436979…1081, Y ≈ -2947…0

확인 절차

  1. bb.dwg 열기 → Model 탭 (기본이 Layout이면 반드시 Model로)
  2. Fit → 우하단 좌표가 대략 위 UCS 범위 안
  3. 커서 오른쪽 박스 모서리 ≈ X=0, Y=0
  4. 왼쪽 박스 ≈ X=-436900, Y=-2400 부근

CAD WCS (0,0) 에는 기하가 없음. CAD status의 (0,0)은 UCS 원점이다.


8. 검증 체크리스트

확인 기대
C0060202-001 기본 탭 Layout
Layout 도곽 + 평면/종단 VP, 주석이 VP 위, 한글(인코딩 패치 병행)
Model ~17k 엔티티, 공간 필터로 paper 제외
Fit 현재 가시 전체 AABB (이중 좌표면 둘 다 포함)
Model 줌 인 선형/종단 글자 크기 ≈ CAD (거대 빌보드 없음)
BasicSample Model 기본, 회귀 없음
우하단 Model 커서 좌표 ≈ CAD UCS (선형 ~-436k 등)
Fit 후 중심 빈 (0,0) WCS 가 아닌 실제 기하 범위

9. 원본 hmwebviewer 이식 가이드

순서 작업
1 cadSpaces.ts 신규 복사
2 Viewer2D.js — 공간 필터, VP 투영, draw order, minTextH, fit/AABB, 좌표 API diff 이식 (통째 덮어쓰기 비권장)
3 Viewer2D.d.ts 동기화
4 호스트 UI: Model/Layout 탭, pickDefaultSpace + spaceHandle
5 (선택) 우하단 좌표 표시
6 fixDwgKoreanText한글 문서 대로 별도
7 C0060202-001 + BasicSample 회귀

하지 말 것

금지 이유
acadrust 등 오픈소스 파서 수정 정책
SORTENTS를 위해 파서 개조 뷰어 규칙으로 대체
Model+Paper 동시 렌더 복귀 이슈 #1 재발
밀도 기반 Fit 재도입 이슈 #3 에서 철회
minTextH = diag×0.0002 단독 이슈 #4 재발

10. 잔여 / 후속 (뷰어 측만)

  1. VIEWPORT 안 솔리드 HATCH/SOLID — 윤곽 위주 근사
  2. 다중 named Layout 탭 캡션 (블록명 *Paper_Space* 이상)
  3. TILEMODE/CTAB 을 파서 없이 알 수 없으면 현재 휴리스틱 유지
  4. 비직교 VIEWPORT (3D viewDirection)
  5. (선택) Model 이중 군집 점프 UI
  6. (선택) Fit “전체/선택” 분리는 요구 시만

11. 한 줄 요약

Model/Paper를 나눠 그리고, Layout은 VIEWPORT로 Model을 투영하되 paper 아래에 깐다.
Fit은 가시 엔티티 bbox. 글자 높이는 CAD median을 넘기지 않는다.
오픈소스 파서는 수정하지 않으며, draw-order는 Layout 관례로 처리한다.


12. 참고 파일 (샘플)

경로 역할
../src/viewer2d/cadSpaces.ts 공간 목록·기본 탭·owner 클로저
../src/viewer2d/Viewer2D.js 필터, VP 투영, draw order, minTextH, fit, 좌표
../src/viewer2d/Viewer2D.d.ts 타입
../src/main.ts 탭·좌표 UI 글루
../index.html #spaces, #coords
korean-dwg-text-encoding.md CP949 한글 깨짐 (병행 필수)