50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
/**
|
|
* 오토캐드 → 웹 CAD 붙여넣기 — 순수 부분.
|
|
* 오토캐드 기본 명령(WBLOCK · DXFOUT)으로 저장한 파일을 끌어다 놓거나 DXF 글을 Ctrl+V 하면,
|
|
* 서버(`/api/projects/dxf-clip` · `/file`)가 돌려준 JSON 을 여기서 현재 도면에 맞춘다.
|
|
* DOM · 상태를 안 만지는 것만 둔다(시험이 바로 부름) — 잇기는 `dxf-clip-paste.ts`.
|
|
*/
|
|
import type { Layer } from '../App.types.ts';
|
|
import type { JsonEntity } from '../entities/Entity';
|
|
|
|
/** DXF 글인가 — 그룹 코드 0 다음 줄이 SECTION 으로 시작(앞 공백 · CRLF 허용). */
|
|
export function isDxfText(text: string): boolean {
|
|
return /^\s*0\s*\r?\n\s*SECTION\b/.test(text);
|
|
}
|
|
|
|
export interface ClipLayer {
|
|
name: string;
|
|
color: string | null;
|
|
}
|
|
|
|
/**
|
|
* 서버 엔티티(layerId = DXF 도면층 이름)를 현재 도면에 붙일 모양으로 —
|
|
* 같은 이름 도면층이 있으면 그 층 · 없으면 새 층(DXF 층 색) · id 는 모두 새로(두 번 붙여도 안 겹침).
|
|
*/
|
|
export function prepareClip(
|
|
entities: JsonEntity[],
|
|
clipLayers: ClipLayer[],
|
|
existing: Layer[]
|
|
): { entities: JsonEntity[]; newLayers: Layer[] } {
|
|
const idByName = new Map(existing.map((layer) => [layer.name, layer.id]));
|
|
const newLayers: Layer[] = [];
|
|
const colorByName = new Map(clipLayers.map((layer) => [layer.name, layer.color]));
|
|
const layerIdOf = (name: string): string => {
|
|
let id = idByName.get(name);
|
|
if (!id) {
|
|
id = crypto.randomUUID();
|
|
idByName.set(name, id);
|
|
const color = colorByName.get(name);
|
|
newLayers.push({ id, name, isVisible: true, isLocked: false, ...(color ? { color } : {}) });
|
|
}
|
|
return id;
|
|
};
|
|
const renew = (entity: JsonEntity): JsonEntity => ({
|
|
...entity,
|
|
id: crypto.randomUUID(),
|
|
layerId: layerIdOf(String(entity.layerId ?? '0')),
|
|
...(entity.children ? { children: entity.children.map(renew) } : {}),
|
|
});
|
|
return { entities: entities.map(renew), newLayers };
|
|
}
|