diff --git a/docs/entity-selection-property-layer-ui.md b/docs/entity-selection-property-layer-ui.md new file mode 100644 index 0000000..8e95ffb --- /dev/null +++ b/docs/entity-selection-property-layer-ui.md @@ -0,0 +1,233 @@ +# Entity 선택, 속성 보기(Property Inspector), 레이어 관리(Layer Panel) & UI 패널 통합 가이드 + +이 문서는 DWG/DXF 뷰어 및 다른 2D/3D CAD 웹 뷰어 프로젝트에서 **엔티티 선택(Picking)**, **상세 속성 패널(Property Inspector)**, **레이어 관리 패널(Layer Panel)**, 그리고 **드래그·접기·리사이즈 가능한 UI 윈도우(Panel Utilities)**를 구축하고 이식하기 위한 통합 개발 및 재사용 가이드입니다. + +--- + +## 📌 1. 전체 아키텍처 & 모듈 구성 + +본 시스템은 뷰어 코어 엔진과 UI 구성요소가 완벽히 분리된 모듈형 구조로 설계되어 있어, 다른 Three.js/WebGL 기반 뷰어에도 손쉽게 이식할 수 있습니다. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Canvas Viewport (Viewer2D) │ +│ - Entity Raycasting & Pick Index (_pickSegs, _pickFills) │ +│ - Highlight & Accent recoloring (_highlight) │ +│ - Selected Entity Fit Camera (zoomToSelection) │ +│ - Layer Visibility & Info (getLayerInfo, setHiddenLayers) │ +└──────────────────────┬──────────────────────────────┬───────────────────────┘ + │ Event: onSelect(entity) │ Layer Info API + ▼ ▼ +┌────────────────────────────────────────┐ ┌──────────────────────────────────┐ +│ propertyInspector.ts │ │ layerPanel.ts │ +│ - formatEntityProperties() │ │ - LayerPanelManager class │ +│ - Entity Type Specific Geometry Math │ │ - Real-time Keyword Search │ +│ - Dynamic Property Card Rendering │ │ - Eye Toggle & Show/Hide All │ +└───────────────────┬────────────────────┘ └─────────────────┬────────────────┘ + │ │ + ▼ ▼ +┌─────────────────────────────────────────────────────────────────────────────┐ +│ panelUtils.ts │ +│ - makePanelDraggableAndCollapsible(panelEl, options) │ +│ - Header Mouse/Pointer Dragging & Screen Clamping │ +│ - Z-Index Top Focus Management │ +│ - Height Preservation Collapse / Expand Toggle │ +│ - CSS3 resize: both Integration │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 📑 2. 주요 모듈 명세 및 역할 + +| 모듈 파일 | 역할 및 제공 기능 | 비고 | +| :--- | :--- | :--- | +| **`src/viewer2d/Viewer2D.js`** | 렌더링 시 피킹 인덱스 구축, 레이캐스팅, 강조 표시, `zoomToSelection()` 카메라 핏팅 | 뷰어 코어 엔진 | +| **`src/propertyInspector.ts`** | 엔티티 유형(LINE, CIRCLE, ARC, POLYLINE, TEXT, INSERT 등)별 속성 추출 및 포맷팅, DOM 카드 렌더링 | 속성 패널 모듈 | +| **`src/layerPanel.ts`** | `LayerPanelManager` 클래스 - 검색 필터, 가시성 눈동자 토글, 전체 켜기/끄기, 색상/개수 표시 | 레이어 패널 모듈 | +| **`src/panelUtils.ts`** | `makePanelDraggableAndCollapsible` - 헤더 드래그, 화면 이탈 방지, z-index 최상단 전환, 접기/펼치기 | UI 패널 공통 유틸 | +| **`index.html` & `src/main.ts`** | 패널 HTML 구조, 글래스모피즘 CSS 스타일, 메인 이벤트 바인딩 | 애플리케이션 글루 | + +--- + +## 🔍 3. 핵심 기능별 상세 구현 원리 + +### 3.1 Entity 선택 (Picking) & Zoom to Selection + +1. **픽 데이터 수집 (Render Time)** + - 렌더링 시 각 엔티티의 실선 선분은 `_pickSegs` (`[ax, ay, bx, by, ...]`) 배열에 추가하고, owner 엔티티 메타 인덱스는 `_pickSegMeta`에 기록합니다. + - 해치(HATCH), 솔리드(SOLID), 텍스트(TEXT) 박스 등 면적을 가진 도형은 `_pickFills` (`{ metaIdx, loops }`) 배열에 추가합니다. + +2. **히트 테스트 및 선택 (`_onClick`)** + - 캔버스 클릭 시 브라우저 좌표를 월드 WCS 좌표로 변환 (`screenToWorld`). + - 클릭 지점으로부터 화면 픽셀 임계값(`CLICK_THRESHOLD_PX`) 이내에 있는 가장 가까운 선분을 우선 탐색합니다 (`_segDist`). + - 선분이 없을 경우 면적 도형 내부인지 다각형 포함 테스트(`_fillHit`)를 수행하여 엔티티 메타데이터를 결정합니다. + - `_highlight(meta)`를 통해 이전 선택 객체 색상을 복원하고 새 선택 객체의 Vertex Color를 선택 강조색(`_selColor`)으로 변경합니다. + - `onSelect(cb)` 콜백을 발생시켜 선택된 `entity` 객체를 외부 UI로 전달합니다. + +3. **선택 객체로 Zoom (`zoomToSelection()`)** + ```typescript + zoomToSelection() { + if (!this._selMeta) return; + const idx = this._entityMeta.indexOf(this._selMeta); + if (idx < 0) return; + const box = new THREE.Box3(); + + // 선택된 메타 인덱스의 선분 및 꽉 찬 루프 좌표로 Box3 확장 + for (let i = 0, j = 0; i < S.length; i += 4, j++) { + if (SM[j] === idx) { + box.expandByPoint(new THREE.Vector3(S[i], S[i + 1], 0)); + box.expandByPoint(new THREE.Vector3(S[i + 2], S[i + 3], 0)); + } + } + if (!box.isEmpty()) this._fit(box); + } + ``` + +--- + +### 3.2 속성 보기 모듈 (`propertyInspector.ts`) + +엔티티의 DXF/DWG 데이터 속성을 사용자가 읽기 편한 일반 정보(General)와 기하학적 정보(Geometry)로 분류하여 직관적으로 렌더링합니다. + +#### 주요 엔티티별 계산 속성: +- **`LINE`**: 시작점, 끝점, $\Delta X, \Delta Y$, 길이 ($L = \sqrt{\Delta x^2 + \Delta y^2}$), 각도 ($\theta = \text{atan2}(\Delta y, \Delta x)$) +- **`CIRCLE`**: 중심점, 반지름 ($r$), 지름 ($2r$), 둘레 ($2\pi r$), 넓이 ($\pi r^2$) +- **`ARC`**: 중심점, 반지름, 시작/끝 각도, 중심각 ($\Delta \theta$), 호 길이 ($r \cdot \Delta \theta$) +- **`LWPOLYLINE` / `POLYLINE`**: 정점 개수, 닫힘 여부, 총 세그먼트 길이, 면적 (Shoelace 공식을 이용한 $A = \frac{1}{2} |\sum (x_i y_{i+1} - x_{i+1} y_i)|$) +- **`TEXT` / `MTEXT`**: 텍스트 내용, 높이, 회전각, 정렬, 삽입점 +- **`INSERT` (블록)**: 블록 이름, 삽입점, 축척 ($S_x, S_y, S_z$), 회전각 + +--- + +### 3.3 레이어 관리 모듈 (`layerPanel.ts`) + +`LayerPanelManager` 클래스는 `Viewer2D`의 레이어 테이블 데이터와 동기화되어 다음 기능을 수행합니다: + +1. **실시간 키워드 필터링**: + ```typescript + const filtered = layers.filter(l => l.name.toLowerCase().includes(this.searchQuery)); + ``` +2. **레이어 숨김/표시 제어**: + ```typescript + public toggleLayer(name: string): void { + if (this.hiddenLayers.has(name)) this.hiddenLayers.delete(name); + else this.hiddenLayers.add(name); + this.viewer.setHiddenLayers(this.hiddenLayers); + this.render(); + } + ``` +3. **일괄 동작**: `showAllLayers()` 및 `hideAllLayers()` 지원. + +--- + +### 3.4 UI 패널 드래그 · 접기 · 크기 조절 모듈 (`panelUtils.ts`) + +모든 플로팅 UI 패널에 자유로운 **드래그 이동**, **접기/펼치기**, **크기 조절(Resize)**을 부여합니다. + +```typescript +export function makePanelDraggableAndCollapsible( + panelEl: HTMLElement, + options?: PanelControlOptions +) +``` + +#### 동작 원리: +1. **드래그 이동 & 화면 클램핑**: + - 패널 헤더(`handleEl`) `pointerdown` 시 포인터 시작 좌표와 패널의 상대 위치를 기록합니다. + - 이동 시 `Math.max(10, Math.min(newLeft, maxLeft))`로 클램핑하여 패널이 화면 밖으로 이탈하지 않도록 조절합니다. + - 드래그 시 패널 클릭과 함께 `globalMaxZIndex`를 증가시켜 선택된 패널이 다른 창 위에 표시되도록 처리합니다. +2. **접기/펼치기 (Collapsible)**: + - 접기(`isCollapsed = true`) 시 원래 높이(`lastHeight`)를 저장하고 `height = 42px`로 변경 및 내용 영역(`bodyEl`)을 `display: none` 처리합니다. + - 펼침 시 저장해둔 `lastHeight`와 `display: flex`를 복원합니다. +3. **크기 조절 (Resizable)**: + - CSS `.cad-panel`에 `resize: both; overflow: hidden;`을 적용하여 우하단 리사이즈 핸들을 활성화합니다. + - `.cad-panel.collapsed` 시에는 `resize: none !important;`를 적용하여 접힘 상태 시 리사이즈를 차단합니다. + +--- + +## 🎨 4. CSS 패널 스타일링 가이드 (`index.html`) + +다른 프로젝트 이식 시 필요한 공통 패널 스타일 정의: + +```css +/* 공통 패널 윈도우 스타일 (Properties & Layers - Draggable & Resizable) */ +.cad-panel { + position: fixed; + top: 56px; + width: 320px; + height: 480px; + min-width: 250px; + min-height: 140px; + max-width: 90vw; + max-height: 90vh; + z-index: 15; + background: rgba(22, 27, 34, 0.96); + backdrop-filter: blur(12px); + border: 1px solid var(--line); + border-radius: 10px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5); + display: flex; + flex-direction: column; + overflow: hidden; + resize: both; + transition: border-color 0.15s; +} + +/* 패널 접힘 상태 */ +.cad-panel.collapsed { + height: 42px !important; + min-height: 42px !important; + max-height: 42px !important; + overflow: hidden !important; + resize: none !important; +} + +/* 드래그 핸들 헤더 */ +.cad-panel .hdr { + padding: 10px 14px; + border-bottom: 1px solid var(--line); + display: flex; + align-items: center; + justify-content: space-between; + background: rgba(13, 17, 23, 0.7); + position: sticky; + top: 0; + z-index: 5; + cursor: grab; + user-select: none; + flex-shrink: 0; +} +.cad-panel .hdr:active { + cursor: grabbing; +} +``` + +--- + +## 🚀 5. 다른 뷰어 프로젝트로의 이식 단계 (Migration Steps) + +1. **파일 복사**: + - `src/panelUtils.ts` + - `src/propertyInspector.ts` + - `src/layerPanel.ts` +2. **HTML 창 구조 추가**: + - `index.html`에 `.cad-panel` 클래스를 가진 `#properties` 및 `#layers` 요소 추가. +3. **타겟 뷰어 이벤트 바인딩 (`main.ts`)**: + ```typescript + import { makePanelDraggableAndCollapsible } from './panelUtils'; + import { renderPropertyInspector } from './propertyInspector'; + import { LayerPanelManager } from './layerPanel'; + + // 1. 패널 드래그/접기 적용 + makePanelDraggableAndCollapsible(document.getElementById('properties')!); + makePanelDraggableAndCollapsible(document.getElementById('layers')!); + + // 2. 레이어 매니저 바인딩 + const layerManager = new LayerPanelManager(viewer, document.getElementById('layerList')!); + + // 3. 엔티티 선택 바인딩 + viewer.onSelect((entity) => { + renderPropertyInspector(document.getElementById('propBody')!, entity); + }); + ``` diff --git a/docs/modules-dwg-dxf.html b/docs/modules-dwg-dxf.html index 8b1951e..e6a5323 100644 --- a/docs/modules-dwg-dxf.html +++ b/docs/modules-dwg-dxf.html @@ -197,8 +197,27 @@
isDwg / isDxf / is2D — 의존 zero.+ 📖 엔티티 선택 & UI 패널 통합 가이드: docs/entity-selection-property-layer-ui.md 참조 +
+