Files
Aislo/B07_DesignDetail/openwebcad/src/entities/Entity.ts
T
eomsangdonandClaude Opus 5 946d61f8df feat(B07): GROUP 묶음 JSON 저장·복원, 줌 로그 제거
- `groupId` 를 도면 JSON 에 실어 [저장] 뒤 다시 연 도면에서도 묶음 유지.
  엔티티 13종의 `toJson` 대신 직렬화 한 곳(export/import)에서 붙이고,
  복원은 순번이 아니라 id 로 — `compact` 가 null 을 걷어 index 가 어긋남.
- `setScreenScale` 의 매 호출 `console.log` 제거 — 줌·팬마다 콘솔을 덮었음.
- 검증: `group-id-roundtrip.test.ts` 신규, `npx vitest run` 87건 중 81 passed,
  실패 6건은 작업 전과 동일한 기존 결함. `npm run build` 통과.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-02 06:33:19 +09:00

94 lines
2.8 KiB
TypeScript

import type { Box, Point, Segment } from '@flatten-js/core';
import type { Shape, SnapPoint } from '../App.types';
import type { DrawController } from '../drawControllers/DrawController.ts';
import type { ArcJsonData } from './ArcEntity';
import type { ArrowHeadJsonData } from './ArrowHeadEntity.ts';
import type { CircleJsonData } from './CircleEntity';
import type { HatchJsonData } from './HatchEntity';
import type { ImageJsonData } from './ImageEntity';
import type { LineEntity, LineJsonData } from './LineEntity';
import type { PointJsonData } from './PointEntity';
import type { RectangleJsonData } from './RectangleEntity';
import type { TableJsonData } from './TableEntity.ts';
import type { TextJsonData } from './TextEntity.ts';
export interface Entity {
// Random uuid generated when the Entity is created
// Used for comparing entities
id: string;
lineColor: string;
lineWidth: number;
lineDash: number[] | undefined;
layerId: string;
/** 0~1 객체 투명도. 없으면 도면층 값을 따른다 */
opacity?: number;
/** GROUP으로 묶인 객체가 공유하는 식별자 */
groupId?: string;
draw(drawController: DrawController, highlighted?: boolean, selected?: boolean): void;
/**
* Translate an entity by x and y amount
* @param x
* @param y
*/
move(x: number, y: number): void;
scale(scaleOrigin: Point, scaleFactor: number): void;
rotate(rotateOrigin: Point, angle: number): void;
mirror(mirrorAxis: LineEntity): void;
clone(): Entity;
getBoundingBox(): Box;
intersectsWithBox(box: Box): boolean;
isContainedInBox(box: Box): boolean;
getBoundingBox(): Box;
getFirstPoint(): Point | null;
getShape(): Shape | null;
getSnapPoints(): SnapPoint[];
getIntersections(entity: Entity): Point[];
distanceTo(shape: Shape): [number, Segment] | null;
getSvgString(): string | null;
getType(): EntityName;
containsPointOnShape(point: Point): boolean;
toJson(): Promise<JsonEntity | null>;
// static fromJson(jsonEntity: JsonEntity): Promise<Entity | null>;
}
export enum EntityName {
Line = 'Line',
Circle = 'Circle',
Arc = 'Arc',
Rectangle = 'Rectangle',
Point = 'Point',
Image = 'Image',
Measurement = 'Measurement',
ArrowHead = 'ArrowHead',
Text = 'Text',
PolyLine = 'PolyLine',
Hatch = 'Hatch',
Table = 'Table',
}
export type ShapeJsonData =
| RectangleJsonData
| CircleJsonData
| ArcJsonData
| LineJsonData
| PointJsonData
| ImageJsonData
| ArrowHeadJsonData
| HatchJsonData
| TableJsonData
| TextJsonData;
export interface JsonEntity<TShapeJsonData = ShapeJsonData> {
id: string;
type: EntityName;
lineColor: string;
lineWidth: number;
lineDash?: number[];
layerId: string;
/** GROUP 묶음 식별자 — 저장·복원에서 그대로 실어 나른다 */
groupId?: string;
shapeData: TShapeJsonData | null;
children?: JsonEntity<ShapeJsonData>[];
}