# TrapMap完整图片导出与终端日志开关设计 ## 目标 为`MovementTest.Trapmaptest.cs`增加两个相互独立的测试开关: - 成功建图后,将完整栅格地图独立渲染为300 DPI PNG,不依赖Clumsy当前视口、缩放或其他Painter。 - 控制TrapMap调试信息是否同步打印到宿主进程终端,同时始终保留`DLog`日志。 现有`TrapMapTest` Painter初始化和清理已经使用世界坐标调用`UI.GetPainter("TrapMapTest")`,本次不重复修改。两腿检测ROI继续使用车体局部Painter及`false`参数。 ## 用户开关与默认值 在`TrapMapTest`手动编辑区增加: ```csharp private const bool _saveFullMapImage = true; private const bool _enableTerminalDebugLog = true; ``` 两个值传入`TrapMapBuilder`或共享日志/导出组件。关闭图片开关时不得创建目录、临时文件或PNG。关闭终端开关时只抑制`Console.WriteLine`,不得抑制`DLog`和必要的UI提示。 ## 图片内容 图片从最终发布的`GridMapData`离屏渲染,包含完整地图边界而不是屏幕截图: - 白色背景。 - 浅灰色完整栅格线,确保每个小格可见。 - 红色占用栅格。 - 蓝色车辆轮廓、几何中心和朝向。 - 绿色工作站目标标记。 - 黑色地图外边界。 - 标题/图例区域,显示世界边界、分辨率、行列数、占据率、障碍物数量、轮胎层状态和输入来源。 世界X轴在图片中向右;世界Y轴向上,因此从`Cells[row,col]`映射到位图时反转图像Y方向。工作站仅绘制标记,不写入占用数据。 ## 图片尺寸与文件约束 - 每个栅格使用`4×4`像素。 - PNG水平和垂直DPI都设置为`300`。 - 包含边距和标题后,任一图片边长不得超过`4000`像素。 - 最终PNG文件大小不得超过`50 * 1024 * 1024`字节。 尺寸在分配RGBA像素缓冲区前检查。若超过4000像素,跳过导出并报告明确原因。编码先写入同目录临时文件,完成后检查实际字节数;超过50MB时删除临时文件,不留下超限最终文件。只有所有检查通过后,才原子移动/重命名为最终PNG。 典型`327×139`地图的栅格主体约为`1308×556`像素,另加标题和边距。 ## 保存位置与命名 输出根目录使用宿主进程当前工作目录: ```text TrapMapExports\TrapMap_yyyyMMdd_HHmmss_fff.png ``` 毫秒时间戳避免同一秒多次测试覆盖。目录只在图片开关打开且地图成功后创建。临时文件使用同目录、同文件名加`.tmp`后缀,以保证最终重命名不跨磁盘。 ## 日志行为 引入TrapMap专用日志入口,其行为为: ```text 所有消息 -> DLog.Log(message, "TrapMapTest") 终端开关开启 -> 额外Console.WriteLine("[TrapMapTest] " + message) ``` 至少覆盖测试开始、输入参数、Detour位姿、车辆尺寸、地图边界/尺寸、轮胎层状态、图片保存成功/跳过/失败、最终统计和测试停止。图片错误不得因终端开关关闭而静默,仍必须进入`DLog`。 ## 组件边界 图片导出放在独立文件`ClumsyPilot/TrapMapImageExporter.cs`,避免继续扩大已经较长的MovementTest文件。组件只消费不可变的导出请求数据:地图、车辆位姿、工作站、轮胎层元数据和目标文件路径;它不读取Detour、雷达或UI,也不修改栅格。 `MovementTest.Trapmaptest.cs`负责开关、调用时机、日志和错误降级。导出发生在地图成功生成之后;导出失败不改变`TrapMapBuilder.Succeeded`或`GridMap`。 实现使用内部纯C# RGBA光栅器绘制栅格、车辆、工作站和5×7位图文字,再由精确版本`StbImageWriteSharp` 1.16.7编码PNG。编码后立即在`IHDR`后插入`pHYs=11811/11811/unit1`,以保留300 DPI元数据。运行时不依赖平台绘图程序集或原生图形资产;除单个托管Stb编码程序集外,光栅、元数据和文件流程均只使用BCL。 ## 错误处理 以下情况只导致图片导出失败,不导致建图失败: - 图片开关关闭。 - 图片尺寸超过4000像素。 - 输出目录创建失败。 - RGBA缓冲区创建、绘制或PNG编码异常。 - 临时文件超过50MB。 - 临时文件重命名失败。 异常路径必须尽力删除本次临时文件,不得删除已有的成功PNG。 ## 验证要求 至少验证: 1. 图片开关关闭时不创建文件和目录。 2. 小型已知栅格导出的PNG由BCL测试解码器重新读取;所有chunk CRC有效,`IHDR`为RGBA8,`pHYs`表示300 DPI,像素尺寸符合4像素/格及布局规则。 3. PNG中占用格、车辆和工作站采样位置颜色正确,Y轴没有上下颠倒。 4. 超过4000像素的请求在RGBA缓冲区分配前失败。 5. 最终路径使用毫秒时间戳且不覆盖旧文件。 6. 成功文件严格小于或等于50MB,超限临时文件被删除。 7. 终端开关开启时消息同时进入DLog和终端;关闭时仍进入DLog但不写终端。 8. 图片失败时地图仍为成功状态。 9. 现有源码契约、栅格行为、生命周期测试及`ClumsyPilot`编译继续通过。 ## 非目标 - 不截取Clumsy/CycleGUI窗口。 - 不保存紫色UI背景、小车3D模型、绿色两腿ROI或橙色检测猜测线。 - 不改变栅格数据格式或地图边界计算。 - 不接入新的点云来源。 - 不修改`TrajPlanner`。 - 不提交或暂存本次工作区改动。