绘图交互完善 + 稠密区域拖拽性能修复(VERY_BIG_DATA 2ms/大格不再卡顿)
一、功能修正 - 修复「光标数据点在上下视界外不绘制」的问题,并让上下越界与左右越界一样用三角表示: 新增 `DataMarker` / `PaintDataMarker()`,统一处理「可视区内画圆点、越界则钉在网格边上 画三角指示方向」的四向情形(左/右/上/下)。光标取值与中心轴取值都改走这一套, 因此纵向被裁掉的数据点不再消失。 - 「边沿计数(中心轴)」的中心平均值曲线改为**跟随原信号的样式**: 与原始信号同色但更透明,线宽同样跟随(lineWidth + 0.6,下限 1.4), 原信号改颜色/线宽/透明度后曲线同步变化(曲线参与场景指纹,样式变化即失效重绘)。 光标显示中心值时的胶囊也改用**原始信号颜色**(一一对应),并**始终按线段模式**着色, 不再使用光标色。 - 「拆分当前网格」在可点击时追加尾缀「(N个信号)」(N = 该网格内信号数), 只有 1 条信号(不可点击)时不加尾缀。 二、新增:左侧信号筛选框 - 信号列表上方新增「筛选信号」输入框:空内容时显示灰色占位提示,单击进入编辑, 点击别处或回车结束编辑;列表内容随输入**实时**变化。 - 支持 `*` 通配符(`*` 等价于"任意字符",因此 `*` 单独出现等价于不过滤),忽略大小写。 - 筛选结果**仍以组为单位**,组默认展开,只显示匹配的信号;组内无匹配信号时整组不显示。 - 复用统一的 `TextEdit` 编辑模型,因此光标/选区/Ctrl+A/C/X/V 等行为与其它输入框一致。 三、性能:修复 VERY_BIG_DATA.CSV 在 2ms/大格密集区域拖拽卡顿 以「显示全部 5 条信号 + 时间轴缩放到 2ms 一大格」为场景逐段打点定位后修复: - **主因:稠密包络的锯齿描边光栅化**。抽稀时每列产生 min/max 两个顶点交替的锯齿, 2000+ 条近乎满幅的斜线段在 GDI+ 抗锯齿下要光栅化几十万像素(实测每网格 14ms, 5 网格约 70ms/帧)。 改为**包络带一次填充**:逐列记录上/下包络,收段时拼成「上包络正向 + 下包络反向」的 闭合多边形,用一条 `GraphicsPath` + `FillPath` 绘制(显式 `FillModeWinding`, 自交包络不会挖洞)。基准测试(1224 列):14.26ms → **1.69ms(约 8.4 倍)**, 且**保留抗锯齿**、静态帧与拖拽帧完全一致(不是"交互降级")。 逐像素对比确认观感等价(墨量覆盖率 90.8% vs 91.3%)。 包络带同时用于静态绘制与 MOVE_SIGNAL 的拖拽虚影。 - **大面积不透明填充改走 GDI**:`UiFillRect` 在面积 ≥ 20000px² 且颜色不透明时使用 `GetHDC + FillRect`(GDI+ FillRectangle 约 2.2ns/像素,整窗背景 1.7M 像素要 0.9ms、 面板背景 1.9ms)。半透明填充仍走 GDI+(GDI 不做 alpha 混色);小面积仍走 GDI+ (避免 GetHDC 固定开销)。顺序安全:GetHDC 会先刷入已排队的 GDI+ 内容。 - **`UiTextWidth` 不再触发 GDI+ 批次刷新**:改为复用 `UiMeasureTextWidth` (`GetDC(nullptr)`),`UiEllipsize` 逐字符回退时的十几次刷新被完全消除。 实测(125% 缩放、1725x996、5 信号、2ms 一大格): 绘图区绘制 47~87ms → **3.6~4.5ms**;整帧最大 196.8ms → **约 17~21ms(≈50~60fps)**, 与空闲帧基本持平,即"拖拽与不拖拽一样流畅"。 验证(VERY_BIG_DATA.CSV;面板行坐标因新增筛选框整体下移,复选框客户区 (61,250) 起、行距 33): - 筛选框:输入 `B` 后只剩「编码器B相」「电流钳采集(ABSx10)」,组仍展开;清空即恢复。 - 拆分:合并 3 条信号后右键显示「拆分当前网格(3个信号)」;单信号网格该项置灰无尾缀。 - 光标/中心轴:竖线光标取值与中心值胶囊均按四向越界正确显示三角/圆点。 - 稠密区域:5 信号全选 + 缩放到 2ms 一大格,左键拖拽信号、左键平移、中键平移均流畅; 渲染观感与修改前等价(叠图对比)。 - make clean && make all 无警告无错误。
This commit is contained in:
1 parent
82a29362eb
commit
fe72afc83c
6 files changed
+721
-126
No files matched your search
@@ -867,7 +867,9 @@ namespace jdi
|
||||
* @param [OUT] breaks 输出每段折线的起始下标(用于处理缺失值断线)。
|
||||
*/
|
||||
void BuildPolyline(const ResolvedSignal& resolved, const LaneVisual& lane,
|
||||
std::vector<gd::PointF>& points, std::vector<std::size_t>& breaks) const;
|
||||
std::vector<gd::PointF>& points, std::vector<std::size_t>& breaks,
|
||||
std::vector<gd::PointF>& band, std::vector<std::size_t>& bandBreaks,
|
||||
bool& bandMode) const;
|
||||
|
||||
/**
|
||||
* @brief 绘制单个网格。
|
||||
@@ -982,6 +984,42 @@ namespace jdi
|
||||
void PaintCenterCurve(gd::Graphics& g, const ResolvedSignal& resolved, const LaneVisual& lane,
|
||||
int smooth) const;
|
||||
|
||||
/**
|
||||
* @brief 数据点标记的位置与"越界方向"(用于决定画圆点还是贴边三角)。
|
||||
*/
|
||||
struct DataMarker
|
||||
{
|
||||
float x = 0.0f; /**< 标记锚点横坐标(已夹在可视区内)。 */
|
||||
float y = 0.0f; /**< 标记锚点纵坐标(已夹在可视区内)。 */
|
||||
bool offLeft = false; /**< 数据点位于左侧视界之外。 */
|
||||
bool offRight = false; /**< 数据点位于右侧视界之外。 */
|
||||
bool offUp = false; /**< 数据点位于上方视界之外。 */
|
||||
bool offDown = false; /**< 数据点位于下方视界之外。 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 计算数据点标记:把越界的数据点"钉"在网格可见边缘,并记录越界方向。
|
||||
* @param [IN] rawX 数据点的原始横坐标。
|
||||
* @param [IN] rawY 数据点的原始纵坐标。
|
||||
* @param [IN] pinX 横向贴边位置(光标在视界外时的钉住横坐标)。
|
||||
* @param [IN] clipTop 网格可见区上边界。
|
||||
* @param [IN] clipBottom 网格可见区下边界。
|
||||
* @return 标记几何。
|
||||
*/
|
||||
DataMarker MakeDataMarker(float rawX, float rawY, float pinX, float clipTop,
|
||||
float clipBottom) const;
|
||||
|
||||
/**
|
||||
* @brief 绘制数据点标记:视界内为圆点,越界时在对应边缘绘制指示方向的三角。
|
||||
* @param [IN,OUT] g 绘图上下文。
|
||||
* @param [IN] marker 标记几何。
|
||||
* @param [IN] radius 圆点半径。
|
||||
* @param [IN] fillColor 前景色(圆点/三角内部)。
|
||||
* @param [IN] ringColor 描边色(圆环/三角外框)。
|
||||
*/
|
||||
void PaintDataMarker(gd::Graphics& g, const DataMarker& marker, float radius,
|
||||
std::uint32_t fillColor, std::uint32_t ringColor) const;
|
||||
|
||||
/**
|
||||
* @brief 放置一个光标取值胶囊:先夹到网格可见范围内,再向下(必要时向上)避让
|
||||
* 已占用的标注矩形,最后登记到 `m_cursorLabelRects`。
|
||||
@@ -1254,6 +1292,21 @@ namespace jdi
|
||||
double laneYMax = 0.0; /**< 网格幅值上界。 */
|
||||
std::vector<gd::PointF> points; /**< 折线顶点。 */
|
||||
std::vector<std::size_t> breaks; /**< 每段折线在 points 中的起始下标。 */
|
||||
|
||||
/**
|
||||
* @brief 是否处于「稠密包络」模式(采样点密度超过像素分辨率)。
|
||||
*
|
||||
* 此时 `points` 是每列 min/max 交替的锯齿,逐段描边的光栅化开销极大
|
||||
* (实测每网格约 14ms);改用下面的「包络带」一次填充后约 1.7ms,
|
||||
* 且保留抗锯齿,静态与拖拽帧的观感完全一致。
|
||||
*/
|
||||
bool bandMode = false;
|
||||
|
||||
/** 包络带顶点:每段为「上包络正向 + 下包络反向」,闭合后即为该段的填充多边形。 */
|
||||
std::vector<gd::PointF> band;
|
||||
|
||||
/** 每段包络带在 `band` 中的起始下标。 */
|
||||
std::vector<std::size_t> bandBreaks;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user