- 新增 _calculate_lane_conflicts_v2() 分開返回標籤重疊和線穿框分數 - 修改泳道選擇算法,優先選擇無標籤重疊的泳道 - 兩階段搜尋:優先側別無可用泳道則嘗試另一側 - 增強日誌輸出,顯示標籤範圍和詳細衝突分數 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
3.4 KiB
3.4 KiB
時間軸標籤避碰改進(v2.0)
問題
原始實現中,標籤只有簡單的上下(或左右)交錯,導致當事件密集時會出現文字框重疊、遮蔽的問題。
解決方案 v2.0 - 智能 2D 避碰 + 折線連接
1. 二維智能避碰演算法
def _calculate_label_positions(events, start_date, end_date):
- 計算每個標籤在時間軸上的 2D 佔用範圍
- 偵測水平重疊衝突
- 嘗試水平偏移(左右移動標籤)
- 如果同層無法容納,自動分配到新層級
- 支援無限層級擴展
避碰策略:
- 先嘗試在同一層級無偏移放置
- 如有衝突,嘗試向左偏移 (1x, 2x, 3x 間距)
- 仍有衝突,嘗試向右偏移 (1x, 2x, 3x 間距)
- 都無法容納,創建新層級
2. 折線連接(Polyline)
- 舊版本:直線連接(事件點 → 標籤)
- 新版本:Z 形折線連接
- 水平時間軸:垂直線 → 水平線 → 垂直線
- 垂直時間軸:水平線 → 垂直線 → 水平線
- 使用 Plotly
path繪製平滑折線
折線路徑(水平時間軸):
事件點 (event_x, 0)
↓ 垂直線
中間點 (event_x, mid_y)
→ 水平線
轉折點 (label_x, mid_y)
↓ 垂直線
標籤位置 (label_x, label_y)
3. 動態標籤位置
- 垂直位置:根據層級自動計算(上下交錯)
- 水平位置:根據避碰演算法動態偏移
- 連接線:自動調整路徑適應偏移
4. 關鍵參數
label_width_ratio = 0.08: 標籤寬度約為時間軸的 8%(增加)min_horizontal_gap = 0.015: 最小水平間距為時間軸的 1.5%layer_spacing = 0.6: 層級間距(增加)- 動態 Y/X 軸範圍調整
5. 效果
- ✅ 2D 智能避碰(垂直 + 水平)
- ✅ 標籤可以左右偏移避免重疊
- ✅ 使用折線優雅連接標籤與事件點
- ✅ 根據事件密度自動調整層級數
- ✅ 視覺更清晰、更專業
視覺改進對比
舊版本
- ❌ 只有垂直避碰(上下層級)
- ❌ 標籤 x 位置固定,無法偏移
- ❌ 直線連接,密集時會交叉
- ❌ 容易出現重疊
新版本 v2.0
- ✅ 2D 避碰(垂直層級 + 水平偏移)
- ✅ 標籤可動態左右移動
- ✅ Z 形折線連接,路徑清晰
- ✅ 智能避免重疊
調整建議
如果標籤仍有重疊,可調整以下參數(在 backend/renderer_timeline.py):
# 第 80 行:增加標籤寬度估計(更保守)
label_width_ratio = 0.10 # 從 0.08 增加到 0.10
# 第 84 行:增加最小水平間距
min_horizontal_gap = total_seconds * 0.02 # 從 0.015 增加到 0.02
# 第 226/420 行:增加層級間距
layer_spacing = 0.8 # 從 0.6 增加到 0.8
測試方法
start_dev.bat
然後訪問 http://localhost:12010 並測試三個示範檔案。
技術細節
折線路徑格式
使用 SVG Path 語法:
M x,y:移動到起點L x,y:直線到指定點
範例:
M 2024-01-15,0 L 2024-01-15,0.3 L 2024-01-16,0.3 L 2024-01-16,0.6
避碰演算法複雜度
- 時間複雜度:O(n × m × k)
- n = 事件數
- m = 平均層級數
- k = 偏移嘗試次數(最多7次)
- 空間複雜度:O(n × m)
改進方向
未來可考慮:
- 使用力導向演算法優化標籤位置
- 支援標籤尺寸動態計算(根據文字長度)
- 添加標籤碰撞預覽功能