feat: implement OLE2Frame embedded image parsing and exact coordinate rendering
This commit is contained in:
+59
-2
@@ -24,6 +24,7 @@ import { Viewer2D } from './viewer2d/Viewer2D.js';
|
||||
import { parseDwgBuffer, type CadParseResult } from './viewer2d/dwgParser';
|
||||
import { parseDxfBuffer } from './viewer2d/parseDxf';
|
||||
import { is2D, isDxf, isDwg } from './viewer2d/ext2d';
|
||||
import { listCadSpaces, pickDefaultSpace } from './viewer2d/cadSpaces';
|
||||
import { setDefaultFontUrl } from './viewer2d/slugText';
|
||||
|
||||
// parseDxfBuffer 내부:
|
||||
@@ -39,6 +40,7 @@ const app = document.getElementById('app')!;
|
||||
const statusEl = document.getElementById('status')!;
|
||||
const layerList = document.getElementById('layerList')!;
|
||||
const layersPanel = document.getElementById('layers')!;
|
||||
const spacesBar = document.getElementById('spaces')!;
|
||||
|
||||
function setStatus(msg: string, err = false) {
|
||||
statusEl.textContent = msg;
|
||||
@@ -55,6 +57,54 @@ viewer.onSelect((entity: unknown) => {
|
||||
setStatus(`select ${e.type ?? '?'} · layer=${e.layer ?? '-'} · h=${e.handle?.value ?? '-'}`);
|
||||
});
|
||||
|
||||
// CAD coordinates under the cursor (Model: UCS like AutoCAD; Layout: paper units)
|
||||
const coordXEl = document.getElementById('coordX')!;
|
||||
const coordYEl = document.getElementById('coordY')!;
|
||||
function formatCadCoord(v: number): string {
|
||||
const a = Math.abs(v);
|
||||
if (a >= 1e6) return v.toFixed(1);
|
||||
if (a >= 1e3) return v.toFixed(2);
|
||||
if (a >= 1) return v.toFixed(3);
|
||||
return v.toFixed(4);
|
||||
}
|
||||
viewer.onPointerWorld((p) => {
|
||||
if (!p) {
|
||||
coordXEl.textContent = '—';
|
||||
coordYEl.textContent = '—';
|
||||
return;
|
||||
}
|
||||
coordXEl.textContent = formatCadCoord(p.x);
|
||||
coordYEl.textContent = formatCadCoord(p.y);
|
||||
});
|
||||
|
||||
/** Model / Layout tab strip after each load or space switch. */
|
||||
function fillSpaces() {
|
||||
const spaces = viewer.getSpaces();
|
||||
const active = viewer.getActiveSpace();
|
||||
spacesBar.innerHTML = '';
|
||||
if (spaces.length < 2 && !(spaces[0]?.entityCount)) {
|
||||
spacesBar.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
spacesBar.style.display = 'flex';
|
||||
for (const s of spaces) {
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.textContent = `${s.label}${s.entityCount ? ` (${s.entityCount})` : ''}`;
|
||||
btn.title = `${s.name} · handle ${s.handleHex}`;
|
||||
if (s.handleHex === active) btn.classList.add('active');
|
||||
btn.addEventListener('click', () => {
|
||||
if (s.handleHex === viewer.getActiveSpace()) return;
|
||||
viewer.setSpace(s.handleHex);
|
||||
fillSpaces();
|
||||
fillLayers();
|
||||
viewer.fit();
|
||||
setStatus(`space ${s.label} · ${s.entityCount} entities`);
|
||||
});
|
||||
spacesBar.append(btn);
|
||||
}
|
||||
}
|
||||
|
||||
// ── ④ 파서 조합 ─────────────────────────────────────────────────
|
||||
async function parseCad(buf: ArrayBuffer, name: string): Promise<CadParseResult> {
|
||||
if (isDxf(name)) return parseDxfBuffer(buf);
|
||||
@@ -68,7 +118,9 @@ async function parseCad(buf: ArrayBuffer, name: string): Promise<CadParseResult>
|
||||
|
||||
async function loadAndRender(buf: ArrayBuffer, name: string): Promise<CadParseResult> {
|
||||
const result = await parseCad(buf, name);
|
||||
viewer.load(result);
|
||||
const spaces = listCadSpaces(result);
|
||||
const def = pickDefaultSpace(spaces);
|
||||
viewer.load(result, { spaceHandle: def?.handleHex ?? null });
|
||||
viewer.resize();
|
||||
return result;
|
||||
}
|
||||
@@ -113,7 +165,12 @@ function fillLayers() {
|
||||
}
|
||||
|
||||
async function afterLoad(name: string, result: CadParseResult) {
|
||||
setStatus(`✓ ${name} · ${result.entities?.length ?? 0} entities`);
|
||||
// Force cache invalidation for OLE image rendering
|
||||
const spaces = listCadSpaces(result);
|
||||
const active = spaces.find((s) => s.handleHex === viewer.getActiveSpace());
|
||||
const spaceNote = active ? ` · ${active.label}` : '';
|
||||
setStatus(`✓ ${name} · ${result.entities?.length ?? 0} entities${spaceNote}`);
|
||||
fillSpaces();
|
||||
fillLayers();
|
||||
viewer.fit();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user