- CAD 테마: 저장값이 없으면 부모 문서 테마(호스트 기본 밝음)를 따름 — 시스템 설정을 따라 CAD 만 어둡던 것 - 맞춤 뒤 화면을 안 옮겼으면 캔버스 크기가 바뀔 때 다시 맞춤 — 첫 표시 때 iframe 이 늦게 커져 어긋나던 것 · 빈 도면은 원점을 가운데로 - 도면 양식 📂 불러온 뒤 저장 안 하고 떠나면 물음 - 작도 영역 칸: 빈 칸 · 숫자 아님은 그 칸만 짚음 - 화면 검증용 창구에 기준점 · 보기 전용 상태 추가 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019qWfH6MMhLwjhtLYnDVUXv
91 lines
4.0 KiB
TypeScript
91 lines
4.0 KiB
TypeScript
/**
|
|
* 기준점 십자(좌표 0,0) 검증 — 확대해도 화면 크기 고정 · 원점에 붙음 · 도면 개체를 안 늘림.
|
|
* 실행: cd B07_DesignDetail/openwebcad && npx vitest run --config vitest.tmp.config.ts origin-marker
|
|
*/
|
|
import { Point } from '@flatten-js/core';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
import { ScreenCanvasDrawController } from '../../../B07_DesignDetail/openwebcad/src/drawControllers/screenCanvas.drawController';
|
|
import { drawOriginMarker } from '../../../B07_DesignDetail/openwebcad/src/helpers/draw-functions';
|
|
import { getEntities } from '../../../B07_DesignDetail/openwebcad/src/state';
|
|
|
|
// 자동색(theme.ts)이 `document` 의 data-theme 를 읽는다.
|
|
vi.stubGlobal('document', { documentElement: { getAttribute: () => 'dark' } });
|
|
|
|
/** moveTo·lineTo·arc 인자만 기록하는 최소 2d 컨텍스트 — 나머지 호출은 무시. */
|
|
function recordingContext() {
|
|
const segments: number[][] = [];
|
|
const arcs: number[][] = [];
|
|
let from: number[] = [];
|
|
const context = new Proxy(
|
|
{
|
|
lineWidth: 1,
|
|
moveTo: (x: number, y: number) => (from = [x, y]),
|
|
lineTo: (x: number, y: number) => segments.push([...from, x, y]),
|
|
arc: (x: number, y: number, r: number) => arcs.push([x, y, r]),
|
|
} as Record<string, unknown>,
|
|
{ get: (target, key: string) => target[key] ?? (() => undefined), set: () => true }
|
|
) as unknown as CanvasRenderingContext2D;
|
|
return { context, segments, arcs };
|
|
}
|
|
|
|
function drawAt(scale: number, offset: Point) {
|
|
const { context, segments, arcs } = recordingContext();
|
|
const controller = new ScreenCanvasDrawController(context);
|
|
controller.setCanvasSize(new Point(800, 600));
|
|
controller.setScreenScale(scale);
|
|
controller.setScreenOffset(offset);
|
|
drawOriginMarker(controller);
|
|
const origin = controller.worldToTarget(new Point(0, 0));
|
|
return { segments, arcs, origin };
|
|
}
|
|
|
|
describe('기준점 십자', () => {
|
|
it.each([0.01, 1, 40])('확대 %s 배에서도 가로세로 20px', (scale) => {
|
|
const { segments, arcs } = drawAt(scale, new Point(-120, 75));
|
|
expect(segments).toHaveLength(2);
|
|
const lengths = segments.map(([x1, y1, x2, y2]) => Math.hypot(x2 - x1, y2 - y1));
|
|
expect(lengths).toEqual([20, 20]);
|
|
// 끝점 둥글림(반지름 0.5)을 뺀 원 하나 — 작은 원
|
|
expect(arcs.filter(([, , r]) => r > 1).map(([, , r]) => r)).toEqual([10 / 3]);
|
|
});
|
|
|
|
it('십자 중심이 원점에 붙어 이동을 따라감', () => {
|
|
const a = drawAt(2, new Point(0, 0));
|
|
const b = drawAt(2, new Point(50, -30));
|
|
const center = ([x1, , x2]: number[]) => (x1 + x2) / 2;
|
|
expect(center(a.segments[0])).toBeCloseTo(a.origin.x);
|
|
expect(center(b.segments[0])).toBeCloseTo(b.origin.x);
|
|
expect(b.origin.x - a.origin.x).toBeCloseTo(-100); // 세계 50 = 화면 100px(2배) — 화면을 옮기면 원점이 반대로 감
|
|
});
|
|
|
|
it('빈 도면 맞춤은 원점을 화면 가운데로 — 십자가 귀퉁이에 안 잘림', () => {
|
|
const { context } = recordingContext();
|
|
const controller = new ScreenCanvasDrawController(context);
|
|
controller.setCanvasSize(new Point(800, 600));
|
|
controller.setScreenScale(2);
|
|
controller.setScreenOffset(new Point(0, 0));
|
|
controller.zoomToFitScreen();
|
|
const origin = controller.worldToTarget(new Point(0, 0));
|
|
expect([origin.x, origin.y]).toEqual([400, 300]);
|
|
});
|
|
|
|
it('맞춘 뒤 캔버스가 커지면 다시 맞춤 · 사용자가 옮긴 뒤에는 그대로', () => {
|
|
const { context } = recordingContext();
|
|
const controller = new ScreenCanvasDrawController(context);
|
|
controller.setCanvasSize(new Point(200, 100));
|
|
controller.zoomToFitScreen();
|
|
controller.setCanvasSize(new Point(800, 600));
|
|
const refit = controller.worldToTarget(new Point(0, 0));
|
|
expect([refit.x, refit.y]).toEqual([400, 300]);
|
|
controller.panScreen(50, 0);
|
|
controller.setCanvasSize(new Point(1000, 600));
|
|
const kept = controller.worldToTarget(new Point(0, 0));
|
|
expect([kept.x, kept.y]).toEqual([450, 300]);
|
|
});
|
|
|
|
it('그리기만 — 도면 개체를 만들지 않음', () => {
|
|
drawAt(1, new Point(0, 0));
|
|
expect(getEntities()).toHaveLength(0);
|
|
});
|
|
});
|