有啥方法可以从作为 LAT/LONG 作为 PostGIS 中的地理数据类型插入的 GPS 坐标中恢复数据?

Posted

技术标签:

【中文标题】有啥方法可以从作为 LAT/LONG 作为 PostGIS 中的地理数据类型插入的 GPS 坐标中恢复数据?【英文标题】:Any way to recover data from GPS coordinates that were inserted as LAT/LONG as geography data type in PostGIS?有什么方法可以从作为 LAT/LONG 作为 PostGIS 中的地理数据类型插入的 GPS 坐标中恢复数据? 【发布时间】:2021-12-30 17:29:42 【问题描述】:

我将所有数据点作为“POINT(43.870683 -112.359383)”插入到地理字段中,即先经纬度。现在,当我尝试使用 ST_X 和 ST_Y 提取坐标时,X 坐标看起来是正确的,但是 Y 坐标让我在大西洋中出路。我假设 PostGIS 不考虑纬度,并试图推断经度。我从该插入中得到的要点是:

   st_x    |    st_y
-----------+------------
 43.870683 | -67.640617

有没有办法恢复正确的坐标?

编辑:版本信息

            postgis_version
---------------------------------------
 3.0 USE_GEOS=1 USE_PROJ=1 USE_STATS=1

PostgreSQL 13.3

                        gps
----------------------------------------------------
 0101000020E61000007217618A72EF4540BF1072DEFFE850C0
gps | geography(Point,4326)

插入查询(现在我知道这是错误的顺序,我能以某种方式恢复数据吗?)

insert into buildings (gps) values('POINT(43.870683 -112.359383)')
select ST_X(gps::geometry), ST_Y(gps::geometry) from buildings


   st_x    |    st_y
-----------+------------
 43.870683 | -67.640617
              ^^^^^^^^^ very wrong, not what I input

【问题讨论】:

在您的问题中添加 Postgres 版本、Postgis 版本和您正在使用的实际查询。 你的积分倒退了。当参考地球表面的点时,X 映射到经度,Y 映射到纬度。因此点数据总是先解释经度,再解释纬度;你的定义应该是POINT( -112.359383 43.870683) @Belayer - PostGIS 可能确实如此,但在 GIS 世界中远未普及。 @Belayer 我明白,这就是为什么我问我是否可以通过某种方式从 PostGIS 恢复正确的 GPS 坐标。我会用版本信息更新问题。 @IanTurton 你是对的。由于 OP 实际上指定了 PostGIS,这只是一个未说明的假设,对我不利。我应该说:因此 PostGIS 中的点数据总是被解释...。感谢您指出。 【参考方案1】:

你最初以 -67.640617 结尾让我很困惑,这怎么可能?好吧,我可以得出那个确切的值(我确信它不完全是如何得到的,并且可能不是一个通用公式)。考虑纬度(Y 坐标)是 -90 ,负值表示 赤道以南,但在 -90 之后继续沿同一条运动线移动向北移动剩下的东西。您所拥有的值可以推导出为:注意:180 距离赤道 -> 南极 -> 赤道 = 180 纬度经过。

with on_earth (gps) as
     ( values ( POINT(43.870683, -112.359383)) )
select ST_Y(gps::geometry) "Latitude"
     , sign( ST_Y(gps::geometry) ) * (180 - abs( ST_Y(gps::geometry))) "Derived Latitude"        
  from on_earth;  

现在这引出了 2 个问题:

    您如何插入值:直接 SQL 或通过某些接口 (ORM/API); 转换是在输入期间还是在输出时发生的。

使用 Postgres 14.1 和 PostGIS 3.1.4 运行直接 SQL 我没有在插入 -112.359383 后获得纬度 -67.640617。 除了#2之外,以上都没有真正解决您的问题,而是试图理解结果。如果答案 #2 是在输入期间发生的转换,而 -67 是存储的值,那么您只需重新加载数据。不是你想要的答案,而是你将要面对的。然而,如果这是一个显示输出转换,那么恢复就是一个简单的更新语句。 Postgres(和 AFAIK 所有其他数据库)您可以使用旧数据值,直到至少语句复杂化。您只需选择反向反转的列即可反转您的列;即为 X 选择 ST_Y,为 Y 选择 ST_X。所以尝试:

update building  
   set gps = point( st_y(gps::geometry)    -- move Y value to X
                  , st_x(gps::geometry)    -- move X value to Y
                 ); 

它在我的环境中工作,beploy 是我的完整测试序列。我通常会创建一个小提琴,但 db<>fiddle 和 SQL Fiddle 都不支持 PostGIS。

create table building(id   integer generated always as identity
                     , gps point
                     );
                         
insert into building(gps) values (POINT(43.870683, -112.359383));

select * from building; 
/* Result
*  id | gps                    
*  1  | (43.870683,-112.359383)
*/

update building  
   set gps = point( st_y(gps::geometry)    -- move Y value to X
                  , st_x(gps::geometry)    -- move X value to Y
                 );


select * from building; 
/* Result
*  id | gps                     
*  1  | (-112.359383,43.870683) 
*/

如果数据值的转换发生在输入(插入)时,这将不会恢复实际值。但看起来你没有什么可失去的,可能会获得巨大的收益。值得一试!

【讨论】:

抱歉回复晚了!这是一个很好的答案;是的,它发生在输入上。因此,我正在考虑重新加载所有 GPS 数据。在使用 PostGIS 之前,我读过一本关于 PostGIS 的小书,从来没有遇到过需要按照与谷歌地图相反的顺序输入 lon/lat。哦,好吧,现在我知道了!感谢您提供信息丰富且详细的回答。

以上是关于有啥方法可以从作为 LAT/LONG 作为 PostGIS 中的地理数据类型插入的 GPS 坐标中恢复数据?的主要内容,如果未能解决你的问题,请参考以下文章

获取基于lat&long的邮政编码?

从 1600 万+ lat/long 获取 FIPS 块代码

根据当前地理位置 ios app javascript 从 lat / long 列表中返回值

使用 Jinja 将数据作为 JSON 对象从 Python 发送到 Javascript [重复]

PHP 地理编码,从地址到坐标lat long

Blob 存储上的 Azure 触发器,从图像 (Blob) 中提取 EXIF (lat/long/direction...) 数据