1088 lines
25 KiB
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,
|
|
});
|
|
}
|