1
property: XmlIgnore
含义
[property: XmlIgnore] 是 CommunityToolkit.Mvvm 的特殊语法,用于在 [ObservableProperty] 自动生成的公共属性 上标记 [XmlIgnore],让它在 XML 序列化/反序列化时被跳过。
这些属性全部是 运行时临时状态,保存配方(Recipe/Job)时不应该持久化。否则下次加载配方时会出现"虚假的检测结果"------这就是在检测时能根据状态变化、但不会污染配方文件的关键机制。
[XmlIgnore] vs [property: XmlIgnore]
csharp
// 直接标注 --- 编译器自动推断目标是 property
[XmlIgnore]
public string Name { get; set; }
// 显式指定目标为 property --- 效果完全相同
[property: XmlIgnore]
public string Name { get; set; }
什么时候需要 property: 前缀?
当使用自动属性(auto-property)且需要将特性精确应用到编译器生成的幕后字段 或属性本身时:
csharp
// 要求序列化时忽略属性,但使用 [field: NonSerialized] 应用到字段级别
[field: NonSerialized]
[property: XmlIgnore]
public byte[] CachedData { get; set; }
[field: NonSerialized]→ 应用到编译器自动生成的<CachedData>k__BackingField[property: XmlIgnore]→ 应用到属性本身,让XmlSerializer跳过它
常见场景
[XmlIgnore] 通常用于标记那些不应该被 XML 序列化的属性,比如:
- 计算属性 / 派生值
- 运行时状态(如
IsSelected、CancellationToken) - 循环引用对象
- 大数据量缓存(图片、体数据等)
你写的代码:
csharp
[ObservableProperty]
[property: XmlIgnore]
private bool isFocused = false;
编译后实际会变成:
csharp
// 字段保留
private bool isFocused = false;
// 源码生成器自动生成了这个属性,XmlIgnore 贴在了这里
[XmlIgnore]
public bool IsFocused
{
get => isFocused;
set { ... }
}
如果去掉 property::
csharp
[ObservableProperty]
[XmlIgnore] // ← 没有 property:
private bool isFocused = false;
编译后变成:
csharp
// XmlIgnore 贴在了字段上,但字段是 private 的,不会被 XML 序列化用到 → 白写了
[XmlIgnore]
private bool isFocused = false;
// 生成的公开属性上没有 XmlIgnore → 会被序列化进去!
public bool IsFocused
{
get => isFocused;
set { ... }
}
所以 property: 的作用就是:
"这个 XmlIgnore 是给自动生成的公开属性用的,不是给字段用的"
就像寄快递要写对收件人------[XmlIgnore] 默认收件人是字段,[property: XmlIgnore] 收件人是属性。
打个比方。
你的 XRayShape 用 XML 保存/加载项目文件。假设保存时不加 [XmlIgnore]:
XML 保存出来的内容:
xml
<Shape>
<Name>R1</Name>
<X>100</X>
<Y>200</Y>
<Width>50</Width>
<Height>30</Height>
<IsFocused>true</IsFocused> ← 运行时状态也被存进去了
</XRayShape>
下次打开项目时,元件突然变成"检测中"状态,明明还没开始检测------这些运行时状态不应该被保存。
加了 [property: XmlIgnore] 之后:
xml
<XRayShape>
<ShapeName>R1</ShapeName>
<X>100</X>
<Y>200</Y>
<Width>50</Width>
<Height>30</Height>
<!-- IsFocused、IsDetecting 等运行时状态不会写进 XML -->
</XRayShape>
简单说:保存只存有用的数据,加载回来都是干净的初始状态,不会乱。
2
namespace a;
namespace a
{
public class Message
{
}
}
一样
3
1. Shape(形状)
PCB 上一切可检测的图形元素,是系统的最小操作单元。
Shape = 图形(能画出来) + 检测数据(能算出来)
2. 坐标
同一位置有两套坐标表达:
| 坐标类型 | 含义 | 类比 |
|---|---|---|
| 物理坐标 (StartX, EndX, mm) | PCB 上的真实位置 | 现实世界的位置 |
| 像素坐标 (PixelStartX, PixelEndX, px) | 图像上的位置 | 照片上的位置 |
通过 Matrix(变换矩阵)互相转换。
4. CT(计算机断层扫描)
用 X 光从不同角度拍摄,重建出物体内部的 3D 图像。
三个关键参数:
| 参数 | 含义 | 单位 |
|---|---|---|
| imgResn | 分辨率,每个像素代表多大 | mm/pixel |
| zoffset | Z 轴偏移,焦平面上下移动 | mm |
| 层数 | 重建多少层切片 | 层 |
imgResn 越小 → 放大倍率越高 → 看得越精细
zoffset 正 → 焦平面上移;负 → 焦平面下移
ZOffset 分析
ZOffset(Z轴偏移) 是 CT 重建中用于调整检测焦平面的核心参数,定义在以下位置:
作用机制
ZOffset 代表产品厚度方向的中心位置(mm),以此为基准向上下各展开 halfThickness,得到上下表面。所有检测的 Z 方向范围计算都基于这个偏移量来确定。
元件级 zoffset 与全局 ZOffset 的差值被换算为层偏移,用于调整背钻检测的基准层位置 (BaseZ)。
总结
| 参数 | 作用 |
|---|---|
ZOffset |
焦平面在 Z 轴上的位置(产品厚度中心) |
| 正值 | 焦平面上移 |
| 负值 | 焦平面下移 |
| 默认值 | 1.0mm |
当检测的焦平面与实际 PCB 物理平面存在偏差时(例如产品厚度不均匀、皮带高度变化等),通过调整 ZOffset 可以将重建的清晰层对齐到正确的检测位置,确保背钻残桩检测的精度。
FOD / DOD 与 ZOffset 的几何关系
定义
FOD DOD
┌─────────────────┬─────────────────┐
│ │ │
射线源 物体/PCB 探测器
(Tube) (焦平面/检测物) (FPD)
| 参数 | 全称 | 物理含义 |
|---|---|---|
| FOD | Focus--Object Distance | 射线源(Tube) 到 检测物的距离 |
| DOD | Detector--Object Distance | 检测物 到 探测器(FPD)的距离 |
两者由设备标定值(ResoInfo.FOD、ResoInfo.DOD)决定,通常每个分辨率下是一组固定值。
"保持 FOD、DOD 不变" 的含义
ZOffset 调整时所做的操作是:Tube 和 FPD 同步同向移动(比如整体上移 0.5mm),保证:
FOD' = FOD → tube 到物体的距离不变
DOD' = DOD → 物体到 fpd 的距离不变
即几何放大比 M = DOD / FOD 保持不变 → CT 重建的分辨率不受影响。动的只是焦平面(清晰层)在物理世界中的 Z 坐标。
为什么这样做
实际物理场景:
皮带导轨(Z) → PCB上表面 ─── 清晰层(期望) ─── PCB下表面
↑
这里就是 "焦平面"
如果焦平面偏了(比如 PCB 翘曲、皮带高低不平):
→ ZOffset 负值:整体下移 → 清晰层下移
→ ZOffset 正值:整体上移 → 清晰层上移
本质上,ZOffset 是一个虚拟平移:不改变 CT 几何投影关系(FOD/DOD 不动),只改变重建体积的 Z 轴参考零点,把清晰层对齐到正确的物理位置。