PHP项目中的“高速跑动距离对比”实现方案
我理解你的需求是:在一个PHP项目中,实现“高速跑动距离”的对比功能(比如运动员/车辆在不同时段、不同对象间的高速跑动距离对比),由于需求比较简短,我先澄清可能的方向,再给出完整可落地的方案。

需求澄清(请确认属于哪种)
| 场景 | 说明 | 数据来源 |
|---|---|---|
| A. 运动员GPS数据 | 足球/跑步中,速度超过阈值(如≥20km/h)的累计距离,多人/多场对比 | GPS轨迹点(csv/接口) |
| B. 车辆轨迹 | 高速行驶路段距离对比 | 车载GPS/北斗 |
| C. 模拟/演示数据 | 后台管理系统里的统计对比图表 | 数据库表 |
下面以 A/B 通用 的方式给出方案(轨迹点 → 计算高速段距离 → 对比展示),可直接套用。
核心算法:高速跑动距离计算
思路:把轨迹按时间排序,逐段计算相邻两点的距离与速度,速度 ≥ 阈值 的段累加距离。
<?php
/**
* 高速跑动距离计算
* @param array $points 轨迹点 [['lat'=>..,'lng'=>..,'ts'=>..], ...]
* @param float $thresholdKmh 高速阈值(km/h),如 20
* @return array ['total'=>总距离km, 'high'=>高速距离km, 'ratio'=>占比]
*/
function calcHighSpeedDistance(array $points, float $thresholdKmh = 20.0): array
{
// 按时间排序
usort($points, fn($a, $b) => $a['ts'] <=> $b['ts']);
$total = 0.0;
$high = 0.0;
for ($i = 1, $n = count($points); $i < $n; $i++) {
$p1 = $points[$i - 1];
$p2 = $points[$i];
$distKm = haversineKm($p1['lat'], $p1['lng'], $p2['lat'], $p2['lng']);
$dtSec = $p2['ts'] - $p1['ts'];
if ($dtSec <= 0) continue; // 防脏数据
$speedKmh = ($distKm / $dtSec) * 3600;
$total += $distKm;
if ($speedKmh >= $thresholdKmh) {
$high += $distKm;
}
}
return [
'total' => round($total, 3),
'high' => round($high, 3),
'ratio' => $total > 0 ? round($high / $total * 100, 2) : 0,
];
}
/** Haversine 球面距离(km) */
function haversineKm(float $lat1, float $lng1, float $lat2, float $lng2): float
{
$R = 6371.0;
$dLat = deg2rad($lat2 - $lat1);
$dLng = deg2rad($lng2 - $lng1);
$a = sin($dLat/2)**2
+ cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * sin($dLng/2)**2;
return 2 * $R * asin(min(1, sqrt($a)));
}
⚠️ 注意:GPS 抖动会造成“假高速”,生产中建议:
- 过滤速度 > 40km/h 的异常点(或按运动类型调阈值)
- 用滑动窗口平滑(如 3 点平均)
- 丢弃相邻点时间间隔 > N 秒(如 10s)的段
数据库设计
-- 对象表(运动员/车辆) CREATE TABLE subjects ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), type VARCHAR(20) -- athlete / vehicle ); -- 轨迹点表 CREATE TABLE track_points ( id BIGINT PRIMARY KEY AUTO_INCREMENT, subject_id INT, lat DECIMAL(10,7), lng DECIMAL(10,7), ts BIGINT, -- unix 时间戳 INDEX idx_subject_ts (subject_id, ts) ); -- 结果缓存表(避免每次实时算) CREATE TABLE distance_stats ( id INT PRIMARY KEY AUTO_INCREMENT, subject_id INT, session_id VARCHAR(40), -- 场次/行程 threshold_kmh DECIMAL(4,1), total_km DECIMAL(8,3), high_km DECIMAL(8,3), ratio DECIMAL(5,2), created_at DATETIME );
对比查询与展示
多对象对比(PHP 层)
$pdo = new PDO('mysql:host=localhost;dbname=sport', 'root', '');
$stmt = $pdo->prepare("SELECT * FROM track_points WHERE subject_id = ? ORDER BY ts");
$subjects = $pdo->query("SELECT id, name FROM subjects")->fetchAll();
$result = [];
foreach ($subjects as $s) {
$stmt->execute([$s['id']]);
$points = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stat = calcHighSpeedDistance($points, 20.0);
$result[] = array_merge($s, $stat);
}
// 按高速距离降序
usort($result, fn($a, $b) => $b['high'] <=> $a['high']);
前端对比图表(ECharts 示例)
<div id="chart" style="width:800px;height:400px;"></div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script>
const data = <?= json_encode($result, JSON_UNESCAPED_UNICODE) ?>;
const chart = echarts.init(document.getElementById('chart'));
chart.setOption({ { text: '高速跑动距离对比 (≥20km/h)' },
tooltip: { trigger: 'axis' },
legend: { data: ['总距离', '高速距离'] },
xAxis: { type: 'category', data: data.map(d => d.name) },
yAxis: { type: 'value', name: 'km' },
series: [
{ name: '总距离', type: 'bar', data: data.map(d => d.total) },
{ name: '高速距离', type: 'bar', data: data.map(d => d.high),
label: { show:true, formatter: p => p.value + 'km' } }
]
});
</script>
性能优化建议
- 预计算 + 缓存:轨迹入库时异步计算
distance_stats,查询时直接读表。 - 只算增量:新点入库时只需与上一点比较,累加即可(
O(1)更新)。 - 大量数据用空间索引:MySQL 8 的
POINT+SPATIAL INDEX,或 Redis GEO。 - 阈值可配置:不同运动类型(足球 20km/h、马拉松 15km/h、车辆 80km/h)存
threshold_kmh字段。
需要你进一步明确的信息
为了给你更精准的代码,请补充:
- 数据来源:CSV 文件?GPS 设备接口?数据库已有表?
- 对比维度:人与人对 比?同一人不同场次对比?多队伍对比?
- "高速"阈值:固定值还是按运动类型?
- 展示形式:后台表格、图表、导出 Excel?
- 数据规模:单次多少点(几百 / 几万 / 百万级)?
告诉我这些,我可以直接给出贴合你项目的完整代码(含路由、控制器、视图)。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播