fix(B07): 배수유역도 메모리 부족 — 배경선 솎기 · 배열 캐시 · 해칭 선분 재사용
- 등고선·세류선: 종이 0.1 mm(펜 굵기) 아래 굴곡 점 제거 — 294,339점 → 약 95,600점 - 배경선 캐시: 파이썬 튜플 → numpy 배열 + 선마다 범위 · 도곽 밖 선은 자르기 전에 거름 · 투영 한 줄씩 묶어 처리 - HatchEntity: 경계·무늬가 그대로면 줌·이동 때 패턴 선분 다시 계산 안 함 - 검증_sub4 유역도: 응답 75 MB → 24 MB · 서버 최고 1,304 MB → 595 MB · 끝 489 MB → 288 MB - 브라우저: 전 = 힙 289 MB 넘다 페이지 죽음 · 후 = 최고 203 MB 열림 · 줌 20번 275~281 MB 고정 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013rJwJMVL4EE31y77TB11AP
This commit is contained in:
@@ -6,7 +6,7 @@ import { Box, Point, Polygon, Segment } from '@flatten-js/core';
|
||||
import type { Shape, SnapPoint } from '../App.types';
|
||||
import { SnapPointType } from '../App.types';
|
||||
import type { DrawController } from '../drawControllers/DrawController';
|
||||
import { hatchSpans } from '../helpers/geometry/hatch-lines';
|
||||
import { type Span, hatchSpans } from '../helpers/geometry/hatch-lines';
|
||||
import { getExportColor } from '../helpers/get-export-color';
|
||||
import { mirrorPointOverAxis } from '../helpers/mirror-point-over-axis';
|
||||
import { scalePoint } from '../helpers/scale-point';
|
||||
@@ -50,6 +50,8 @@ export class HatchEntity implements Entity {
|
||||
|
||||
private points: Point[];
|
||||
public options: HatchOptions;
|
||||
/** 패턴 선분 — 줌·이동마다 다시 그리므로 경계·무늬가 그대로면 지난 계산을 쓴다. */
|
||||
private spanCache?: { key: string; points: Point[]; spans: Span[] };
|
||||
|
||||
constructor(layerId: string, points: Point[], options?: Partial<HatchOptions>) {
|
||||
this.layerId = layerId;
|
||||
@@ -77,14 +79,8 @@ export class HatchEntity implements Entity {
|
||||
this.drawGradient(drawController);
|
||||
} else {
|
||||
drawController.setLineStyles(highlighted, selected, this.options.color, this.lineWidth);
|
||||
const angles =
|
||||
this.options.style === 'cross'
|
||||
? [this.options.angle, this.options.angle + Math.PI / 2]
|
||||
: [this.options.angle];
|
||||
for (const angle of angles) {
|
||||
for (const [start, end] of hatchSpans(this.points, angle, this.options.spacing)) {
|
||||
drawController.drawLine(start, end);
|
||||
}
|
||||
for (const [start, end] of this.patternSpans()) {
|
||||
drawController.drawLine(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +97,18 @@ export class HatchEntity implements Entity {
|
||||
}
|
||||
}
|
||||
|
||||
private patternSpans(): Span[] {
|
||||
const { style, angle, spacing } = this.options;
|
||||
const key = `${style}:${angle}:${spacing}`;
|
||||
if (this.spanCache?.points === this.points && this.spanCache.key === key) {
|
||||
return this.spanCache.spans;
|
||||
}
|
||||
const angles = style === 'cross' ? [angle, angle + Math.PI / 2] : [angle];
|
||||
const spans = angles.flatMap((value) => hatchSpans(this.points, value, spacing));
|
||||
this.spanCache = { key, points: this.points, spans };
|
||||
return spans;
|
||||
}
|
||||
|
||||
/** 그라데이션 — 촘촘한 스캔선의 색을 조금씩 바꿔 표현한다 */
|
||||
private drawGradient(drawController: DrawController): void {
|
||||
const box = this.getBoundingBox();
|
||||
|
||||
Reference in New Issue
Block a user