# 厘米级！奥维无偏移导出插件精度优化！


- 发布：2022-11-09
- 栏目：工具软件

## 正文

**前言**

上一期，我制作并分享了一个奥维无偏移导出插件（👉[_**文章回顾**_](http://mp.weixin.qq.com/s?__biz=MzU1OTkwMjEyOQ==&mid=2247491114&idx=1&sn=032f9589fe0d745842a018d687d8a4f5&chksm=fc1162f4cb66ebe2460834515f618df3ae15ede8686a6334accda4a9312902de2051b5b44570&scene=21#wechat_redirect)），受限于当时的算法理解，最终只能达到2米左右的转换精度，而且经插件导出的数据文件中的“标签名称”有点问题。（最新网盘中的插件已经修复了标签名称这一bug）

由于疫情影响，封控在家，于是我又在网上再次查找了一下GCJ02-WGS84坐标转换的高精度算法，经过对多个算法进行编译、调试、精度检验，终于找到了一个可用的高精度转换算法，使得新版本奥维数据导出能够实现**真正的无偏**！

**一、优化插件转换精度分析**

使用的奥维软件版本和用于测试的标签数据仍然和上次测试一致。

在全国34个省级行政区域分别设置了一个标签点，分别利用9.0.3版本与9.3.8版本导出txt格式的坐标文件，上期文章已经解释过，由于香港特别行政区和台湾省的点位导出后直接就是无偏的，所以本期测试没有使用它们的标签数据。![](https://file.sinosite.com.cn/sinosite-file/news/old/20221109/52452aeeb21aeb2dcecea6048132c2a3.png)

（底图为高德卫星影像，审图号GS(2022)1083号）

地球的子午线总长度大约40008km，因此纬度差1度对应的实际距离约为40008/360≈111.13千米；经度差1度对应的实际距离约为111.13千米\*cos（纬度）。

利用最新9.3.8版本奥维软件，使用**最新优化后的转换插件**进行txt数据导出，与9.0.3版本直接导出数据的坐标差值如下：

![](https://file.sinosite.com.cn/sinosite-file/news/old/20221109/c181ded6a9a3fb2ebd0f6dd87ffba5f3.jpg)

可以看出，对于每个点位，使用**最新插件**导出后的坐标都能达到10cm以内的转换精度，计算出来的**坐标转换点位中误差仅为5cm**！

**二、算法优化分析**

在上一期文章中的算法（👉[_**文章回顾**_](http://mp.weixin.qq.com/s?__biz=MzU1OTkwMjEyOQ==&mid=2247491114&idx=1&sn=032f9589fe0d745842a018d687d8a4f5&chksm=fc1162f4cb66ebe2460834515f618df3ae15ede8686a6334accda4a9312902de2051b5b44570&scene=21#wechat_redirect)），使用的仅仅是利用反推估计公式进行的一次简单的转换，所以只能达到2米的转换精度。

这一次，我参考高精度算法中使用的**迭代法进行反复计算**，最终实现了**厘米级的转换精度。**

然而，看着转换后那些误差高达7、8cm的转换数据，我不仅陷入了思考：

**明明从我所使用的迭代算法的角度来说，虽然不能做到0误差，但通过反复迭代实现转换值和真值的无限近似，****理论上是可以做到在厘米级完全没有精度损失的****，但为什么现在还存在10cm以内的明显偏差呢？**

通过大量的分析和测试，我最终从数据源头找到了答案。

**三、误差源头分析**

从奥维官方给出的《奥维对象转换插件开发文档》中可以知道：

> 导出文件时，对象转换插件与奥维客户端通过Js脚本进行数据交互。其中ov_change函数是插件代码的执行入口函数，通过调用脚本中的ov_change函数，以JSON格式数据为载体，完成插件与奥维客户端的数据交互。
>
> https://www.gpsov.com/appdoc/index.php?id=52

在插件代码中，是通过先读取奥维软件中的JSON对象，然后再进行后续的数据转换操作：

```
  /*自定义经纬度纠偏计算*/
```

于是我在读取JSON对象后，立即进行数据打印：

```
    alert(JSON.stringify(Detail));//打印JSON对象的值
```

随意选择一个标签使用插件进行kml格式导出，数据打印弹窗显示，纬度Lat和经度Lng中的数据均为6位小数：

![](https://file.sinosite.com.cn/sinosite-file/news/old/20221109/90fe15f23817c09871b3a7c39e05696a.png)

由于官方给出的示例插件中并没有实际的坐标转换代码，只是一个“空壳”，使用后并不会产生数据变化，直接导出的就是原始数据。

于是，我又直接利用奥维官方给出的示例插件进行标签数据导出，可以看到虽然导出后的坐标有8位小数，但第7、8位都是0：![](https://file.sinosite.com.cn/sinosite-file/news/old/20221109/c997f79a2a620982e4fff7fb92dec730.png)

虽然，读取的原始JSON数据中的经纬度只有6位小数，然而对于纬度差0.000001°，实地距离的值为：

纬度差=0.000001\*111133m≈0.11m

也就是说，**在读取原始数据的时候，就已经会产生11cm以内的坐标误差，所以无论坐标转换算法有多精确，都避不开这11cm的误差。**

终于“破案”了！可想而知，如果我们读取的到经纬度是8位小数的，那么使用最新插件的导出结果将更加精确！

**四、取位误差对比**

最后，我任意选择了两个标签数据进行了误差对比：

**▼新疆点位**![](https://file.sinosite.com.cn/sinosite-file/news/old/20221109/dfa5f3ce6e988ff36bd00703176d557a.png)

**▼黑龙江点位**

![](https://file.sinosite.com.cn/sinosite-file/news/old/20221109/0386c2b762ef77a96fdddba63a802c46.png)

以新疆点位为例，938版本读取到的坐标和938版本无插件直接导出的GCJ02坐标相差了0.06m，而938版本使用最新插件导出的坐标和903版本导出的WGS84坐标也相差了0.06m，也就是说，转换前差了0.06m，转换后也差了0.06m。

不难推测，**插件转换的误差，是由于奥维软件中数据取位的原因造成的。**

由于数据存储的时候，单精度类型最多只能保留6位小数，双精度类型则最多可以保留15位小数。我猜想可能是奥维软件里对象数据存储的时候使用了单精度类型，所以导致了数据精度损失。

**结语**

对于绝大部分专业用户来说，其实现有阶段**厘米级的导出精度**已经完全可以满足工作需求了，但如果奥维官方在接下来的某个版本对于数据取位的问题进行了优化，使用最新插件的导出精度则会**更高**。

至于最新优化后的插件，暂时不打算直接公开分享，因为考虑到很可能导致的二次售卖问题。

昨天我在某宝上随意买了一份谷歌地球的资源，下载下来才发现竟然是我之前在公众号分享的那份，里面还保留了我当初特意放进去的公众号二维码= =。

考虑到各方面因素，加之近几个月以来惨淡的流量主广告收益，今天建立了一个付费加入的交流群，优化后的插件会在交流群内发布。

_网页版：https://www.sinosite.com.cn/news/1000000000000000912_
