Files
Aislo/B07_DesignDetail/openwebcad/src/entities/Entity.ts
T
eomsangdonandClaude Opus 5 ea5ce92725 feat(B07): 표를 객체로 만들어 도면의 표가 진짜 표가 되게 한다
표가 DXF의 표로 나가야 한다(사용자 확정). 지금까지 도면의 표는 선과 문자 뭉치라
내보낼 때 고를 수 있는 길이 하나뿐이었다.

- TableEntity: 열별 폭·행별 높이·칸 문자·병합을 한 객체가 들고 있다. 격자선은 담지
  않고 병합 자리에서 선을 끊는 규칙을 표가 스스로 안다(helpers/table-geometry.ts).
  회전·대칭은 지원하지 않는다 — 표는 축에 붙어 있다.
- 명령: TABLE을 표 객체 생성으로 다시 쓰고 TABLEEDIT(칸 문자)·TABLEROW·TABLECOL·
  TABLEMERGE·TABLEUNMERGE를 더했다. EXPLODE는 표를 선과 문자로 흩는다.
- 그립: 좌측 상단으로 표를 옮기고, 열·행 경계로 폭·높이를 바꾼다.
- 백엔드: 유역 정보표와 횡단 수량 산출표를 표 객체로 낸다. 횡단표는 머리행이 폭
  8등분, 본문이 11열 가중치로 격자가 서로 달라 두 경계를 합친 18열로 만들고 병합으로
  원래 칸을 되살렸다 — 손으로 하던 가로선 끊기가 사라졌다.
- 수량 역추출: 값 Text의 결정적 id로 읽던 것을 칸에 실은 key로 읽도록 옮겼다. 이미
  저장된 도면을 위해 옛 방식을 폴백으로 남겼다.

토적도·종단표는 값이 칸이 아니라 측점 위치에 놓이는 성격이라 이관하지 않았다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 15:12:19 +09:00

92 lines
2.7 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;
shapeData: TShapeJsonData | null;
children?: JsonEntity<ShapeJsonData>[];
}