反应器系统
大约 3 分钟
反应器系统
反应器系统允许实体响应其他"Owner"实体的变化,用于实现关联标注等功能。
IEntityReactor 接口
interface IEntityReactor {
id: string; // 反应器实体ID
// 获取关联的Owner实体ID列表
getOwnerIds(): string[];
// Owner变化时回调
onOwnerChanged(args: ReactorEventArgs): void;
// 标记需要更新
setReactorDirty(): void;
// 检查是否需要更新
isReactorDirty(): boolean;
// 从Owner更新自身
updateFromOwners(): void;
// 解除与所有Owner的关联
unlinkAllOwners(): void;
// 注册到文档
tryRegisterReactor(docId: string): void;
}ReactorEvent 类型
// 变化事件类型
enum ReactorEvent {
Modified = 'modified', // Owner被修改
Erased = 'erased', // Owner被删除
Copied = 'copied', // Owner被复制
Unlinked = 'unlinked' // Owner主动解除关联
}
// 事件参数
interface ReactorEventArgs {
event: ReactorEvent;
docId: string;
ownerId: string;
ownerEntity?: EntityBase;
timestamp: number;
}
// Owner引用信息
interface OwnerReference {
ownerId: string;
segmentIndex?: number; // 多段线段索引
pointType?: 'start' | 'end' | 'center'; // 点类型
parameterT?: number; // 曲线参数
meta?: Record<string, any>; // 额外元数据
}完整反应器实体示例
以下是一个关联圆心标记的完整实现:
import {
CustomEntityBase,
IEntityReactor,
ReactorEvent,
ReactorEventArgs,
OwnerReference,
EntityBase,
CircleEnt,
LineEnt,
Point2D,
Engine
} from 'vjcad';
// 判断是否为反应器实体
function isEntityReactor(entity: any): entity is IEntityReactor {
return entity && typeof entity.getOwnerIds === 'function';
}
// 关联圆心标记实体
class CircleCenterMark extends CustomEntityBase implements IEntityReactor {
readonly customType = 'CIRCLE_CENTER_MARK';
readonly customDisplayName = '圆心标记';
private _ownerId: string = '';
private _ownerRef: OwnerReference | null = null;
private _isDirty: boolean = false;
private _center: Point2D = new Point2D(0, 0);
private _markSize: number = 5;
// ===== IEntityReactor 实现 =====
getOwnerIds(): string[] {
return this._ownerId ? [this._ownerId] : [];
}
onOwnerChanged(args: ReactorEventArgs): void {
switch (args.event) {
case ReactorEvent.Modified:
// Owner被修改,标记为脏
this.setReactorDirty();
break;
case ReactorEvent.Erased:
// Owner被删除,解除关联
this._ownerId = '';
this._ownerRef = null;
break;
}
}
setReactorDirty(): void {
this._isDirty = true;
}
isReactorDirty(): boolean {
return this._isDirty;
}
updateFromOwners(): void {
if (!this._isDirty || !this._ownerId) return;
const doc = Engine.currentDoc;
const owner = doc.getEntityById(this._ownerId);
if (owner && owner.type === 'CIRCLE') {
const circle = owner as CircleEnt;
this._center = circle.center.clone();
this.setModified(); // 触发重绘
}
this._isDirty = false;
}
unlinkAllOwners(): void {
this._ownerId = '';
this._ownerRef = null;
}
tryRegisterReactor(docId: string): void {
if (this._ownerId) {
const reactorMgr = Engine.reactorManager;
reactorMgr.registerReactor(docId, this);
}
}
// ===== 关联方法 =====
linkToCircle(circle: CircleEnt): void {
this._ownerId = circle.id;
this._ownerRef = {
ownerId: circle.id,
pointType: 'center'
};
this._center = circle.center.clone();
// 注册到反应器管理器
this.tryRegisterReactor(Engine.currentDoc.docId);
this.setModified();
}
// ===== CustomEntityBase 实现 =====
getSnapPoints() {
return [{ point: this._center, type: 'center' }];
}
getGripPoints() {
return []; // 不可编辑
}
protected buildNestEnts(): EntityBase[] {
const entities: EntityBase[] = [];
const s = this._markSize;
// 十字标记
const hLine = new LineEnt(
new Point2D(this._center.x - s, this._center.y),
new Point2D(this._center.x + s, this._center.y)
);
const vLine = new LineEnt(
new Point2D(this._center.x, this._center.y - s),
new Point2D(this._center.x, this._center.y + s)
);
hLine.fromDefaultProps(this);
vLine.fromDefaultProps(this);
entities.push(hLine, vLine);
return entities;
}
clone(): CircleCenterMark {
const copy = new CircleCenterMark();
copy.fromDefaultProps(this);
copy._center = this._center.clone();
copy._markSize = this._markSize;
// 注意:克隆时不复制owner关联
return copy;
}
getEntityData() {
return {
ownerId: this._ownerId,
ownerRef: this._ownerRef,
center: this._center.toDb(),
markSize: this._markSize
};
}
setEntityData(data: any): void {
this._ownerId = data.ownerId || '';
this._ownerRef = data.ownerRef || null;
this._center = Point2D.fromDb(data.center);
this._markSize = data.markSize || 5;
}
}使用示例
// 创建圆
const circle = new CircleEnt(new Point2D(100, 100), 50);
circle.setDefaults();
Engine.pcanvas.addEntity(circle);
// 创建关联标记
const mark = new CircleCenterMark();
mark.setDefaults();
mark.linkToCircle(circle);
Engine.pcanvas.addEntity(mark);
// 当圆被移动时,标记会自动更新
circle.center = new Point2D(200, 200); // 标记自动跟随反应器管理器
import { Engine } from 'vjcad';
const reactorMgr = Engine.reactorManager;
// 注册反应器实体
reactorMgr.registerReactor(docId, reactorEntity);
// 注销反应器
reactorMgr.unregisterReactor(docId, reactorEntity.id);
// 通知Owner变化(系统自动调用)
reactorMgr.notifyOwnerChanged({
event: ReactorEvent.Modified,
docId: docId,
ownerId: circle.id,
ownerEntity: circle,
timestamp: Date.now()
});
// 批量更新所有脏反应器
reactorMgr.updateAllDirtyReactors(docId);应用场景
关联标注
尺寸标注关联到被标注的实体,当实体移动或修改时,标注自动更新。
约束系统
几何约束(如平行、垂直、相切等)通过反应器实现联动。
智能符号
如焊接符号、粗糙度符号等关联到指定边或点。