sentrux源码剖析(三):egui Treemap渲染引擎——squarify布局、依赖边路由与实时高亮的实现细节
【免费下载链接】sentruxReal-time architectural sensor that helps AI agents close the feedback loop, enabling recursive self-improvement of code quality. Pure Rust.项目地址: https://gitcode.com/gh_mirrors/se/sentrux
sentrux是一个纯 Rust 编写的实时架构传感器,它把代码仓库扫描成 Treemap 树状图,让每个文件按"权重"占据一块矩形、每条依赖关系变成一条连线,帮助开发者(和 AI Agent)一眼看清代码库的规模、耦合与热点。本文深入它的渲染引擎源码,拆解squarify 布局算法、依赖边路由与实时高亮三大核心机制,带你看懂这个 egui Treemap 可视化是如何在每帧绘制中既快又稳的。
渲染管线总览:从文件树到屏幕像素
整条管线的设计目标是布局与渲染彻底解耦:布局引擎只输出抽象的几何数据RenderData(扁平矩形 + 折线边 + 锚点),不依赖 egui;渲染器拿到它后纯函数式地画到egui::Painter上,无状态、无副作用。
- 入口:compute_layout_from_snapshot 把快照、视口尺寸和 LayoutConfig(尺寸模式、缩放模式、布局模式、聚焦过滤等 9 个配置打包)喂给布局调度,产出矩形、锚点,再调用边路由,最终拼成 RenderData。
- 每帧绘制:render_frame 按固定图层顺序绘制:根矩形 → 目录分区 → 文件块 → 热度覆盖层 → 依赖边 → 徽标 → 小地图。交互时自动降级 LOD(
lod_full),跳过边与热度层保证流畅。 - 坐标换算:所有几何都在世界坐标系计算,由 ViewportTransform 统一换算成屏幕像素,支持平移、缩放与视口剔除——屏幕外的矩形和边直接不画。
Squarify 布局:让上百个文件摆得"又方又齐"
Squarified treemap(Bruls、Huizing、van Wijk 2000)是业界标准的空间填充算法,sentrux 在 squarify.rs 中做了通用化实现:调用方提供带权重的条目和目标矩形,算法通过回调逐个吐出定位后的矩形。
权重先行:谁的文件块该更大
面积分配前先做自底向上权重预计算:precompute_weights 一次遍历同时应用聚焦过滤、隐藏路径排除(排序后二分前缀匹配,O(log H))和尺寸模式(行数/逻辑行/函数数/热度/均匀),再用 apply_scale 压缩极端差值——线性、平方根、log₂、x^0.6 四种缩放,小文件不会被大文件"碾没"。
逐行构建:宽高比最优贪心
核心在 build_row:从最大权重条目开始逐个试加入当前行,用 worst_aspect_ratio 追踪行内最差宽高比,一旦变差立即定行——这就是"square 化"的由来。随后 process_row 按比例切分行区域,主循环 squarify 反复"放一行、缩剩余视口"直到耗尽。
两个工程细节值得留意:
- 尾部兜底:剩余空间塞不下正常矩形时,emit_tail 以最小尺寸网格摆放,保证 100 个小文件一个不丢(有专门的浮点漂移回归测试)。
- NaN 防御:零权重、NaN 权重都不会产生 NaN 坐标,test_zero_weight_items_no_nan 专门守护这一点。
递归切分由 layout_treemap 驱动:目录先扣除内边距和标题条(chrome_for_depth 用简单规则而非小数启发式),再对子节点调用 squarify,避免"幽灵空目录"。
依赖边路由:L 形折线、边界裁剪与车道分配
边路由的目标是最少弯折 + 永不穿块。compute_edge_path 的策略很直观:
- 两端裁剪到块边界:起点按出块方向贴到源块边缘(clip_source_to_border),终点沿入线方向贴到目标块边缘,还处理了"端点落在块内"的退化情况。
- 0 弯折:两中心近似水平/垂直对齐时直接画直线;
- 1 弯折:否则按主导方向走 L 形正交路径,拐角坐标还会被钳制到源块外部(clamp_bend_outside),防止折线穿过自己。
当多个文件对之间存在 import/call/inherit 三类边同时存在时,apply_lane_offsets 用规范化 (min,max) 字符串对分组,assign_lanes 按 0、-1、+1、-2、+2 对称展开车道,避免平行线段叠在一起。
性能上,compute_all_edge_paths 先把重复的 (from,to) 边聚合成带计数连接(透明度、线宽随条数增强),再用rayon::join三类边并行路由;同时构建双向邻接索引EdgeAdjacency,把每帧"某文件连接了谁"的查询从 O(E) 扫描降为 O(1)。
实时高亮:聚光灯模式、热度涟漪与虚线动画
聚光灯高亮是最"实时"的交互:悬停或选中文件时,渲染器通过EdgeAdjacency查出它的所有邻居组成集合(build_connected_set)——命中者提亮、无关文件整体变暗,边只画与活跃文件相连的那几条(passes_spotlight)。搜索框激活时同一套机制切换为"匹配高亮、其余压暗"。
边与块的视觉区分靠虚线模式:import 实线、call 虚线、inherit 点线(draw_edge_line)。draw_dashed_polyline 用累计长度让虚线图案跨拐角连续不重置,每帧推进相位偏移形成流动动画——动画偏移特意用 f64 取模,避免 4.5 小时后 f32 精度丢失。
热度层由独立的 heat_overlay 处理:编辑活动让对应块泛起涟漪光晕,配合 Heat 配色模式,"最近谁在动"一目了然——这正是 sentrux 作为"实时架构传感器"帮 AI Agent 闭合反馈环的视觉基础。
关键源码文件速查
| 模块 | 路径 |
|---|---|
| 布局总入口 | sentrux-core/src/layout/mod.rs |
| Squarify 算法 | sentrux-core/src/layout/squarify.rs |
| 递归切分与目录装饰 | sentrux-core/src/layout/treemap_layout.rs |
| 权重与缩放 | sentrux-core/src/layout/weight.rs |
| 边路由与车道 | sentrux-core/src/layout/routing.rs |
| 边聚合与并行 | sentrux-core/src/layout/aggregation.rs |
| 每帧渲染编排 | sentrux-core/src/renderer/mod.rs |
| 文件块绘制与高亮 | sentrux-core/src/renderer/rects.rs |
| 边绘制与虚线动画 | sentrux-core/src/renderer/edges.rs、sentrux-core/src/renderer/edge_routing.rs |
| 视口变换与剔除 | sentrux-core/src/layout/viewport.rs |
小结
sentrux 的 Treemap 渲染引擎是"经典算法 + 工程防御"的范例:squarify 保证面积语义正确且形状美观,L 形路由 + 车道分配让依赖网络在密集画布中依然可读,邻接索引 + 视口剔除 + LOD 降级则支撑起实时高亮的流畅体验。纯 Rust、无状态渲染、并行路由的设计,让它能从容应对数万边的大仓库。
【免费下载链接】sentruxReal-time architectural sensor that helps AI agents close the feedback loop, enabling recursive self-improvement of code quality. Pure Rust.项目地址: https://gitcode.com/gh_mirrors/se/sentrux
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考