fix(B08·M02): 구조물 도면 처음 맞춤을 도각 기준으로 · 보조 회색 글자 대비 4.5 이상(73-7)
- CAD 화면맞춤 — 얹은 도각(m02-structure-frame)이 있으면 도각 전체에 맞춤(옛 DXF 도곽에 안 끌림) · 시험 추가 - B08 설명 줄 · 홍수량 보조 글 · 판정 글자와 진행 단계 머리의 프로젝트 이름 글자를 보조 글자 토큰으로 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MgChuAcyBqUkhHMTXomQC7
This commit is contained in:
+35
-1
@@ -1,5 +1,8 @@
|
||||
import { Point } from '@flatten-js/core';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { LineEntity } from '../entities/LineEntity';
|
||||
import type { Layer } from '../App.types';
|
||||
import { setEntities, setLayers } from '../state';
|
||||
import { ScreenCanvasDrawController } from './screenCanvas.drawController';
|
||||
|
||||
/** translate·drawImage 인자만 기록하는 최소 2d 컨텍스트. */
|
||||
@@ -37,3 +40,34 @@ describe('ScreenCanvasDrawController.drawImage', () => {
|
||||
expect(calls.rotate).toEqual([-0.5, 0.5]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ScreenCanvasDrawController.zoomToFitScreen', () => {
|
||||
beforeAll(() => {
|
||||
(globalThis as { window?: unknown }).window = { dispatchEvent: () => true };
|
||||
});
|
||||
const layer = (id: string, isLocked: boolean) =>
|
||||
({ id, name: id, isVisible: true, isLocked }) as unknown as Layer;
|
||||
|
||||
it('얹은 도각(m02-structure-frame)이 있으면 도각 전체에 맞춘다 — 도각 밖 먼 그림에 안 끌린다', () => {
|
||||
setLayers([layer('m02-structure-frame', true), layer('기본', false)]);
|
||||
setEntities(
|
||||
[
|
||||
new LineEntity('m02-structure-frame', new Point(0, 0), new Point(800, 600)),
|
||||
new LineEntity('기본', new Point(-8000, -8000), new Point(0, 0)),
|
||||
],
|
||||
false
|
||||
);
|
||||
const controller = new ScreenCanvasDrawController(recordingContext().context);
|
||||
controller.setCanvasSize(new Point(800, 600));
|
||||
controller.zoomToFitScreen();
|
||||
const scale = controller.getScreenScale();
|
||||
expect(scale).toBeCloseTo(0.9, 5); // 800×600 도각 → 캔버스 90 %
|
||||
for (const corner of [new Point(0, 0), new Point(800, 600)]) {
|
||||
const t = controller.worldToTarget(corner);
|
||||
expect(t.x).toBeGreaterThanOrEqual(0);
|
||||
expect(t.x).toBeLessThanOrEqual(800);
|
||||
expect(t.y).toBeGreaterThanOrEqual(0);
|
||||
expect(t.y).toBeLessThanOrEqual(600);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,6 +31,8 @@ const CANVAS_BACKGROUND_FALLBACK = '#111';
|
||||
*
|
||||
* To convert between the 2 coordinate systems, you need the screenOffset and screenScale
|
||||
*/
|
||||
/** M02 가 구조물 도면에 얹는 도각 층 — 서버 `STRUCTURE_FRAME_LAYER` 와 같음 */
|
||||
const STRUCTURE_FRAME_LAYER_ID = 'm02-structure-frame';
|
||||
// Batch-mode stroke decimation: skip chain segments shorter than this (screen px)
|
||||
const BATCH_LOD_PX = 0.5;
|
||||
// Batch-mode text smaller than this (screen px) is unreadable — skip drawing it
|
||||
@@ -150,8 +152,15 @@ export class ScreenCanvasDrawController implements DrawController {
|
||||
public zoomToFitScreen() {
|
||||
// 도각·원지반 같은 잠금 도면층은 빼고 설계 콘텐츠에만 맞춘다 (2026-08-31 사용자
|
||||
// 확정). 도각까지 넣으면 A1 한 장 전체가 잡혀 화면의 40%가 여백으로 간다.
|
||||
// 구조물 도면(M02·B08)은 얹은 도각(작도 틀)이 있으면 도각 전체에 맞춘다 — 옛 DXF 가 자기 도곽·
|
||||
// 표제 띠를 품어 범위가 크면 도각이 화면 밖으로 밀린다.
|
||||
const structureFrame = getEntities().filter((e) => e.layerId === STRUCTURE_FRAME_LAYER_ID);
|
||||
const pickable = getPickableEntities();
|
||||
const entities = pickable.length ? pickable : getEntities();
|
||||
const entities = structureFrame.length
|
||||
? structureFrame
|
||||
: pickable.length
|
||||
? pickable
|
||||
: getEntities();
|
||||
if (!entities.length) {
|
||||
// 빈 도면 — 원점(0,0)을 화면 가운데로. 안 옮기면 기준점 십자가 왼쪽 아래 귀퉁이에 잘린다.
|
||||
const canvasSize = this.getCanvasSize();
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
}
|
||||
|
||||
.b08-hydro__hint {
|
||||
color: var(--color-text-muted);
|
||||
color: var(--color-text-secondary);
|
||||
font-size: var(--text-caption);
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
|
||||
.b08-hydro__verdict {
|
||||
padding: var(--spacing-8) 0;
|
||||
color: var(--color-text-muted);
|
||||
color: var(--color-text-secondary);
|
||||
font-size: var(--text-body);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
gap: var(--spacing-16);
|
||||
}
|
||||
|
||||
.b08-quantity .ui-general-block__empty {
|
||||
color: var(--color-text-secondary); /* muted 는 밝은 테마에서 대비 3:1 — 4.5:1 로 */
|
||||
}
|
||||
|
||||
.b08-quantity__tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
max-width: 60%;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
color: var(--color-text-muted, var(--color-text));
|
||||
color: var(--color-text-secondary, var(--color-text));
|
||||
font-size: var(--text-body-sm);
|
||||
text-align: right;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
Reference in New Issue
Block a user