Spaces:
Sleeping
Sleeping
| """Extract quỹ đạo polyline từ System sau simulate(render=True) — MỚI 23/07/2026. | |
| Đúng logic render_png CLI đang dùng: ưu tiên history_cts (đã continuize | |
| dt=0.01), fallback history event-based; vectorize() → rvw[:, 0, :2]. | |
| Downsample còn ≤ max_points điểm/bi để JSON nhẹ (~10 KB/cú). | |
| 25/07/2026 (Production §2e): thêm ``min_disp`` OPT-IN để lọc bi đứng yên. | |
| ``continuize`` điền history cho MỌI bi kể cả bi không hề nhúc nhích → bàn | |
| full rack cho ra 200 điểm × 10 bi × 4 cú ≈ 250-350 KB JSON/response (đo bàn | |
| 3 bi chỉ ~10 KB/cú). Mặc định None = hành vi cũ y nguyên (đường v1 + CLI | |
| render_png KHÔNG được đổi một pixel). | |
| """ | |
| from __future__ import annotations | |
| def extract_trajectories(system, max_points: int = 200, | |
| min_disp: float | None = None) -> dict: | |
| """{ball_id: [[x, y], ...]} — chỉ gồm bi có quỹ đạo ≥ 2 điểm. | |
| min_disp: bỏ qua bi có ĐỘ DÀI ĐƯỜNG ĐI < min_disp (mét). Cố ý dùng độ | |
| dài đường đi chứ không phải dịch chuyển ròng đầu→cuối: bi bị đánh đi rồi | |
| dội băng về gần chỗ cũ có dịch chuyển ròng ~0 nhưng đó chính là quỹ đạo | |
| người dùng cần thấy. None (mặc định) = không lọc. | |
| """ | |
| import numpy as np | |
| out: dict = {} | |
| if system is None: | |
| return out | |
| for bid, ball in system.balls.items(): | |
| xy = None | |
| for hist in (getattr(ball, "history_cts", None), | |
| getattr(ball, "history", None)): | |
| if hist is None: | |
| continue | |
| try: | |
| rvw, _ss, _ts = hist.vectorize() | |
| except Exception: | |
| continue | |
| if rvw is not None and len(rvw) > 1: | |
| xy = rvw[:, 0, :2] | |
| break | |
| if xy is None: | |
| continue | |
| if min_disp is not None: | |
| # đo trên mảng ĐẦY ĐỦ, trước khi downsample | |
| path = float(np.linalg.norm(np.diff(xy, axis=0), axis=1).sum()) | |
| if path < min_disp: | |
| continue | |
| if len(xy) > max_points: | |
| idx = np.round(np.linspace(0, len(xy) - 1, max_points)).astype(int) | |
| xy = xy[idx] | |
| out[bid] = [[float(p[0]), float(p[1])] for p in xy] | |
| return out | |