waferMap图像渲染

定义数据类

csharp 复制代码
    /// <summary>
    /// 晶圆地图数据
    /// </summary>
    public class WaferMapData
    {
        /// <summary>
        /// 行数
        /// </summary>
        public int Rows { get; set; }
        /// <summary>
        /// 列数
        /// </summary>
        public int Columns { get; set; }
        /// <summary>
        /// 数据
        /// </summary>
        public string[,] Matrix { get; set; }
    }

增加helper类

csharp 复制代码
/// <summary>
/// 晶圆地图帮助类
/// </summary>
public class WaferMapHelper
{
    /// <summary>
    /// 晶圆图数据解析
    /// </summary>
    /// <param name="lines">数据</param>
    /// <param name="datas">解析数组</param>
    /// <param name="isInterval">是否存在间隔</param>
    /// <param name="interval">间隔字符串</param>
    /// <returns></returns>
    public static WaferMapData Parse(string[] lines, Dictionary<string, string> datas, bool isInterval, string interval = " ")
    {
        int rows = 0, cols = 0;
        List<string[]> matrix = new List<string[]>();

        // 先按 key 长度倒序排列(先匹配长的,防止例如 "___" 和 "_" 冲突)
        var keys = datas.Keys.OrderByDescending(k => k.Length).ToList();

        foreach (var line in lines)
        {
            if (line.StartsWith("ROWCT:"))
                rows = int.Parse(line.Substring(6));
            else if (line.StartsWith("COLCT:"))
                cols = int.Parse(line.Substring(6));
            else if (line.StartsWith("RowData:"))
            {
                string raw = line.Substring(8).Trim();
                if (isInterval)
                {
                    raw = raw.Replace(interval, ""); // 如果是间隔分割,则移除间隔字符
                }

                List<string> rowData = new List<string>();
                int i = 0;
                while (i < raw.Length)
                {
                    bool matched = false;
                    foreach (var key in keys)
                    {
                        if (i + key.Length <= raw.Length && raw.Substring(i, key.Length) == key)
                        {
                            rowData.Add(key);
                            i += key.Length;
                            matched = true;
                            break;
                        }
                    }

                    if (!matched)
                    {
                        // 若没有匹配上任何 key,可选择跳过或抛异常,这里添加 '?' 占位
                        rowData.Add("?");
                        i += 1;
                    }
                }

                matrix.Add(rowData.ToArray());
            }
        }

        // 修正行列数
        if (rows != matrix.Count)
            rows = matrix.Count;

        if (matrix.Count > 0 && cols != matrix[0].Length)
            cols = matrix[0].Length;

        // 构建结果矩阵
        string[,] result = new string[rows, cols];
        for (int y = 0; y < rows; y++)
        {
            for (int x = 0; x < cols; x++)
            {
                var rawVal = matrix[y][x];
                result[y, x] = datas.TryGetValue(rawVal, out var mapped) ? mapped : "?";
            }
        }

        return new WaferMapData
        {
            Rows = rows,
            Columns = cols,
            Matrix = result
        };
    }

    /// <summary>
    /// 晶圆图渲染
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="dieColorMap">渲染颜色选择</param>
    /// <param name="dieSizeX">芯片X尺寸</param>
    /// <param name="dieSizeY">芯片Y尺寸</param>
    /// <param name="gridThickness">栅格尺寸 等于0则不显示栅格</param>
    /// <param name="gridColor">栅格颜色</param>
    /// <returns></returns>
    public static BitmapSource Render(WaferMapData data, Dictionary<string, Color> dieColorMap, int dieSizeX = 6, int dieSizeY = 6, int gridThickness = 1, Color? gridColor = null)
    {
        int width = data.Columns * dieSizeX;
        int height = data.Rows * dieSizeY;

        WriteableBitmap bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
        bitmap.Lock();

        unsafe
        {
            IntPtr pBackBuffer = bitmap.BackBuffer;
            int stride = bitmap.BackBufferStride;
            Color actualGridColor = gridColor ?? Colors.LightGray;

            for (int y = 0; y < data.Rows; y++)
            {
                for (int x = 0; x < data.Columns; x++)
                {
                    string value = data.Matrix[y, x];
                    Color fillColor = dieColorMap.TryGetValue(value, out var c) ? c : Colors.Gray;

                    for (int dy = 0; dy < dieSizeY; dy++)
                    {
                        for (int dx = 0; dx < dieSizeX; dx++)
                        {
                            int px = x * dieSizeX + dx;
                            int py = y * dieSizeY + dy;

                            // 当 gridThickness > 0 时才绘制边线
                            bool isGridLine = gridThickness > 0 &&
                                              (dx < gridThickness || dy < gridThickness);

                            Color color = isGridLine ? actualGridColor : fillColor;

                            int offset = py * stride + px * 4;
                            byte* pPixel = (byte*)pBackBuffer + offset;
                            pPixel[0] = color.B;
                            pPixel[1] = color.G;
                            pPixel[2] = color.R;
                            pPixel[3] = color.A;
                        }
                    }
                }
            }
        }

        bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
        bitmap.Unlock();
        return bitmap;
    }

    /// <summary>
    /// 修改晶圆图数据中指定位置的芯片状态
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="row">目标芯片的行索引(从0开始)</param>
    /// <param name="col">目标芯片的列索引(从0开始)</param>
    /// <param name="newStatus">新的状态字符</param>
    /// <returns>是否成功修改</returns>
    public static bool UpdateDieStatus(WaferMapData data, int row, int col, string newStatus)
    {
        if (row < 0 || row >= data.Rows || col < 0 || col >= data.Columns)
            return false;
        // 修改状态
        data.Matrix[row, col] = newStatus;
        return true;
    }

    /// <summary>
    /// 批量修改晶圆图数据中多个芯片的位置状态
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="changes">每项包含 (row, col, newStatus)</param>
    /// <returns>成功修改的个数</returns>
    public static int UpdateDieStatuses(WaferMapData data, IEnumerable<(int row, int col, string newStatus)> changes)
    {
        if (data == null || data.Matrix == null)
            return 0;

        int successCount = 0;

        foreach (var (row, col, newStatus) in changes)
        {
            if (row >= 0 && row < data.Rows && col >= 0 && col < data.Columns)
            {
                data.Matrix[row, col] = newStatus;
                successCount++;
            }
        }

        return successCount;
    }

    /// <summary>
    /// 保存晶圆图为 PNG 文件
    /// </summary>
    /// <param name="filePath">PNG 文件路径</param>
    /// <param name="bitmap">晶圆图数据</param>
    public static void SaveBitmapToPng(string filePath, BitmapSource bitmap)
    {
        FileStream stream = new FileStream(filePath, FileMode.Create);
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bitmap));
        encoder.Save(stream);
    }

    /// <summary>
    /// 保存晶圆图数据到文件
    /// </summary>
    /// <param name="filePath">文件路径</param>
    /// <param name="data">晶圆图数据</param>
    /// <param name="dieDatas">反解析数组</param>
    /// <param name="isInterval">是否保留间隔</param>
    /// <param name="interval">间隔字符串</param>
    public static void SaveWaferDataToFile(string filePath, WaferMapData data, Dictionary<string, string> dieDatas, bool isInterval, string interval = " ")
    {
        StreamWriter writer = new StreamWriter(filePath);

        writer.WriteLine($"ROWCT:{data.Rows}");
        writer.WriteLine($"COLCT:{data.Columns}");

        for (int y = 0; y < data.Rows; y++)
        {
            StringBuilder sb = new StringBuilder("RowData:");
            for (int x = 0; x < data.Columns; x++)
            {
                foreach (var kvp in dieDatas)
                {
                    if (data.Matrix[y, x] == kvp.Key)
                    {
                        sb.Append(kvp.Value);
                        break;
                    }
                }
                if (isInterval)
                {
                    sb.Append(interval);
                }
            }
            writer.WriteLine(sb.ToString().TrimEnd());
        }
    }

    /// <summary>
    /// 获取晶圆图中所有芯片状态的总数量
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <returns></returns>
    public static Dictionary<string, int> CountAllDieStatuses(WaferMapData data)
    {
        Dictionary<string, int> statusCounts = new Dictionary<string, int>();

        if (data == null || data.Matrix == null)
            return statusCounts;

        for (int y = 0; y < data.Rows; y++)
        {
            for (int x = 0; x < data.Columns; x++)
            {
                string value = data.Matrix[y, x];
                if (!statusCounts.ContainsKey(value))
                    statusCounts[value] = 0;
                statusCounts[value]++;
            }
        }

        return statusCounts;
    }

    /// <summary>
    /// 获取晶圆图中指定芯片状态的总数量
    /// </summary>
    /// <param name="data">晶圆图数据</param>
    /// <param name="targetStatus">要统计的目标状态(如 "001", "$$$", "X" 等)</param>
    /// <returns>该状态芯片的总数</returns>
    public static int CountDieStatus(WaferMapData data, string targetStatus)
    {
        if (data == null || data.Matrix == null)
            return 0;

        int count = 0;
        for (int y = 0; y < data.Rows; y++)
        {
            for (int x = 0; x < data.Columns; x++)
            {
                if (data.Matrix[y, x] == targetStatus)
                {
                    count++;
                }
            }
        }

        return count;
    }

    /// <summary>
    /// 统计指定行中某个芯片状态的数量
    /// </summary>
    public static int CountDieStatusInRow(WaferMapData data, int row, string targetStatus)
    {
        if (data == null || data.Matrix == null || row < 0 || row >= data.Rows)
            return 0;

        int count = 0;
        for (int x = 0; x < data.Columns; x++)
        {
            if (data.Matrix[row, x] == targetStatus)
                count++;
        }
        return count;
    }

    /// <summary>
    /// 统计指定列中某个芯片状态的数量
    /// </summary>
    public static int CountDieStatusInColumn(WaferMapData data, int col, string targetStatus)
    {
        if (data == null || data.Matrix == null || col < 0 || col >= data.Columns)
            return 0;

        int count = 0;
        for (int y = 0; y < data.Rows; y++)
        {
            if (data.Matrix[y, col] == targetStatus)
                count++;
        }
        return count;
    }

    /// <summary>
    /// 统计指定矩形区域内某个芯片状态的数量
    /// </summary>
    /// <param name="startRow">起始行索引(包含)</param>
    /// <param name="startCol">起始列索引(包含)</param>
    /// <param name="endRow">结束行索引(包含)</param>
    /// <param name="endCol">结束列索引(包含)</param>
    public static int CountDieStatusInRegion(WaferMapData data, int startRow, int startCol, int endRow, int endCol, string targetStatus)
    {
        if (data == null || data.Matrix == null)
            return 0;

        int count = 0;

        // 限制边界
        startRow = Math.Max(0, startRow);
        startCol = Math.Max(0, startCol);
        endRow = Math.Min(data.Rows - 1, endRow);
        endCol = Math.Min(data.Columns - 1, endCol);

        for (int y = startRow; y <= endRow; y++)
        {
            for (int x = startCol; x <= endCol; x++)
            {
                if (data.Matrix[y, x] == targetStatus)
                    count++;
            }
        }
        return count;
    }
}
相关推荐
唐青枫1 小时前
C#.NET dapper 详解
c#·.net
死也不注释3 小时前
【鸡零狗碎记录】
unity·c#
Maybe_ch3 小时前
.NET-键控服务依赖注入
开发语言·c#·.net
★YUI★7 小时前
学习游戏制作记录(剑投掷技能)7.26
学习·游戏·unity·c#
小乖兽技术7 小时前
C#与C++交互开发系列(二十四):WinForms 应用中嵌入C++ 原生窗体
c++·c#·交互
界面开发小八哥8 小时前
界面组件DevExpress WPF中文教程:Grid - 如何过滤节点?
.net·wpf·界面控件·devexpress·ui开发
I'mSQL8 小时前
C#与WPF使用mvvm简单案例点击按钮触发弹窗
开发语言·c#·wpf
工藤新一OL9 小时前
把xml的格式从utf-8-bom转为utf-8
xml·c#·asp.net·.netcore·visual studio
henreash10 小时前
NLua和C#交互
开发语言·c#·交互
SAJalon13 小时前
C#集合全面解析
c#