基于PostGIS的火星坐標(biāo),百度坐標(biāo)批量互轉(zhuǎn)

一 背景

GIS項(xiàng)目中底圖是必不可少的,絕大部分GIS項(xiàng)目使用的底圖是基于高德,谷歌,百度,天地圖等互聯(lián)網(wǎng)(在線/離線)底圖。由于我國(guó)特殊國(guó)情,公眾版地理信息服務(wù)(包括電子底圖)都要進(jìn)行各種坐標(biāo)偏移旋轉(zhuǎn)等數(shù)據(jù)加密處理,并獲取國(guó)土資源部數(shù)據(jù)審查并頒發(fā)審圖號(hào)才可公開(kāi)發(fā)布。企業(yè)的GIS數(shù)據(jù)都是通過(guò)傳感器或者實(shí)地測(cè)量獲得的非加密的WGS84坐標(biāo)(即常用的gps那種坐標(biāo)),當(dāng)企業(yè)將自己的業(yè)務(wù)數(shù)據(jù)疊加到互聯(lián)網(wǎng)底圖時(shí),不可避免出現(xiàn)圖層疊加偏移問(wèn)題,如下圖:

圖層疊加偏移.png

底圖偏移情況總結(jié)如下:

  • 百度底圖,最坑爹的,bd-09坐標(biāo),二次加偏。
  • 高德,谷歌底圖,GCJ-02坐標(biāo),俗稱的“火星坐標(biāo)系”。
  • 天地圖,osm底圖,通常認(rèn)為是不偏移底圖。

二 解決方案與存在問(wèn)題

2.1 解決方案

由于底圖是不可改變的,唯一能解決疊加偏移問(wèn)題的方法是:將自己的業(yè)務(wù)數(shù)據(jù)根據(jù)一定的偏移公式轉(zhuǎn)換,從而使數(shù)據(jù)的坐標(biāo)與底圖達(dá)到相對(duì)對(duì)齊。當(dāng)前主流編程語(yǔ)言,都有類似處理坐標(biāo)偏移的公式換算庫(kù),滿足不同語(yǔ)言開(kāi)發(fā)的GIS項(xiàng)目需求。比如如下幾個(gè)地址:
https://github.com/FreeGIS/CoordinateTransform
https://github.com/wandergis/coordtransform

2.2 存在問(wèn)題

  • 不支持批量計(jì)算。
    當(dāng)前各種坐標(biāo)轉(zhuǎn)換庫(kù),都是實(shí)現(xiàn)單個(gè)點(diǎn)坐標(biāo)轉(zhuǎn)到底圖對(duì)應(yīng)的坐標(biāo)。但實(shí)際上,GIS存在 圖形復(fù)雜數(shù)據(jù)量大的通用特征,每個(gè)圖層都有大量圖形記錄,每個(gè)圖形記錄,其圖形常用分類就有點(diǎn)線面多點(diǎn)多線多面等六種,每個(gè)圖形都可能由非常多的坐標(biāo)點(diǎn)組成。業(yè)務(wù)需求最好是支持批量計(jì)算。
  • 動(dòng)態(tài)計(jì)算,顯示效率低。
    當(dāng)前各種坐標(biāo)轉(zhuǎn)換庫(kù),都是基于前后臺(tái)的語(yǔ)言實(shí)現(xiàn)的,每次都要獲取數(shù)據(jù)源數(shù)據(jù),再通過(guò)實(shí)時(shí)計(jì)算展示,當(dāng)數(shù)據(jù)復(fù)雜,數(shù)據(jù)量大時(shí)候,效率很成問(wèn)題。解決辦法通常是,后臺(tái)先讀取數(shù)據(jù)源,然后計(jì)算好,最后將計(jì)算結(jié)果重新存入庫(kù)里,項(xiàng)目使用時(shí),直接讀取計(jì)算好的結(jié)果。 捯飭的費(fèi)勁不?
  • 數(shù)據(jù)轉(zhuǎn)換服務(wù)維護(hù)復(fù)雜。
    當(dāng)數(shù)據(jù)庫(kù)數(shù)據(jù)發(fā)生變更時(shí),轉(zhuǎn)換服務(wù)要能增量得到變更的數(shù)據(jù),然后計(jì)算,然后再更新數(shù)據(jù)庫(kù)已存儲(chǔ)的轉(zhuǎn)換結(jié)果。整個(gè)架構(gòu)要是能自動(dòng)維護(hù)好,還是很復(fù)雜的。

三 PostGIS方案

基于現(xiàn)有方案普遍存在的問(wèn)題,筆者基于最常用的開(kāi)源GIS空間數(shù)據(jù)庫(kù)PostGIS開(kāi)發(fā)了一個(gè)function,基于一行sql搞定一切的是思想,滿足使用PostGIS的開(kāi)發(fā)者,簡(jiǎn)單的處理這些坐標(biāo)轉(zhuǎn)換問(wèn)題。PostGIS實(shí)現(xiàn)的倉(cāng)庫(kù)如下:
https://github.com/FreeGIS/Postgis_Coordinate_Transform
實(shí)現(xiàn)功能列表如下:

  • 支持WGS84與bd-09,gcj-02坐標(biāo)系,百度經(jīng)緯度與百度墨卡托之間互轉(zhuǎn)。
  • 支持點(diǎn)線面多點(diǎn)多線多面的復(fù)雜圖形批量轉(zhuǎn)換。
  • 支持對(duì)整個(gè)表批處理轉(zhuǎn)換。

約束:

  • 要求轉(zhuǎn)換的表是基于PostGIS創(chuàng)建的空間關(guān)系表
    示例支持的表:
create table point_test(
  gid serial primary key,
  name text,
  geom geometry(Point,4326)
);

不支持的表:

create table point_test(
  gid serial primary key,
  name text,
  lon numeric,   --經(jīng)度
  lat numeric     --緯度
);

不支持的表是普通關(guān)系表,非空間圖形表。

  • 要求轉(zhuǎn)換的圖形必須是二維圖形
    當(dāng)前暫不支持三維或者多維,如帶Z值的高程,帶M值的測(cè)量值等,由于過(guò)于復(fù)雜,目前筆者暫未有時(shí)間去過(guò)多實(shí)現(xiàn)。
  • 轉(zhuǎn)換表圖形坐標(biāo)系必須是epsg:4326
    除了將百度墨卡托坐標(biāo)轉(zhuǎn)百度經(jīng)緯度外,其他轉(zhuǎn)換方式,必須保證轉(zhuǎn)換表的坐標(biāo)系是4326,其他坐標(biāo)系,需要用戶使用ST_Transform函數(shù),將其數(shù)據(jù)先轉(zhuǎn)到4326坐標(biāo)系下,再使用該工具。百度墨卡托坐標(biāo)轉(zhuǎn)百度經(jīng)緯度轉(zhuǎn)換,數(shù)據(jù)源必須是3857的。
  • 圖形數(shù)據(jù)是點(diǎn)線面多點(diǎn)多線多面
    僅僅支持Point,LineString,Polygon,MultiPoint,MultiLineString,MultiPolygon六種明確類型。其他的PostGIS類型由于不常用,且不嚴(yán)格規(guī)范,通常不用于標(biāo)準(zhǔn)的空間數(shù)據(jù)庫(kù)類型,暫時(shí)不考慮實(shí)現(xiàn)。

3.1 安裝應(yīng)用

前提:PostGIS用戶,圖形表是基于PostGIS的空間關(guān)系表。
示例:在test庫(kù)安裝轉(zhuǎn)換方法

[postgres@sss~]$ psql -d test
psql (11.1)
Type "help" for help.

test=# \i FreeGIS_Coordinate_Transform.sql
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE TYPE
CREATE FUNCTION

方法簡(jiǎn)介:

FreeGIS_Coordinate_Transform(
    in schema_name text,
    in table_name text,
    in transform_type FreeGIS_coordinate_transform_type
)

schema_name:表的schema名稱。
table_name:表的名稱。
transform_type:轉(zhuǎn)換類型,枚舉型,類型如下:

BD2GCJ:百度經(jīng)緯度 轉(zhuǎn) 火星經(jīng)緯度。
GCJ2BD:火星經(jīng)緯度 轉(zhuǎn) 百度經(jīng)緯度。
WGS2GCJ:WGS84經(jīng)緯度 轉(zhuǎn) 火星經(jīng)緯度
GCJ2WGS:火星經(jīng)緯度 轉(zhuǎn) WGS84經(jīng)緯度。
BD2WGS:百度經(jīng)緯度 轉(zhuǎn) WGS84經(jīng)緯度。
WGS2BD:WGS84經(jīng)緯度 轉(zhuǎn) 百度經(jīng)緯度。
BDWGS2BDMKT:百度經(jīng)緯度 轉(zhuǎn) 百度墨卡托。
BDMKT2BDWGS:百度墨卡托 轉(zhuǎn) 百度經(jīng)緯度。
WGS2BDMKT: WGS84經(jīng)緯度 轉(zhuǎn) 百度墨卡托。
BDMKT2WGS:百度墨卡托 轉(zhuǎn) WGS84經(jīng)緯度。
轉(zhuǎn)換批處理執(zhí)行:

--將public.test表從wgs84坐標(biāo)轉(zhuǎn)火星坐標(biāo)。
select FreeGIS_Coordinate_Transform('public','test','WGS2GCJ');

執(zhí)行后,test表新增了一個(gè)transform_geom字段,就是轉(zhuǎn)換后的結(jié)果。


轉(zhuǎn)換結(jié)果

3.2 底圖疊加示例

3.2.1 疊加osm,天地圖底圖

企業(yè)的坐標(biāo),可不做處理,直接疊加。


點(diǎn)疊加osm

3.2.2 疊加谷歌,高德底圖

將企業(yè)的數(shù)據(jù),使用wgs84轉(zhuǎn)火星坐標(biāo),然后疊加:

select FreeGIS_Coordinate_Transform('public','test_pt','WGS2GCJ');

執(zhí)行展示:

--transform_geom字段存儲(chǔ)了轉(zhuǎn)換結(jié)果,示例使用如下:
create or replace view v_test_pt as select gid,name,transform_geom as geom from test_pt;

將v_test_pt 發(fā)布成地理服務(wù)后,疊加地圖如下:


轉(zhuǎn)換后疊加osm,發(fā)生偏移

轉(zhuǎn)換后疊加谷歌或高德,位置匹配

依次制作了測(cè)試線和面,測(cè)試情況如下


線 osm

線 谷歌
面 osm

面 谷歌

3.2.3 疊加百度底圖

將企業(yè)的數(shù)據(jù),使用wgs84轉(zhuǎn)百度墨卡托坐標(biāo),然后疊加:

select FreeGIS_Coordinate_Transform('public','test_pg','WGS2BDMKT');
面 百度

說(shuō)明下:將wgs批量轉(zhuǎn)到百度地圖上,需要先轉(zhuǎn)到百度經(jīng)緯,再?gòu)陌俣冉?jīng)緯轉(zhuǎn)到百度墨卡托,這些步驟被WGS2BDMKT封裝了。
百度很麻煩很麻煩?。。?br> 其他底圖的偏移操作是,將wgs偏移到對(duì)應(yīng)的底圖,然后使用標(biāo)準(zhǔn)的墨卡托投影函數(shù)疊加到底圖上即可。
百度底圖操作是,將wgs偏移到對(duì)應(yīng)的底圖,但是底圖是墨卡托坐標(biāo)系,百度經(jīng)緯度不能使用標(biāo)準(zhǔn)的墨卡托投影函數(shù),二次加密的,所以要寫(xiě)個(gè)自定義函數(shù),將百度經(jīng)緯度自己轉(zhuǎn)到百度墨卡托,才能疊加到百度底圖。
這是其他轉(zhuǎn)換庫(kù)都沒(méi)注意到,沒(méi)涉及到的,坑爹的百度?。?!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容