/** * 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? tags; Metadata({ required this.createdAt, required this.updatedAt, this.createdBy, this.tags, }); Metadata copyWith({ Timestamp? createdAt, Timestamp? updatedAt, String? createdBy, List? 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 pins; final String? manufacturer; final String? partNumber; final String? description; final Map? 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? pins, String? manufacturer, String? partNumber, String? description, Map? 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 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? 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 componentIds; final List traceIds; final List viaIds; final List 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? componentIds, List? traceIds, List? viaIds, List? 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 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? 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 pads; final List? silkscreenLines; final List? silkscreenArcs; final List? 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? pads, List? silkscreenLines, List? silkscreenArcs, List? 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 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? 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 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? 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 vertices; final List>? 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? vertices, List>? 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 data; final Map? 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? data, Map? 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 components; final Map nets; final Map layers; final Map footprints; final Map traces; final Map vias; final Map polygons; final List stackupLayerIds; final double totalThickness; final DesignRules designRules; final List undoStack; final List 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? components, Map? nets, Map? layers, Map? footprints, Map? traces, Map? vias, Map? polygons, List? stackupLayerIds, double? totalThickness, DesignRules? designRules, List? undoStack, List? 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, }); }