mobile-eda/lib/domain/models/core_models.dart

1088 lines
25 KiB
Dart

/**
* EDA 引擎核心数据模型 - Dart 版本
*
* 基于 TypeScript core-models.ts 移植
* 用于移动端 Flutter 应用
*
* @version 0.2.0
* @date 2026-03-07
*/
// ============================================================================
// 基础类型
// ============================================================================
/// 坐标 (单位:纳米 nm)
typedef Coordinate = int;
/// 唯一标识符
typedef ID = String;
/// 旋转角度
typedef Rotation = int; // 0, 90, 180, 270
/// 时间戳 (毫秒)
typedef Timestamp = int;
// ============================================================================
// 枚举类型
// ============================================================================
/// 层类型
enum LayerType {
signal,
power,
silkscreen,
solderMask,
paste
}
/// 镜像状态
enum MirrorState {
none,
top,
bottom
}
/// 元件类型
enum ComponentType {
resistor,
capacitor,
inductor,
diode,
transistor,
ic,
connector,
custom
}
/// 引脚电气类型
enum PinElectricalType {
passive,
input,
output,
power,
ground,
bidirectional
}
/// 网络类型
enum NetType {
signal,
power,
ground,
differential,
bus
}
/// 连接类型
enum ConnectionType {
pin,
via,
wireEnd
}
/// 操作类型 (撤销/重做)
enum OperationType {
componentAdd,
componentMove,
componentRotate,
componentDelete,
netAdd,
netConnect,
netDelete,
traceAdd,
traceDelete,
viaAdd,
propertyChange
}
/// 焊盘形状
enum PadShape {
rect,
circle,
oval,
custom
}
/// 走线形状
enum TraceShape {
line,
arc,
curve
}
// ============================================================================
// 通用接口
// ============================================================================
/// 元数据
class Metadata {
final Timestamp createdAt;
final Timestamp updatedAt;
final String? createdBy;
final List<String>? tags;
Metadata({
required this.createdAt,
required this.updatedAt,
this.createdBy,
this.tags,
});
Metadata copyWith({
Timestamp? createdAt,
Timestamp? updatedAt,
String? createdBy,
List<String>? tags,
}) {
return Metadata(
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
createdBy: createdBy ?? this.createdBy,
tags: tags ?? this.tags,
);
}
}
/// 二维位置
class Position2D {
final Coordinate x;
final Coordinate y;
const Position2D({required this.x, required this.y});
Position2D copyWith({Coordinate? x, Coordinate? y}) {
return Position2D(
x: x ?? this.x,
y: y ?? this.y,
);
}
@override
String toString() => 'Position2D(x: $x, y: $y)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is Position2D && other.x == x && other.y == y;
}
@override
int get hashCode => x.hashCode ^ y.hashCode;
}
// ============================================================================
// 元件相关
// ============================================================================
/// 引脚引用
class PinReference {
final ID pinId;
final String name;
final Coordinate x;
final Coordinate y;
final Rotation rotation;
final PinElectricalType electricalType;
PinReference({
required this.pinId,
required this.name,
required this.x,
required this.y,
required this.rotation,
required this.electricalType,
});
PinReference copyWith({
ID? pinId,
String? name,
Coordinate? x,
Coordinate? y,
Rotation? rotation,
PinElectricalType? electricalType,
}) {
return PinReference(
pinId: pinId ?? this.pinId,
name: name ?? this.name,
x: x ?? this.x,
y: y ?? this.y,
rotation: rotation ?? this.rotation,
electricalType: electricalType ?? this.electricalType,
);
}
}
/// 元件
class Component {
final ID id;
final String name;
final ComponentType type;
final String? value;
final Footprint footprint;
final Position2D position;
final ID layerId;
final Rotation rotation;
final MirrorState mirror;
final List<PinReference> pins;
final String? manufacturer;
final String? partNumber;
final String? description;
final Map<String, String>? customAttributes;
final Metadata metadata;
Component({
required this.id,
required this.name,
required this.type,
this.value,
required this.footprint,
required this.position,
required this.layerId,
this.rotation = 0,
this.mirror = MirrorState.none,
required this.pins,
this.manufacturer,
this.partNumber,
this.description,
this.customAttributes,
required this.metadata,
});
Component copyWith({
ID? id,
String? name,
ComponentType? type,
String? value,
Footprint? footprint,
Position2D? position,
ID? layerId,
Rotation? rotation,
MirrorState? mirror,
List<PinReference>? pins,
String? manufacturer,
String? partNumber,
String? description,
Map<String, String>? customAttributes,
Metadata? metadata,
}) {
return Component(
id: id ?? this.id,
name: name ?? this.name,
type: type ?? this.type,
value: value ?? this.value,
footprint: footprint ?? this.footprint,
position: position ?? this.position,
layerId: layerId ?? this.layerId,
rotation: rotation ?? this.rotation,
mirror: mirror ?? this.mirror,
pins: pins ?? this.pins,
manufacturer: manufacturer ?? this.manufacturer,
partNumber: partNumber ?? this.partNumber,
description: description ?? this.description,
customAttributes: customAttributes ?? this.customAttributes,
metadata: metadata ?? this.metadata,
);
}
/// 获取引脚位置(考虑旋转和镜像)
Position2D getPinPosition(PinReference pin) {
// TODO: 实现旋转和镜像变换
return Position2D(
x: position.x + pin.x,
y: position.y + pin.y,
);
}
}
// ============================================================================
// 网络相关
// ============================================================================
/// 连接点
class ConnectionPoint {
final ID id;
final ConnectionType type;
final ID? componentId;
final ID? pinId;
final ID? viaId;
final Position2D? position;
final ID? layerId;
ConnectionPoint({
required this.id,
required this.type,
this.componentId,
this.pinId,
this.viaId,
this.position,
this.layerId,
});
ConnectionPoint copyWith({
ID? id,
ConnectionType? type,
ID? componentId,
ID? pinId,
ID? viaId,
Position2D? position,
ID? layerId,
}) {
return ConnectionPoint(
id: id ?? this.id,
type: type ?? this.type,
componentId: componentId ?? this.componentId,
pinId: pinId ?? this.pinId,
viaId: viaId ?? this.viaId,
position: position ?? this.position,
layerId: layerId ?? this.layerId,
);
}
}
/// 网络
class Net {
final ID id;
final String name;
final NetType type;
final List<ConnectionPoint> connections;
final double? voltage;
final double? current;
final double? impedance;
final bool isDifferential;
final ID? differentialPair;
final String? busName;
final Metadata metadata;
Net({
required this.id,
required this.name,
required this.type,
required this.connections,
this.voltage,
this.current,
this.impedance,
this.isDifferential = false,
this.differentialPair,
this.busName,
required this.metadata,
});
Net copyWith({
ID? id,
String? name,
NetType? type,
List<ConnectionPoint>? connections,
double? voltage,
double? current,
double? impedance,
bool? isDifferential,
ID? differentialPair,
String? busName,
Metadata? metadata,
}) {
return Net(
id: id ?? this.id,
name: name ?? this.name,
type: type ?? this.type,
connections: connections ?? this.connections,
voltage: voltage ?? this.voltage,
current: current ?? this.current,
impedance: impedance ?? this.impedance,
isDifferential: isDifferential ?? this.isDifferential,
differentialPair: differentialPair ?? this.differentialPair,
busName: busName ?? this.busName,
metadata: metadata ?? this.metadata,
);
}
}
// ============================================================================
// 层相关
// ============================================================================
/// 层
class Layer {
final ID id;
final String name;
final LayerType type;
final int stackupOrder;
final double? thickness;
final String? material;
final double? copperWeight;
final bool isVisible;
final bool isEnabled;
final String? color;
final List<ID> componentIds;
final List<ID> traceIds;
final List<ID> viaIds;
final List<ID> polygonIds;
final Metadata metadata;
Layer({
required this.id,
required this.name,
required this.type,
required this.stackupOrder,
this.thickness,
this.material,
this.copperWeight,
this.isVisible = true,
this.isEnabled = true,
this.color,
this.componentIds = const [],
this.traceIds = const [],
this.viaIds = const [],
this.polygonIds = const [],
required this.metadata,
});
Layer copyWith({
ID? id,
String? name,
LayerType? type,
int? stackupOrder,
double? thickness,
String? material,
double? copperWeight,
bool? isVisible,
bool? isEnabled,
String? color,
List<ID>? componentIds,
List<ID>? traceIds,
List<ID>? viaIds,
List<ID>? polygonIds,
Metadata? metadata,
}) {
return Layer(
id: id ?? this.id,
name: name ?? this.name,
type: type ?? this.type,
stackupOrder: stackupOrder ?? this.stackupOrder,
thickness: thickness ?? this.thickness,
material: material ?? this.material,
copperWeight: copperWeight ?? this.copperWeight,
isVisible: isVisible ?? this.isVisible,
isEnabled: isEnabled ?? this.isEnabled,
color: color ?? this.color,
componentIds: componentIds ?? this.componentIds,
traceIds: traceIds ?? this.traceIds,
viaIds: viaIds ?? this.viaIds,
polygonIds: polygonIds ?? this.polygonIds,
metadata: metadata ?? this.metadata,
);
}
}
// ============================================================================
// 封装相关
// ============================================================================
/// 焊盘
class Pad {
final ID id;
final String name;
final PadShape shape;
final Coordinate width;
final Coordinate height;
final Position2D position;
final List<ID> layerIds;
final double? drillDiameter;
final String? drillShape; // "circle" or "square"
Pad({
required this.id,
required this.name,
required this.shape,
required this.width,
required this.height,
required this.position,
required this.layerIds,
this.drillDiameter,
this.drillShape,
});
Pad copyWith({
ID? id,
String? name,
PadShape? shape,
Coordinate? width,
Coordinate? height,
Position2D? position,
List<ID>? layerIds,
double? drillDiameter,
String? drillShape,
}) {
return Pad(
id: id ?? this.id,
name: name ?? this.name,
shape: shape ?? this.shape,
width: width ?? this.width,
height: height ?? this.height,
position: position ?? this.position,
layerIds: layerIds ?? this.layerIds,
drillDiameter: drillDiameter ?? this.drillDiameter,
drillShape: drillShape ?? this.drillShape,
);
}
}
/// 线段
class Line {
final Position2D start;
final Position2D end;
final Coordinate width;
const Line({
required this.start,
required this.end,
required this.width,
});
Line copyWith({
Position2D? start,
Position2D? end,
Coordinate? width,
}) {
return Line(
start: start ?? this.start,
end: end ?? this.end,
width: width ?? this.width,
);
}
}
/// 圆弧
class Arc {
final Position2D center;
final Coordinate radius;
final double startAngle;
final double endAngle;
final Coordinate width;
const Arc({
required this.center,
required this.radius,
required this.startAngle,
required this.endAngle,
required this.width,
});
Arc copyWith({
Position2D? center,
Coordinate? radius,
double? startAngle,
double? endAngle,
Coordinate? width,
}) {
return Arc(
center: center ?? this.center,
radius: radius ?? this.radius,
startAngle: startAngle ?? this.startAngle,
endAngle: endAngle ?? this.endAngle,
width: width ?? this.width,
);
}
}
/// 文本
class Text {
final String content;
final Position2D position;
final Coordinate size;
final Rotation rotation;
final ID layerId;
const Text({
required this.content,
required this.position,
required this.size,
required this.rotation,
required this.layerId,
});
Text copyWith({
String? content,
Position2D? position,
Coordinate? size,
Rotation? rotation,
ID? layerId,
}) {
return Text(
content: content ?? this.content,
position: position ?? this.position,
size: size ?? this.size,
rotation: rotation ?? this.rotation,
layerId: layerId ?? this.layerId,
);
}
}
/// 封装
class Footprint {
final ID id;
final String name;
final String? description;
final List<Pad> pads;
final List<Line>? silkscreenLines;
final List<Arc>? silkscreenArcs;
final List<Text>? silkscreenTexts;
final String? model3DFormat; // "step", "stp", "obj"
final String? model3DPath;
final Metadata metadata;
Footprint({
required this.id,
required this.name,
this.description,
required this.pads,
this.silkscreenLines,
this.silkscreenArcs,
this.silkscreenTexts,
this.model3DFormat,
this.model3DPath,
required this.metadata,
});
Footprint copyWith({
ID? id,
String? name,
String? description,
List<Pad>? pads,
List<Line>? silkscreenLines,
List<Arc>? silkscreenArcs,
List<Text>? silkscreenTexts,
String? model3DFormat,
String? model3DPath,
Metadata? metadata,
}) {
return Footprint(
id: id ?? this.id,
name: name ?? this.name,
description: description ?? this.description,
pads: pads ?? this.pads,
silkscreenLines: silkscreenLines ?? this.silkscreenLines,
silkscreenArcs: silkscreenArcs ?? this.silkscreenArcs,
silkscreenTexts: silkscreenTexts ?? this.silkscreenTexts,
model3DFormat: model3DFormat ?? this.model3DFormat,
model3DPath: model3DPath ?? this.model3DPath,
metadata: metadata ?? this.metadata,
);
}
}
// ============================================================================
// 走线/过孔/铜皮相关
// ============================================================================
/// 走线
class Trace {
final ID id;
final ID netId;
final ID layerId;
final List<Position2D> points;
final Coordinate width;
final Metadata metadata;
Trace({
required this.id,
required this.netId,
required this.layerId,
required this.points,
required this.width,
required this.metadata,
});
Trace copyWith({
ID? id,
ID? netId,
ID? layerId,
List<Position2D>? points,
Coordinate? width,
Metadata? metadata,
}) {
return Trace(
id: id ?? this.id,
netId: netId ?? this.netId,
layerId: layerId ?? this.layerId,
points: points ?? this.points,
width: width ?? this.width,
metadata: metadata ?? this.metadata,
);
}
}
/// 过孔
class Via {
final ID id;
final ID netId;
final Position2D position;
final Coordinate drillDiameter;
final Coordinate outerDiameter;
final List<ID> layerIds;
final Metadata metadata;
Via({
required this.id,
required this.netId,
required this.position,
required this.drillDiameter,
required this.outerDiameter,
required this.layerIds,
required this.metadata,
});
Via copyWith({
ID? id,
ID? netId,
Position2D? position,
Coordinate? drillDiameter,
Coordinate? outerDiameter,
List<ID>? layerIds,
Metadata? metadata,
}) {
return Via(
id: id ?? this.id,
netId: netId ?? this.netId,
position: position ?? this.position,
drillDiameter: drillDiameter ?? this.drillDiameter,
outerDiameter: outerDiameter ?? this.outerDiameter,
layerIds: layerIds ?? this.layerIds,
metadata: metadata ?? this.metadata,
);
}
}
/// 铜皮
class Polygon {
final ID id;
final ID? netId;
final ID layerId;
final List<Position2D> vertices;
final List<List<Position2D>>? keepouts;
final Metadata metadata;
Polygon({
required this.id,
this.netId,
required this.layerId,
required this.vertices,
this.keepouts,
required this.metadata,
});
Polygon copyWith({
ID? id,
ID? netId,
ID? layerId,
List<Position2D>? vertices,
List<List<Position2D>>? keepouts,
Metadata? metadata,
}) {
return Polygon(
id: id ?? this.id,
netId: netId ?? this.netId,
layerId: layerId ?? this.layerId,
vertices: vertices ?? this.vertices,
keepouts: keepouts ?? this.keepouts,
metadata: metadata ?? this.metadata,
);
}
}
// ============================================================================
// 设计顶层结构
// ============================================================================
/// 操作记录
class Operation {
final ID id;
final OperationType type;
final Timestamp timestamp;
final Map<String, dynamic> data;
final Map<String, dynamic>? inverseData;
Operation({
required this.id,
required this.type,
required this.timestamp,
required this.data,
this.inverseData,
});
Operation copyWith({
ID? id,
OperationType? type,
Timestamp? timestamp,
Map<String, dynamic>? data,
Map<String, dynamic>? inverseData,
}) {
return Operation(
id: id ?? this.id,
type: type ?? this.type,
timestamp: timestamp ?? this.timestamp,
data: data ?? this.data,
inverseData: inverseData ?? this.inverseData,
);
}
}
/// 设计规则
class DesignRules {
final double minTraceWidth;
final double maxTraceWidth;
final double preferredTraceWidth;
final double minTraceSpacing;
final double preferredTraceSpacing;
final double minViaHoleSize;
final double maxViaHoleSize;
final double minViaDiameter;
final double maxViaDiameter;
final double componentToComponentClearance;
final double componentToEdgeClearance;
DesignRules({
this.minTraceWidth = 0.15,
this.maxTraceWidth = 10.0,
this.preferredTraceWidth = 0.2,
this.minTraceSpacing = 0.15,
this.preferredTraceSpacing = 0.2,
this.minViaHoleSize = 0.2,
this.maxViaHoleSize = 0.8,
this.minViaDiameter = 0.4,
this.maxViaDiameter = 1.0,
this.componentToComponentClearance = 0.2,
this.componentToEdgeClearance = 0.2,
});
DesignRules copyWith({
double? minTraceWidth,
double? maxTraceWidth,
double? preferredTraceWidth,
double? minTraceSpacing,
double? preferredTraceSpacing,
double? minViaHoleSize,
double? maxViaHoleSize,
double? minViaDiameter,
double? maxViaDiameter,
double? componentToComponentClearance,
double? componentToEdgeClearance,
}) {
return DesignRules(
minTraceWidth: minTraceWidth ?? this.minTraceWidth,
maxTraceWidth: maxTraceWidth ?? this.maxTraceWidth,
preferredTraceWidth: preferredTraceWidth ?? this.preferredTraceWidth,
minTraceSpacing: minTraceSpacing ?? this.minTraceSpacing,
preferredTraceSpacing: preferredTraceSpacing ?? this.preferredTraceSpacing,
minViaHoleSize: minViaHoleSize ?? this.minViaHoleSize,
maxViaHoleSize: maxViaHoleSize ?? this.maxViaHoleSize,
minViaDiameter: minViaDiameter ?? this.minViaDiameter,
maxViaDiameter: maxViaDiameter ?? this.maxViaDiameter,
componentToComponentClearance: componentToComponentClearance ?? this.componentToComponentClearance,
componentToEdgeClearance: componentToEdgeClearance ?? this.componentToEdgeClearance,
);
}
}
/// 设计
class Design {
final ID id;
final String name;
final String version;
final String? description;
final Coordinate boardWidth;
final Coordinate boardHeight;
final Position2D origin;
final String units; // "nm", "μm", "mm", "mil"
final Coordinate gridX;
final Coordinate gridY;
final Map<ID, Component> components;
final Map<ID, Net> nets;
final Map<ID, Layer> layers;
final Map<ID, Footprint> footprints;
final Map<ID, Trace> traces;
final Map<ID, Via> vias;
final Map<ID, Polygon> polygons;
final List<ID> stackupLayerIds;
final double totalThickness;
final DesignRules designRules;
final List<Operation> undoStack;
final List<Operation> redoStack;
final int maxUndoStackSize;
final Timestamp createdAt;
final Timestamp updatedAt;
final String? createdBy;
final Timestamp? lastSavedAt;
final bool isDirty;
Design({
required this.id,
required this.name,
this.version = '0.1.0',
this.description,
this.boardWidth = 100000000, // 100mm in nm
this.boardHeight = 100000000,
this.origin = const Position2D(x: 0, y: 0),
this.units = 'nm',
this.gridX = 1000000, // 1mm grid
this.gridY = 1000000,
this.components = const {},
this.nets = const {},
this.layers = const {},
this.footprints = const {},
this.traces = const {},
this.vias = const {},
this.polygons = const {},
this.stackupLayerIds = const [],
this.totalThickness = 1.6,
required this.designRules,
this.undoStack = const [],
this.redoStack = const [],
this.maxUndoStackSize = 100,
required this.createdAt,
required this.updatedAt,
this.createdBy,
this.lastSavedAt,
this.isDirty = false,
});
Design copyWith({
ID? id,
String? name,
String? version,
String? description,
Coordinate? boardWidth,
Coordinate? boardHeight,
Position2D? origin,
String? units,
Coordinate? gridX,
Coordinate? gridY,
Map<ID, Component>? components,
Map<ID, Net>? nets,
Map<ID, Layer>? layers,
Map<ID, Footprint>? footprints,
Map<ID, Trace>? traces,
Map<ID, Via>? vias,
Map<ID, Polygon>? polygons,
List<ID>? stackupLayerIds,
double? totalThickness,
DesignRules? designRules,
List<Operation>? undoStack,
List<Operation>? redoStack,
int? maxUndoStackSize,
Timestamp? createdAt,
Timestamp? updatedAt,
String? createdBy,
Timestamp? lastSavedAt,
bool? isDirty,
}) {
return Design(
id: id ?? this.id,
name: name ?? this.name,
version: version ?? this.version,
description: description ?? this.description,
boardWidth: boardWidth ?? this.boardWidth,
boardHeight: boardHeight ?? this.boardHeight,
origin: origin ?? this.origin,
units: units ?? this.units,
gridX: gridX ?? this.gridX,
gridY: gridY ?? this.gridY,
components: components ?? this.components,
nets: nets ?? this.nets,
layers: layers ?? this.layers,
footprints: footprints ?? this.footprints,
traces: traces ?? this.traces,
vias: vias ?? this.vias,
polygons: polygons ?? this.polygons,
stackupLayerIds: stackupLayerIds ?? this.stackupLayerIds,
totalThickness: totalThickness ?? this.totalThickness,
designRules: designRules ?? this.designRules,
undoStack: undoStack ?? this.undoStack,
redoStack: redoStack ?? this.redoStack,
maxUndoStackSize: maxUndoStackSize ?? this.maxUndoStackSize,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
createdBy: createdBy ?? this.createdBy,
lastSavedAt: lastSavedAt ?? this.lastSavedAt,
isDirty: isDirty ?? this.isDirty,
);
}
}
// ============================================================================
// 移动端优化配置
// ============================================================================
/// 懒加载配置
class LazyLoadingConfig {
final bool enabled;
final int viewportMargin;
final int maxLoadedComponents;
const LazyLoadingConfig({
this.enabled = true,
this.viewportMargin = 100,
this.maxLoadedComponents = 500,
});
}
/// 对象池配置
class ObjectPoolConfig {
final bool enabled;
final int componentPoolSize;
final int tracePoolSize;
final int viaPoolSize;
const ObjectPoolConfig({
this.enabled = true,
this.componentPoolSize = 100,
this.tracePoolSize = 200,
this.viaPoolSize = 50,
});
}
/// 数据分块配置
class ChunkingConfig {
final bool enabled;
final int chunkSize;
final int preloadChunks;
const ChunkingConfig({
this.enabled = true,
this.chunkSize = 100,
this.preloadChunks = 3,
});
}
/// 移动端优化配置
class MobileOptimizations {
final LazyLoadingConfig lazyLoading;
final ObjectPoolConfig objectPooling;
final ChunkingConfig chunking;
const MobileOptimizations({
required this.lazyLoading,
required this.objectPooling,
required this.chunking,
});
}