Watch at Ease看见世界,读懂生活。

科技 · 实用指南

GPX 路线转成轨迹后,点名和时间还在吗?

里程不为零只是一个检查项。gpxpy 1.6.2 实测说明,点字段和重叠路径还需要分别验收。

原创示意图:四种受控 GPX 容器样例及二维总长,其中混合样例刻意包含重叠路径。
原创示意图:四种受控 GPX 容器样例及二维总长,其中混合样例刻意包含重叠路径。 Watch at Ease

gpxpy 对含有路线的文件返回零里程时,应先辨认文件结构。转成轨迹可以得到距离,也可能同时改变其他信息。保留原文件,以重新打开后的内容判断结果,不要只看转换成功提示。

我们用 Python 3.12.14 和已发布的 gpxpy 1.6.2 测试了四份人工构造的 GPX 1.1 文件:只有航点、只有路线、只有轨迹,以及路线和轨迹刻意使用相同坐标的混合文件。它们不是实际行程,也不是导航设备测试。

1. 先数容器,再决定处理方法

解析可信的本地副本后,检查 len(gpx.waypoints)、len(gpx.routes)、len(gpx.tracks) 以及每条轨迹的分段。GPX 1.1 区分独立航点、有序路线点和轨迹分段。文件中某处存在三个点,不能证明它记录了一条轨迹,也不能证明独立航点的预期连接顺序。

安装包中的全局长度方法遍历轨迹。如果只需要现有路线的二维长度,先对选定路线分别检查 route.length()。它返回米,不要求转换文件。这不是路线爬升或三维距离的解决方法。

2. 有用的辅助函数也可能只保留少数字段

gpxpy issue 290 的真实提问已经解释了路线文件为何得到零值,也提供了转换辅助函数:用经纬度和海拔新建轨迹点,把路线层名称用作轨迹名,再移除原路线。它没有复制所有点字段。基础问题已有答案。

我们的路线样例纬度均为 0,经度为 0、0.01、0.02,海拔为 10、20、30 米,每点各有一个时间、名称、说明和自定义扩展。复现该函数语义后,轨迹距离变为非零,但保存并重新打开时,这四类字段的数量均由三个降为零。路线层名称还在,点名已经不在。

3. 用普通保存对照区分损失来源

我们还在不转换路线的情况下保存并重新打开文件。GPX 1.1 对照保留了三个时间、点名、说明和扩展元素。这个比较把样例中的变化定位到字段有限的辅助函数,不能用来指责所有导出操作或整个库。

转换前,为要保留的具体点列出字段清单:坐标、海拔、时间、点名、说明和必要扩展。转换后重新打开新文件,比较值、数量和预期顺序,不要只检查是否存在任何名称或时间。轨迹名和点名需要分别核验。

4. 明确哪些路径只应计算一次

混合样例刻意让一条路线和一条轨迹拥有相同坐标。起初全局方法只计算已有轨迹;追加路线转换出的轨迹后,文件有两条轨迹,二维总长由 2,226.39 米变为 4,452.78 米。这是构造的重叠场景,不代表所有混合文件都会重复计算。

加入测量轨迹之前,先判断路线是计划、备选线路,还是同一路径的另一种表示。保留所需分段边界,避免在无关片段之间虚构连接路段。检查路径预览并写清计入哪些几何对象;总数看起来合理不能证明选择正确。

5. 按明确清单验收重新打开的文件

现有工具已经公开转换取舍。GPSBabel 1.10.0 文档说明删除源数据可避免重复,timeless 选项会影响时间复制。GPXAnalyzer 的独立航点工具说明排序和可选点名,会省略说明及符号,而且不能转换只有路线的文件。这些是文档范围,我们没有执行这些工具。

输出使用新文件名,保留原始哈希和未改动副本。只有容器及分段数、选定路径、必需点字段值与名称、单位和连接顺序符合目标时,才接受结果。出现意外变化就停止并保留两份文件。本次原文件字节完全未变;没有验证真实行驶距离、严格模式校验,也未测试 Garmin、BMW、Strava 或 GPSBabel 的运行表现。

原创示意图:字段有限的路线转换丢失四类点字段,普通 GPX 1.1 保存对照则保留这些字段。
原创示意图:字段有限的路线转换丢失四类点字段,普通 GPX 1.1 保存对照则保留这些字段。 Watch at Ease