用于存储纬度和经度的适当/最佳类型

BCS*_*BCS 63 encoding types latitude-longitude

在像C,C++或D这样的系统级编程语言中,用于存储纬度和经度的最佳类型/编码是什么?

我看到的选项是:

  • IEEE-754 FP为度或弧度
  • 度或弧度存储为32或64位int中的固定点值
  • 将整数范围映射到度数范围: - > deg = (360/2^32)*val
  • 度,点,秒和小数秒存储为int中的位字段
  • 某种结构.

简易解决方案(FP)具有主要的缺点,它具有非常均匀的分辨率(在英格兰的某个地方,它可以以微米为单位测量,在日本测量,它不能).这也有FP比较等所有问题.其他选项需要在数据生命周期的不同部分进行额外的努力.(代,演示,计算等)

一个有趣的选择是浮动精度类型,其中随着纬度增加它获得更多位并且经度变得更少(当它们朝向极点靠近时).

相关问题并不完全涵盖这一点:


顺便说一句:32位在赤道上提供大约0.3英寸的E/W分辨率.这接近于高等级GPS设置可以工作的规模(IIRC,它们在某些模式下可以降至约0.5英寸).

OTOH如果32位均匀分布在地球表面,你可以在一边为大约344m的正方形,5 Bytes给21m,6B-> 1.3m和8B-> 5mm.

我现在没有特定的用途,但之前已经使用过这种东西,并且在某些时候再次期待.

cle*_*tus 37

最简单的方法是将它存储为浮点数/双精度.N和E为正,S和W为负.只需记住分数和秒数超过60(因此31 45'N为31.75).通过查看它们很容易理解值是什么,并且在必要时,转换为弧度是微不足道的.

纬度和经度的计算(例如两个坐标之间的大圆距离)严重依赖于三角函数,三角函数通常使用双精度.任何其他格式都将依赖于正弦,余弦,atan2和平方根的另一种实现.任意精度数字(例如Java中的BigDecimal)都不适用于此.类似于int ^ 2 32统一传播的东西会有类似的问题.

几个评论中提出了统一性.在此,我将简单地指出,地球在经度方面并不统一.北极圈的一弧秒经度比赤道的距离短.双精度浮子可在地球上的任何位置提供亚毫米级精度.这还不够吗?如果没有,为什么不呢?

同样值得注意的是您要对该信息做什么,因为您需要的计算类型会对您使用的存储格式产生影响.

  • 我同意这回答了问题.我使用过的大多数商业系统都在内部使用FP度或弧度.缺乏或一致性是纬度和经度定义的函数,而不是它们存储的方式. (3认同)
  • 一个有效的观点,但没有解决我希望解决的问题。 (2认同)
  • 不要忘记 C(和大多数语言)中的数学函数需要以弧度表示的参数。在使用数学函数之前,任何以度为单位存储值的系统都需要转换为弧度。这并不意味着以度为单位存储是错误的;事实上,这可能是最好的。但要注意。 (2认同)

Joh*_*ook 17

通常不知道经度和纬度比32位浮点更精确.因此,如果您担心存储空间,可以使用浮点数.但总的来说,将数字作为双精度数更方便.

Radians对理论数学更方便.(例如,只有当你使用弧度时,正弦的导数才是余弦.)但是度数通常更熟悉,更容易让人们解释,所以你可能想要坚持学位.

  • 请记住,至少在经度上,*地球*不均匀.北极圈经度的1秒与赤道的距离不同.你为什么要/需要统一? (2认同)

V. *_*ler 13

好问题!

我知道这个问题已经有 9 年历史了,我只知道你正在寻找的答案的一部分,但我刚刚来到这里有一个类似的问题,自从这个问题提出以来,很多事情都发生了变化,例如可用的硬件和 GPS 。我经常在固件中处理这个主题,处理不同类型应用程序中的不同类型的 GPS,并且已经记不清我花了多少小时(和天)为我使用过的不同应用程序制定“最佳设计”或发达。

与往常一样,不同的解决方案将提供收益和成本,最终,“最佳设计”始终是收益和成本与系统要求的“最佳匹配”。当我问同样的问题时,我必须考虑以下几点:

CPU时间成本

如果 CPU 没有内置浮点协处理器(许多微控制器都是这种情况),那么处理“float”、“double”和“long double”的成本可能会非常高。例如,对于我经常使用的一个 16 位微控制器,使用“双精度”值的乘法需要 326 个 CPU 时钟周期,除法需要 1193 个时钟周期。非常贵!

精度权衡

在赤道处,一个“float”(IEEE-754 32位浮点值),需要表示一个有符号的度数值,假设能够表示7个“干净”的有效十进制数字,一个最低有效十进制数字的变化(例如从 179.9999 到 180.0000)将表示大约 11.12 米的距离。这可能满足也可能不满足硬系统精度要求。而“双精度”(表示 15 个“干净”的有效十进制数字,因此从 179.999999999999 到 180.000000000000 的变化)表示大约 0.00011 毫米。

输入精度限制

如果您正在处理来自 GPS 的输入,您将获得多少位真实精度,以及您需要保留多少位?

开发时间成本

IEEE-754 64 位双精度值(“double”)和 32 位单精度值(“float”)在 C 语言中处理起来非常方便,因为几乎每个 C 编译器都附带了这两种类型的数学库,并且通常非常可靠。如果您的 CPU 配备了硬件浮点处理器,那么这是一个简单的选择。

RAM 和存储成本

如果您必须在 RAM(或存储,例如 MYSQL)中保留大量这些值,则可用 RAM(和存储空间)可能会影响解决方案的可操作性。

可用数据与所需数据

我在撰写本文时正在处理的一个例子(我来到这里提出这个问题的原因)是我正在处理 u-blox M8 GPS,它能够为我提供二进制 GPS 信息(节省翻译 ASCII NMEA 的 CPU 开销)句子)。在这种二进制格式(称为“UBX 协议”)中,纬度和经度表示为带符号的 32 位整数,该表示能够表示低至约 1.11 厘米的精度(在赤道处)。例如,-105.0269805 度经度表示为 -1050269805(使用全部 32 位),并且 1 个 LSb 变化表示任何地方的纬度变化约 1.11 厘米,赤道处的经度变化为 1.11 厘米(在较高纬度处变化较小,与余弦成比例)的纬度)。该 GPS 所在的应用程序执行导航任务,该任务(已经存在且经过充分测试的代码)需要“双”数据类型。不幸的是,仅通过将整数的基数 2 位移动到“双精度”的内部表示位,无法轻松地将这个整数转换为 IEEE-754 64 位“双精度”,因为要执行的十进制移位是以 10 为底的小数点移位。如果它是以 2 为基数的十进制移位,则可以将整数的以 2 为基数的位移动到“双精度”的位字段中,而只需很少的转换。但可惜的是,我拥有的有符号整数并非如此。因此,在没有硬件浮点处理器的 CPU 上,这将花费我一次乘法:326 个 CPU 时钟周期。

double   ldLatitude;
int32_t  li32LatFromGps;
ldLatitude = (double)li32LatFromGps * 0.0000001;
Run Code Online (Sandbox Code Playgroud)

请注意,选择的乘法是这样的:

ldLatitude = (double)li32LatFromGps / 10000000.0;
Run Code Online (Sandbox Code Playgroud)

因为在我正在处理的 CPU 上,“双”乘法比“双”除法快约 3.6 倍。这就是微控制器世界的生活。:-)

如果导航任务可以直接使用 32 位有符号整数来完成,那就太棒了(如果我周末有时间的话,将来可能会更棒)!那么就不需要转换了……但是用这样的整数来做导航任务会花费更多吗?CPU 成本,可能效率更高。开发时间成本?这是另一个问题,特别是已经有一个经过充分测试的系统,该系统使用 IEEE-754 64 位“双”值!另外,已有的软件可以提供地图数据(使用“双”度数值),该软件也必须转换为使用有符号整数——这不是一朝一夕的任务!

一个非常有趣的选择是使用原始纬度/经度整数直接(无需翻译)表示“矩形”(实际上是梯形,在极点处变成三角形)近似值之间的交点。在赤道处,这些矩形的尺寸约为东西方向 1.11 厘米、南北方向 1.11 厘米,而在英国伦敦等纬度处,尺寸约为东西方向 0.69 厘米、南北方向 1.11 厘米。这可能很容易处理,也可能不容易处理,具体取决于应用程序的需求。

不管怎样,我希望这些想法和讨论能够帮助其他正在研究这个主题的人,为他们的系统寻找“最佳设计”。

亲切的问候,维克

  • 换句话说,是双倍的。 (8认同)

Pyk*_*ler 10

根据这篇关于十进制度数的维基百科文章,精度为8的十进制表示应该绰绰有余.

0 decimal places, 1.0 = 111 km
...
7 decimal places, 0.0000001 = 1.11 cm
8 decimal places, 0.00000001 = 1.11 mm
Run Code Online (Sandbox Code Playgroud)


Rol*_*kas 7

http://www.esri.com/news/arcuser/0400/wdside.html
在赤道,经度的弧秒大约等于纬度的弧秒,即 1/60 海里(或 101.27英尺或 30.87 米)。

32 位浮点数包含 23 位显式数据。
180 * 3600 需要 log2(648000) = 19.305634287546711769425914064259 位数据。请注意,符号位是单独存储的,因此我们只需要计算 180 度。
如果将值 648000 标准化为 2 的某个幂,则适用以下计算。
从 23 中减去 log2(648000) 的位后,我们还剩下 3.694365712453288230574085935741 位用于亚秒数据。
即 2 ^ 3.694365712453288230574085935741 = 12.945382716049382716049382716053 部分每秒。
因此,浮点数据类型在赤道上的精度为 30.87 / 12.945382716049382716049382716053 ~= 2.38 米。

如果您将 180 度值归一化为 2 的某个幂,则上述计算是精确的。否则,假设次度精度存储在小数点后,浮点表示将在物理上将所有 8 位用于度数部分。这为亚度精度留下了 15 位。然后 15 - log2(3600) 使 3.1862188087829629413518832531256 位用于亚秒数据,或 3.3914794921875 ~= 3.39 米精度在赤道。这比归一化所能提供的大约少一米。


Ale*_*hek 7

正如@Roland Pihlakas 已经指出的那样,这取决于您要使用坐标的精度。

我只是建议另一种观点:

  • 地球赤道周长(周长)为 40.000 公里;
  • 即40M米,即40亿厘米;
  • 32 位变量包含 2^32 或 ~42 亿个不同的值,这甚至比上述周长中的厘米数还要多一点。
  • 这意味着,如果我们为纬度和经度选择 32 位整数值,那么我们就可以以 < 1 厘米的精度来定位地球上的某个点。
  • 同样,我们可以计算浮点值的精度:
    • float32包含 23 个有效位 => ~4.7 米精度
    • float64包含 52 个有效位 => < 1 mm 精度


Chr*_*oph 5

您提到的浮点值问题可能会成为问题吗?如果答案是否定的,我建议只使用双精度的弧度值 - 如果您无论如何都要进行三角计算,您将需要它。

\n\n

如果使用双精度时可能存在精度损失问题,或者您不会进行三角学,我建议您映射到整数范围的解决方案 - 这将为您提供最佳分辨率,可以轻松转换为任何显示格式您所在的区域设置将使用 and - 选择适当的 0 子午线后 - 可用于转换为高精度的浮点值。

\n\n

PS:我一直想知道为什么似乎没有人使用地心球坐标——它们应该相当接近地理坐标,并且不需要所有这些花哨的球体数学来进行计算;为了好玩,我想将 Gauss-Kr\xc3\xbcger-Kolinedn (德国 Katasteramt 使用的)转换为 GPS 坐标 - 让我告诉你,这很丑陋:一个使用贝塞尔椭球体,另一个使用 WGS84,并且Gauss-Kr\xc3\xbcger 映射本身就非常疯狂......

\n


aij*_*aij 5

什么编码是“最好的”实际上取决于您的目标/要求。

如果您正在执行算术运算,浮点纬度、经度通常非常方便。其他时候笛卡尔坐标(即x,y,z)可能更方便。例如,如果您只关心地球表面上的点,则可以使用n 向量

至于长期存储,IEEE 浮点会浪费您不关心的范围(对于纬度/经度)或在笛卡尔坐标的情况下您可能不关心的精度(除非您希望在原点处具有非常好的精度)无论出于何种原因)。当然,您可以将任一类型的坐标映射到您首选大小的整数,以便所述整数的整个范围覆盖您在您关心的分辨率下感兴趣的范围。

当然,除了在编码中不浪费比特之外,还有其他事情需要考虑。例如,(Geohashes)[https://en.wikipedia.org/wiki/Geohash] 具有很好的属性,可以很容易地找到同一区域中的其他 geohashes。(大多数将具有相同的前缀,并且您可以计算其他将具有的前缀。)不幸的是,它们在赤道附近和两极附近的经度方面保持相同的精度。我目前使用 64 位 geohashes 进行存储,这在赤道处提供了大约 3 m 的分辨率。

梅登黑德定位系统具有一些类似的特征,但似乎更适合人类之间的位置通信,而不是存储在计算机上。(存储 MLS 字符串会浪费大量比特来进行一些相当微不足道的错误检测。)

我发现的一个以不同方式处理两极的系统是军事网格参考系统,尽管它似乎也更面向人类通信。(从纬度/经度转换到纬度/经度似乎很痛苦。)

根据您的具体需求,您可以在两极附近使用类似于通用极地坐标系的系统,以及在世界其他地方使用比UTM计算更合理的系统,并且最多使用一位来指示这两个系统中的哪一个你正在使用。我说最多一点,因为您关心的大多数点不太可能位于两极附近。例如,您可以使用“半位”,表示 11 表示使用极坐标系,而 00、01 和 10 表示使用其他系统,并且是表示的一部分。

抱歉,这有点长,但我想保存我最近学到的东西。遗憾的是,我还没有找到任何标准的、理智的、有效的方法来以统一的精度表示地球上的一个点。

编辑:我发现另一种方法看起来更像你想要的,因为它更直接地利用了靠近两极的经度所需的较低精度。事实证明,有很多关于存储法向量的研究。使用优化球坐标编码法线向量描述了这样一种系统,用于在保持最低精度水平的同时对法线向量进行编码,但它也可以用于地理坐标。