kcg-monitoring/frontend/src/utils/shipIconSvg.ts
htlee 242fdb8034 fix: 리플레이 IconLayer 전환 + 모델 배지 + correlation 동기화
- ScatterplotLayer → IconLayer (ship-triangle/gear-diamond SVG 정적 캐시)
- shipIconSvg.ts: MapLibre와 동일한 삼각형/마름모 SVG + mask 모드
- 선박 COG 회전 반영 (getAngle), 어구는 회전 없음
- 모델별 색상 배지 ScatterplotLayer 추가 (각 모델 offset)
- correlation 데이터 비동기 로드 후 store.updateCorrelation() 동기화
- CorrPosition에 cog 필드 추가 (세그먼트 방향 계산)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 08:08:39 +09:00

41 lines
1.5 KiB
TypeScript

/**
* deck.gl IconLayer용 SVG 아이콘 생성 유틸.
* MapLibre ship-triangle / gear-diamond 형태와 동일.
* Data URI로 캐싱하여 반복 생성 방지.
*/
const ICON_SIZE = 64;
/** 선박 삼각형 SVG (heading 0 = north, 위쪽 꼭짓점) */
function createShipTriangleSvg(): string {
const s = ICON_SIZE;
return `<svg xmlns="http://www.w3.org/2000/svg" width="${s}" height="${s}" viewBox="0 0 ${s} ${s}">
<polygon points="${s / 2},2 ${s * 0.12},${s - 2} ${s / 2},${s * 0.62} ${s * 0.88},${s - 2}" fill="white"/>
</svg>`;
}
/** 어구 마름모 SVG */
function createGearDiamondSvg(): string {
const s = ICON_SIZE;
return `<svg xmlns="http://www.w3.org/2000/svg" width="${s}" height="${s}" viewBox="0 0 ${s} ${s}">
<polygon points="${s / 2},4 ${s - 4},${s / 2} ${s / 2},${s - 4} 4,${s / 2}" fill="white"/>
</svg>`;
}
function svgToDataUri(svg: string): string {
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
}
// ── 정적 캐시 (모듈 로드 시 1회 생성) ──
const SHIP_TRIANGLE_URI = svgToDataUri(createShipTriangleSvg());
const GEAR_DIAMOND_URI = svgToDataUri(createGearDiamondSvg());
export const SHIP_ICON_MAPPING = {
'ship-triangle': { url: SHIP_TRIANGLE_URI, width: ICON_SIZE, height: ICON_SIZE, anchorY: ICON_SIZE * 0.62, mask: true },
'gear-diamond': { url: GEAR_DIAMOND_URI, width: ICON_SIZE, height: ICON_SIZE, anchorY: ICON_SIZE / 2, mask: true },
};
export const SHIP_ICON_ATLAS = SHIP_TRIANGLE_URI;
export const GEAR_ICON_ATLAS = GEAR_DIAMOND_URI;
export { ICON_SIZE };