中心轴曲线配色 + 筛选框交互完善 + 双光标拖拽性能修复
- 中心轴边沿计数的平均值曲线改为「由信号色派生的高对比度颜色」:保持色相、 大幅拉开明度(与原始波形高对比),透明度与原信号一致;原信号改色时曲线 颜色随之变化,而光标显示该曲线数值时仍沿用原始信号的配色样式。 - 信号筛选框:内容区左右内缩改为与上下一致(不再「左右空隙明显更大」); 有输入时右侧显示清空 ✕(悬停高亮 + 手型光标,点击清空且保持编辑态); 筛选无结果时在列表区提示「无匹配的筛选信号」。 - 光标数值超出上下视界时,三角箭头标识下移 kCursorHandleReserve, 不再遮挡光标自身的三角把手(含双光标模式)。 - 性能:新增「装饰区域脏标记 + 绘图区局部回送」快路径——绘图区内的悬停/拖拽 期间跳过标签栏/工具栏/面板/分隔条的重绘,且只 BitBlt 绘图区矩形; WM_PAINT 依据更新区域是否落在绘图区内决定快慢路径,窗口缩放/遮挡露出/ 菜单与拾色器弹出等场景仍整帧重绘。 以 VERY_BIG_DATA.CSV 全信号双光标拖拽实测:单帧耗时由约 28ms 降至约 12ms。 同时修复拖拽期间残留的信号悬停提示气泡。
This commit is contained in:
1 parent
fe72afc83c
commit
8ae8d7af4f
6 files changed
+333
-45
No files matched your search
@@ -28,6 +28,7 @@ namespace jdi
|
||||
const size_t kPolylinePointsPerPixel = 2; /**< 每个像素列允许的折线顶点数(上/下包络两顶点)。 */
|
||||
const size_t kMinPolylinePoints = 512; /**< 折线最少顶点数(窗口很窄时仍保留细节)。 */
|
||||
const float kEnvelopeMinPixelSpan = 0.5f; /**< 包络纵向跨度小于该像素值时合并为单个顶点。 */
|
||||
const float kCursorHandleReserve = 9.0f; /**< 光标顶部三角把手占用的高度(数据点贴边时需避让)。 */
|
||||
const size_t kMaxScatterPoints = 2500; /**< 单条散点最大绘制点数。 */
|
||||
const size_t kPolylineCacheLimit = 64; /**< 折线顶点缓存条目上限。 */
|
||||
const float kMinScatterRadius = 1.6f; /**< 散点最小半径(逻辑像素)。 */
|
||||
@@ -294,6 +295,42 @@ namespace jdi
|
||||
}
|
||||
return WithAlpha(style.color, static_cast<unsigned int>(opacity * 255.0 + 0.5));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 由信号色派生一个「高对比度」颜色:保持色相、大幅拉开明度。
|
||||
*
|
||||
* 用途:「边沿计数(中心轴)」的平均值曲线叠加在原始波形之上,
|
||||
* 若直接用信号色会被波形淹没。这里把信号色向黑或白方向大幅偏移,
|
||||
* 并**同时考虑与原始波形色以及与绘图区底色的距离**,取对比更强的一侧,
|
||||
* 保证曲线既能与波形区分、又能压在底图上看得清。
|
||||
*
|
||||
* 结果是从信号色派生的,因此原信号改颜色时曲线颜色会自动跟着变。
|
||||
*
|
||||
* @param [IN] color 原始信号色(0xAARRGGBB)。
|
||||
* @param [IN] background 绘图区底色,用于评估可见度。
|
||||
* @return 派生出的高对比度颜色(alpha 与输入一致,由调用方再覆盖)。
|
||||
*/
|
||||
std::uint32_t HighContrastDerived(std::uint32_t color, std::uint32_t background = 0xFFFDF6E3u)
|
||||
{
|
||||
const auto squaredDistance = [](std::uint32_t a, std::uint32_t b)
|
||||
{
|
||||
const double dr =
|
||||
static_cast<double>((a >> 16) & 0xFFu) - static_cast<double>((b >> 16) & 0xFFu);
|
||||
const double dg =
|
||||
static_cast<double>((a >> 8) & 0xFFu) - static_cast<double>((b >> 8) & 0xFFu);
|
||||
const double db = static_cast<double>(a & 0xFFu) - static_cast<double>(b & 0xFFu);
|
||||
return dr * dr + dg * dg + db * db;
|
||||
};
|
||||
|
||||
const std::uint32_t darker = MixColor(color, 0xFF000000u, 0.72);
|
||||
const std::uint32_t lighter = MixColor(color, 0xFFFFFFFFu, 0.72);
|
||||
// 评分:与原始波形色的区分度为主(权重 1.0),与底色的可见度为辅(权重 0.6)。
|
||||
const double scoreDarker =
|
||||
squaredDistance(darker, color) + 0.6 * squaredDistance(darker, background);
|
||||
const double scoreLighter =
|
||||
squaredDistance(lighter, color) + 0.6 * squaredDistance(lighter, background);
|
||||
return (scoreDarker >= scoreLighter) ? darker : lighter;
|
||||
}
|
||||
}
|
||||
PlotView::PlotView() = default;
|
||||
|
||||
@@ -5218,7 +5255,9 @@ namespace jdi
|
||||
|
||||
const float rawY = ValueToY(value, lane);
|
||||
// 上下越界的数据点不再被丢弃:与左右越界一致,贴边绘制指示方向的三角。
|
||||
const DataMarker marker = MakeDataMarker(rawX, rawY, pinX, clipTop, clipBottom);
|
||||
// 上边界额外预留光标顶部把手的高度,避免数据点三角压住光标把手。
|
||||
const DataMarker marker =
|
||||
MakeDataMarker(rawX, rawY, pinX, clipTop, clipBottom, kCursorHandleReserve * m_scale);
|
||||
|
||||
const std::uint32_t signalColor = StyleColor(*resolved.style);
|
||||
|
||||
@@ -5276,8 +5315,8 @@ namespace jdi
|
||||
if (CenterValueAt(*resolved.file, *resolved.data, smooth, time, centerValue))
|
||||
{
|
||||
const float rawCenterY = ValueToY(centerValue, lane);
|
||||
const DataMarker centerMarker =
|
||||
MakeDataMarker(rawX, rawCenterY, pinX, clipTop, clipBottom);
|
||||
const DataMarker centerMarker = MakeDataMarker(
|
||||
rawX, rawCenterY, pinX, clipTop, clipBottom, kCursorHandleReserve * m_scale);
|
||||
{
|
||||
// 中心轴数据点的配色与原始信号一致(便于一一对应);
|
||||
// 但**始终按线段模式**绘制(不跟随原信号的散点模式)。
|
||||
@@ -5514,13 +5553,14 @@ namespace jdi
|
||||
}
|
||||
|
||||
PlotView::DataMarker PlotView::MakeDataMarker(float rawX, float rawY, float pinX, float clipTop,
|
||||
float clipBottom) const
|
||||
float clipBottom, float topReserve) const
|
||||
{
|
||||
DataMarker marker;
|
||||
// 上下越界时同样"钉"在网格可见边缘(留出三角形的高度,保证整体可见)。
|
||||
// 上下越界时"钉"在网格可见边缘(留出三角形的高度,保证整体可见);
|
||||
// 另外预留 topReserve(时间光标的顶部三角把手),避免数据点三角压住把手。
|
||||
const float margin = 7.0f * m_scale;
|
||||
marker.x = pinX;
|
||||
marker.y = std::max(clipTop + margin, std::min(rawY, clipBottom - margin));
|
||||
marker.y = std::max(clipTop + margin + topReserve, std::min(rawY, clipBottom - margin));
|
||||
marker.offLeft = (rawX < marker.x - 0.5f);
|
||||
marker.offRight = (rawX > marker.x + 0.5f);
|
||||
marker.offUp = (rawY < marker.y - 0.5f);
|
||||
@@ -5722,13 +5762,13 @@ namespace jdi
|
||||
return;
|
||||
}
|
||||
|
||||
// 中心平均值曲线:与原始信号**同色**,只是更透明一些;线宽等其它样式同样跟随原信号,
|
||||
// 因此原信号改颜色/线宽/透明度时曲线会自动同步。
|
||||
// 中心平均值曲线:与原信号**同色相**但大幅拉开明度,使其与原始波形形成高对比
|
||||
// (原信号改颜色时曲线随之改变,因为它是从信号色派生出来的);
|
||||
// 透明度与原信号保持一致。
|
||||
const unsigned int baseAlpha = static_cast<unsigned int>(
|
||||
std::max(0.0, std::min(1.0, static_cast<double>(resolved.style->opacity))) * 255.0 + 0.5);
|
||||
const std::uint32_t derived =
|
||||
WithAlpha(StyleColor(*resolved.style),
|
||||
static_cast<unsigned int>(static_cast<double>(baseAlpha) * 0.55 + 0.5));
|
||||
const std::uint32_t derived = WithAlpha(HighContrastDerived(StyleColor(*resolved.style)),
|
||||
baseAlpha);
|
||||
gd::Pen pen(ToGdiColor(derived), std::max(1.0f, resolved.style->lineWidth) * m_scale);
|
||||
pen.SetLineJoin(gd::LineJoinRound);
|
||||
pen.SetStartCap(gd::LineCapRound);
|
||||
@@ -6137,6 +6177,13 @@ namespace jdi
|
||||
return;
|
||||
}
|
||||
|
||||
// 其它拖拽(光标/平移/中键/横向光标/面板)期间不显示信号悬停提示:
|
||||
// 这些操作不会更新 m_hoverSignal,按下前的值会残留,表现为提示气泡"挂在原地"。
|
||||
if (m_dragMode != PlotDragMode::NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 悬停提示:光标贴近曲线时给出可拖拽说明(与时间光标的提示方式一致)。
|
||||
if (!m_hoverSignal.IsValid())
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user