fix(526-1): B07 횡단 장 인쇄 칸선 지움 · 칸마다 안내선 · 처음 맞춤 작도 영역까지
- 횡단 장 칸 격자선(도각 층 인쇄 개체) 지움 — 칸은 화면 안내선 겹판(guide.cells · 단면마다 점선) · 안내선 숨기기에 함께 꺼짐 · 넘친 칸 붉은 틀은 그대로 - 옛 확정 · 저장본 장은 열 때 칸선만 걷고 칸 안내선은 지금 배치로(refresh_saved_sheet) - CAD 처음 맞춤 · 전체 맞춤 = 내용 + 작도 영역(가이드) — 표준 횡단도가 내용에만 확대돼 도면 한 장 안 자리가 안 보이던 흠 - 낡은 시험 고침: test_169 칸선 단언 → 칸선 없음 + 칸 안내선 · test_212_3 「남는 검은 선 = 인쇄 칸선 지우지 않음」(212-3 결정) → 요구 343-4 로 칸선 지움 · guide-area 시험 칸 그리기 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,9 +26,22 @@ export const setFitMinHeight = (value: unknown): void => {
|
||||
fitMinHeight = typeof value === 'number' && value > 0 ? value : 0;
|
||||
};
|
||||
|
||||
/** 개체 범위를 화면 가운데에 놓는 배율 · 화면 원점(월드 좌표) */
|
||||
export function fitView(entities: Entity[], canvasSize: Point): { zoom: number; offset: Point } {
|
||||
/**
|
||||
* 개체 범위를 화면 가운데에 놓는 배율 · 화면 원점(월드 좌표).
|
||||
* `include` = 범위에 더할 [왼 x, 아래 y, 오른 x, 위 y] — 작도 영역(526-1 · 작은 그림이 칸 크기로 과확대되지 않게)
|
||||
*/
|
||||
export function fitView(
|
||||
entities: Entity[],
|
||||
canvasSize: Point,
|
||||
include?: readonly [number, number, number, number]
|
||||
): { zoom: number; offset: Point } {
|
||||
const boundingBox = { ...getBoundingBoxOfMultipleEntities(entities) };
|
||||
if (include) {
|
||||
boundingBox.minX = Math.min(boundingBox.minX, include[0]);
|
||||
boundingBox.minY = Math.min(boundingBox.minY, include[1]);
|
||||
boundingBox.maxX = Math.max(boundingBox.maxX, include[2]);
|
||||
boundingBox.maxY = Math.max(boundingBox.maxY, include[3]);
|
||||
}
|
||||
// 글 몇 줄뿐인 도면이 칸 높이로 과확대되지 않게 — 범위를 위 끝에서 아래로 최소 높이까지 늘림
|
||||
boundingBox.minY = Math.min(boundingBox.minY, boundingBox.maxY - fitMinHeight);
|
||||
const boundingWidth = boundingBox.maxX - boundingBox.minX;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getGridEnabled, triggerReactUpdate } from '../state.ts';
|
||||
import { paintColor, themeColor } from '../theme.ts';
|
||||
import { DEFAULT_TEXT_OPTIONS, type DrawController } from './DrawController';
|
||||
import { fitEntities, fitView } from './fit-view.ts';
|
||||
import { getGuide } from '../integration/guide-area.ts';
|
||||
|
||||
/** 토큰을 못 읽을 때만 쓰는 캔버스 배경 폴백. */
|
||||
const CANVAS_BACKGROUND_FALLBACK = '#111';
|
||||
@@ -157,7 +158,8 @@ export class ScreenCanvasDrawController implements DrawController {
|
||||
this.viewFitted = true;
|
||||
return;
|
||||
}
|
||||
const { zoom, offset } = fitView(entities, this.getCanvasSize());
|
||||
// 작도 영역(가이드)까지 — 그림이 작아도 도면 한 장 안 자리가 보이게(526-1)
|
||||
const { zoom, offset } = fitView(entities, this.getCanvasSize(), getGuide()?.area);
|
||||
this.setScreenScale(zoom);
|
||||
this.setScreenOffset(offset);
|
||||
this.viewFitted = true;
|
||||
|
||||
@@ -21,8 +21,21 @@ describe('작도 영역 가이드(169-1 · 169-3)', () => {
|
||||
expect(getGuide()).toBeNull();
|
||||
setGuideArea(AREA);
|
||||
expect(getGuide()).toBeNull();
|
||||
setGuide({ area: AREA, marks: [[0, 0, 1, 1], 'x'], editable: true });
|
||||
expect(getGuide()).toEqual({ area: AREA, marks: [[0, 0, 1, 1]], editable: true });
|
||||
setGuide({
|
||||
area: AREA,
|
||||
marks: [[0, 0, 1, 1], 'x'],
|
||||
cells: [
|
||||
[0, 0, 2, 2],
|
||||
[3, 3, 1, 1],
|
||||
],
|
||||
editable: true,
|
||||
});
|
||||
expect(getGuide()).toEqual({
|
||||
area: AREA,
|
||||
marks: [[0, 0, 1, 1]],
|
||||
cells: [[0, 0, 2, 2]],
|
||||
editable: true,
|
||||
});
|
||||
setGuideArea([0, 0, 100, 50]);
|
||||
expect(getGuide()?.area).toEqual([0, 0, 100, 50]);
|
||||
setGuide(null);
|
||||
@@ -54,12 +67,14 @@ describe('작도 영역 가이드(169-1 · 169-3)', () => {
|
||||
drawLineScreen: lines,
|
||||
fillRectScreen: vi.fn(),
|
||||
} as unknown as ScreenCanvasDrawController;
|
||||
const guide = { area: AREA, marks: [[0, 0, 5, 5] as GuideArea], editable: false };
|
||||
// 횡단 칸(526-1) 둘 — 단면마다 점선 4 변
|
||||
const cells = [[0, 0, 5, 5] as GuideArea, [5, 0, 10, 5] as GuideArea];
|
||||
const guide = { area: AREA, marks: [[0, 0, 5, 5] as GuideArea], cells, editable: false };
|
||||
|
||||
setGuide(guide);
|
||||
expect(isGuideVisible()).toBe(true); // 기본 = 보임
|
||||
drawGuide(controller);
|
||||
expect(lines).toHaveBeenCalledTimes(8); // 점선 영역 4 변 + 붉은 틀 4 변
|
||||
expect(lines).toHaveBeenCalledTimes(16); // 점선 영역 4 변 + 칸 2 × 4 변 + 붉은 틀 4 변
|
||||
|
||||
setGuideVisible(false);
|
||||
lines.mockClear();
|
||||
@@ -74,7 +89,7 @@ describe('작도 영역 가이드(169-1 · 169-3)', () => {
|
||||
|
||||
setGuideVisible(true);
|
||||
drawGuide(controller);
|
||||
expect(lines).toHaveBeenCalledTimes(8);
|
||||
expect(lines).toHaveBeenCalledTimes(16);
|
||||
setGuideVisible('x'); // 어긋난 값 = 보임
|
||||
expect(isGuideVisible()).toBe(true);
|
||||
setGuide(null);
|
||||
|
||||
@@ -18,6 +18,8 @@ export interface Guide {
|
||||
area: GuideArea;
|
||||
/** 넘친 칸(169-2) — 붉은 사각형으로 짚음 */
|
||||
marks?: GuideArea[];
|
||||
/** 횡단 장 칸(526-1) — 단면마다 점선 사각형(인쇄 칸선 대신) */
|
||||
cells?: GuideArea[];
|
||||
/** 끌어서 고칠 수 있나 — 도각 편집 · M02 양식만 */
|
||||
editable?: boolean;
|
||||
}
|
||||
@@ -60,6 +62,7 @@ export function setGuide(next: unknown): void {
|
||||
? {
|
||||
area: [...candidate.area] as GuideArea,
|
||||
marks: (candidate.marks ?? []).filter(isArea),
|
||||
cells: (candidate.cells ?? []).filter(isArea),
|
||||
editable: candidate.editable === true,
|
||||
}
|
||||
: null;
|
||||
@@ -129,6 +132,8 @@ export function drawGuide(drawController: ScreenCanvasDrawController): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
drawController.setLineStyles(false, false, GUIDE_COLOR, 1, [4, 4]);
|
||||
for (const cell of guide.cells ?? []) strokeRect(drawController, cell);
|
||||
drawController.setLineStyles(false, false, MARK_COLOR, 2, []);
|
||||
for (const mark of guide.marks ?? []) strokeRect(drawController, mark);
|
||||
drawController.setOpacity(1);
|
||||
|
||||
Reference in New Issue
Block a user