博客 / 詳情

返回

JSAPIThree 地圖投影學習筆記:理解座標系統

作為一個剛開始學習 mapvthree 的小白,今天要學習地圖投影了!聽説這個系統可以控制地圖的座標系統,不同的投影方式有不同的效果!想想就好奇!

第一次聽説地圖投影

今天在文檔裏看到了"投影"這個詞,一開始我還以為是投影儀那種投影,結果查了一下才知道,原來這是地圖學裏的概念!

文檔説地圖投影是:

  • 將地球表面的地理座標(經緯度)轉換為平面座標的數學方法
  • 不同的投影方式適合不同的應用場景
  • 選擇合適的投影對準確展示地理數據很重要

我的理解:簡單説就是把地球這個球面"展開"成平面的方法!就像把橘子皮剝下來攤平一樣,不同的剝法會有不同的效果!

第一步:為什麼需要投影?

作為一個初學者,我一開始很困惑:為什麼需要投影?直接用經緯度不行嗎?

我的疑問:經緯度不是已經很準確了嗎?為什麼還要轉換?

看了文檔才知道:

  • 經緯度是球面座標,不能直接在平面上顯示
  • 不同的投影方式有不同的特點(有的保持角度,有的保持面積)
  • 選擇合適的投影可以讓地圖更準確、更美觀

我的理解:就像拍照一樣,不同的角度拍出來的效果不一樣,投影就是選擇"拍照角度"!

第二步:發現引擎支持的投影類型

文檔説 mapvthree 支持多種投影方式,我數了數,主要有這幾種:

投影 1:Web 墨卡託投影(EPSG:3857)

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:3857', // Web 墨卡託投影(默認)
    },
});

我的理解:這是最常用的網絡地圖投影,也是引擎的默認投影。

我的發現

  • 適合低緯度地區(赤道附近)
  • 高緯度地區會有嚴重變形
  • 大多數在線地圖都用這個投影

我的想法:如果做普通的網絡地圖,用這個投影就夠了!

投影 2:ECEF 投影(EPSG:4978)

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4978', // ECEF 投影(3D 地球)
    },
});

我的理解:ECEF 是地心地固座標系,是一個三維直角座標系統。

我的發現

  • 能準確表達地球形狀
  • 所有區域幾乎無形變
  • 適合精確的三維空間定位和計算
  • 是三維數據可視化的理想投影

我的想法:如果做 3D 地球效果,應該用這個投影!

我的嘗試

import * as mapvthree from '@baidumap/mapv-three';

const container = document.getElementById('container');

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4978', // 3D 地球模式
        center: [0, 0],
        range: 30000000, // 很遠的距離,能看到整個地球
    },
});

我的發現:地圖變成了一個球體!可以旋轉看整個地球,太酷了!

我的感受:這個投影真的很適合做 3D 地球效果!

投影 3:WGS84 地理座標系(EPSG:4326)

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4326', // WGS84 地理座標系
    },
});

我的理解:WGS84 是最常用的地理座標系統,使用經緯度表示位置。

我的發現

  • 全球統一的標準
  • 跨應用數據兼容性最好
  • 經緯度數據需要投影轉換才能在平面地圖上顯示

我的想法:如果數據是經緯度格式,用這個投影比較方便!

投影 4:UTM 投影

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:32633', // UTM 33N 帶
    },
});

我的理解:UTM 投影將地球分為 60 個等分帶,每個帶覆蓋 6 度經度。

我的發現

  • 能夠保持較好的距離和麪積比例
  • 適合局部區域的地圖
  • 高緯度地區變形較大

我的想法:如果做局部區域的地圖,可以考慮用 UTM 投影!

投影 5:高斯克呂格投影

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4491', // 高斯克呂格六度帶投影
    },
});

我的理解:高斯克呂格投影是一種等角投影,角度保持不變,適合進行測量和製圖。

我的發現

  • 分為六度帶和三度帶投影
  • 分為標準投影和截取投影
  • 適合中國地區的地圖

我的想法:如果做中國地區的地圖,可以考慮用這個投影!

投影 6:EqualEarth 投影(EPSG:8857)

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:8857', // EqualEarth 投影
    },
});

我的理解:EqualEarth 投影是一種等面積投影,面積保持不變。

我的發現

  • 適合進行面積計算和製圖
  • 面積比例準確

我的想法:如果要做面積相關的計算,可以用這個投影!

第三步:如何設置投影

看到這麼多投影類型後,我開始好奇:怎麼設置投影?

文檔説目標投影只能在引擎初始化時設置,之後不能修改!

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4978', // 設置目標投影
    },
});

我的理解:投影必須在創建引擎時設置,創建後不能改。

我的嘗試

import * as mapvthree from '@baidumap/mapv-three';

const container = document.getElementById('container');

// 設置為 3D 地球模式
const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4978', // ECEF 投影
        center: [0, 0],
        range: 30000000,
    },
});

我的發現:設置後,地圖的顯示方式完全變了!

我的注意:投影設置後不能修改,所以要在初始化時就確定好!

第四步:理解投影的作用

看到可以設置投影后,我想:不同的投影會有什麼不同的效果?

我試了幾個不同的投影:

// Web 墨卡託投影(默認)
const engine1 = new mapvthree.Engine(container1, {
    map: {
        projection: 'EPSG:3857',
        center: [0, 0],
        range: 10000000,
    },
});

// ECEF 投影(3D 地球)
const engine2 = new mapvthree.Engine(container2, {
    map: {
        projection: 'EPSG:4978',
        center: [0, 0],
        range: 30000000,
    },
});

我的發現

  • EPSG:3857:平面地圖,像普通的地圖
  • EPSG:4978:球體地圖,像真實的地球

我的感受:不同的投影真的有完全不同的視覺效果!

我的理解:投影決定了地圖的"形狀",選擇合適的投影很重要!

第五步:數據源的投影設置

看到可以設置目標投影后,我想:如果我的數據不是經緯度,怎麼辦?

文檔説數據源可以設置自己的投影!

GeoJSON 數據源

對於 GeoJSON 數據,可以在數據中聲明 crs 信息:

const geojson = {
    type: 'FeatureCollection',
    crs: {
        type: 'name',
        properties: {
            name: 'EPSG:3857', // 聲明數據源的投影
        },
    },
    features: [
        // ... 數據
    ],
};

const dataSource = mapvthree.GeoJSONDataSource.fromGeoJSON(geojson);

我的理解:在 GeoJSON 中聲明 crs,引擎會自動識別並轉換。

我的發現:引擎會自動將數據源的投影轉換為目標投影!

我的想法:這樣就不用手動轉換座標了,引擎會自動處理!

DataItem 的投影設置

文檔説 DataItem 也支持在屬性字段設置 crs 信息。

我的理解:每個數據項都可以有自己的投影設置。

我的發現:這樣就能處理混合投影的數據了!

第六步:底圖的投影處理

看到數據源的投影后,我想:底圖的投影怎麼處理?

文檔説底圖的投影由 TileProvider 處理,大部分 TileProvider 內部都能自動處理投影轉換!

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4978', // 目標投影是 ECEF
        provider: new mapvthree.BaiduVectorTileProvider(), // 底圖 Provider
    },
});

我的理解TileProvider 會自動處理底圖的投影轉換。

我的發現:不需要手動設置底圖的投影,Provider 會自動處理!

我的想法:這樣就很方便了,不用關心底圖的投影問題!

第七步:實際應用場景

學到這裏,我開始想:不同的投影適合什麼場景?

場景 1:普通網絡地圖

如果做普通的網絡地圖,用 Web 墨卡託投影:

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:3857', // Web 墨卡託投影(默認)
    },
});

我的想法:這是最常用的投影,適合大多數場景!

場景 2:3D 地球效果

如果做 3D 地球效果,用 ECEF 投影:

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4978', // ECEF 投影
        center: [0, 0],
        range: 30000000,
    },
});

我的想法:這個投影最適合做 3D 地球,效果最真實!

場景 3:精確計算

如果要做精確的空間計算,用 ECEF 投影:

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:4978', // ECEF 投影,精度高
    },
});

我的想法:ECEF 投影精度最高,適合做精確計算!

場景 4:面積計算

如果要做面積計算,用 EqualEarth 投影:

const engine = new mapvthree.Engine(container, {
    map: {
        projection: 'EPSG:8857', // EqualEarth 投影
    },
});

我的想法:這個投影面積比例準確,適合做面積相關的計算!

第八步:做一個完整的示例

我想寫一個完整的示例,展示不同投影的效果:

import * as mapvthree from '@baidumap/mapv-three';

// 創建多個容器展示不同投影
const container1 = document.getElementById('container1');
const container2 = document.getElementById('container2');

// Web 墨卡託投影(平面地圖)
const engine1 = new mapvthree.Engine(container1, {
    map: {
        projection: 'EPSG:3857',
        center: [116.404, 39.915],
        range: 10000,
    },
});

// ECEF 投影(3D 地球)
const engine2 = new mapvthree.Engine(container2, {
    map: {
        projection: 'EPSG:4978',
        center: [116.404, 39.915],
        range: 1000000,
    },
});

// 添加一些測試點
const points = [
    [116.404, 39.915], // 北京
    [121.473, 31.230], // 上海
    [113.264, 23.129], // 廣州
];

const geojson = {
    type: 'FeatureCollection',
    features: points.map(coord => ({
        type: 'Feature',
        properties: {},
        geometry: {
            type: 'Point',
            coordinates: coord,
        },
    })),
};

const dataSource = mapvthree.GeoJSONDataSource.fromGeoJSON(geojson);

// 在兩個引擎中都添加點
const point1 = engine1.add(new mapvthree.SimplePoint({ size: 20 }));
point1.dataSource = dataSource;

const point2 = engine2.add(new mapvthree.SimplePoint({ size: 20 }));
point2.dataSource = dataSource;

我的感受:寫一個完整的示例,對比不同投影的效果,感覺很有成就感!

我的發現

  • 不同的投影有不同的視覺效果
  • 數據會自動轉換到目標投影
  • 選擇合適的投影很重要

雖然代碼還很簡單,但是已經能展示不同投影的效果了!

第九步:踩過的坑

作為一個初學者,我踩了不少坑,記錄下來避免再犯:

坑 1:投影設置後不能修改

原因:不知道投影只能在初始化時設置。

解決:在創建引擎時就確定好投影方式,之後不能修改。

坑 2:數據投影設置錯誤

原因:數據源的投影設置錯誤,導致顯示位置不對。

解決:確保數據源的投影設置正確,或者在 GeoJSON 中正確聲明 crs

坑 3:選擇了不合適的投影

原因:不瞭解不同投影的特點,選擇了不合適的投影。

解決:根據應用場景選擇合適的投影:

  • 普通地圖:EPSG:3857
  • 3D 地球:EPSG:4978
  • 面積計算:EPSG:8857

坑 4:高緯度地區變形嚴重

原因:使用 Web 墨卡託投影顯示高緯度地區。

解決:高緯度地區建議使用 ECEF 投影或其他適合的投影。

坑 5:座標轉換問題

原因:數據投影和目標投影不一致,但沒有正確設置。

解決:確保數據源的投影設置正確,引擎會自動轉換。

我的學習總結

經過這一天的學習,我掌握了:

  1. 地圖投影的作用:將地球表面的地理座標轉換為平面座標
  2. 引擎支持的投影類型

    • Web 墨卡託投影(EPSG:3857)- 默認,適合普通地圖
    • ECEF 投影(EPSG:4978)- 適合 3D 地球和精確計算
    • WGS84 地理座標系(EPSG:4326)- 經緯度格式
    • UTM 投影 - 適合局部區域
    • 高斯克呂格投影 - 適合中國地區
    • EqualEarth 投影(EPSG:8857)- 適合面積計算
  3. 如何設置投影:在引擎初始化時通過 map.projection 設置
  4. 數據源的投影:可以在 GeoJSON 中聲明 crs,引擎會自動轉換
  5. 底圖的投影:由 TileProvider 自動處理

我的感受:地圖投影雖然概念有點抽象,但是用起來其實不難。關鍵是要理解不同投影的特點,然後根據應用場景選擇合適的投影!

下一步計劃

  1. 深入學習不同投影的數學原理
  2. 嘗試在不同投影下做數據可視化
  3. 做一個完整的投影對比項目

學習筆記就到這裏啦!作為一個初學者,我覺得地圖投影雖然概念有點抽象,但是用起來其實不難。關鍵是要理解不同投影的特點,然後根據應用場景選擇合適的投影!希望我的筆記能幫到其他初學者!大家一起加油!
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.