v9.5: 實作標籤完全不重疊算法

- 新增 _calculate_lane_conflicts_v2() 分開返回標籤重疊和線穿框分數
- 修改泳道選擇算法,優先選擇無標籤重疊的泳道
- 兩階段搜尋:優先側別無可用泳道則嘗試另一側
- 增強日誌輸出,顯示標籤範圍和詳細衝突分數

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
beabigegg
2025-11-06 11:35:29 +08:00
commit 2d37d23bcf
83 changed files with 22971 additions and 0 deletions

117
IMPROVEMENTS.md Normal file
View File

@@ -0,0 +1,117 @@
# 時間軸標籤避碰改進v2.0
## 問題
原始實現中,標籤只有簡單的上下(或左右)交錯,導致當事件密集時會出現文字框重疊、遮蔽的問題。
## 解決方案 v2.0 - 智能 2D 避碰 + 折線連接
### 1. **二維智能避碰演算法**
```python
def _calculate_label_positions(events, start_date, end_date):
- 計算每個標籤在時間軸上的 2D 佔用範圍
- 偵測水平重疊衝突
- 嘗試水平偏移左右移動標籤
- 如果同層無法容納自動分配到新層級
- 支援無限層級擴展
```
**避碰策略**
1. 先嘗試在同一層級無偏移放置
2. 如有衝突,嘗試向左偏移 (1x, 2x, 3x 間距)
3. 仍有衝突,嘗試向右偏移 (1x, 2x, 3x 間距)
4. 都無法容納,創建新層級
### 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`
```python
# 第 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
```
## 測試方法
```batch
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)
### 改進方向
未來可考慮:
1. 使用力導向演算法優化標籤位置
2. 支援標籤尺寸動態計算(根據文字長度)
3. 添加標籤碰撞預覽功能