我的世界 ParaCraft 結合開源地圖 OpenStreetMap 生成3D校園的方法簡介
我的世界 ParaCraft 結合開源地圖 OpenStreetMap 生成 3D 校園的方法簡介
版本 1.0 日期 2019.2.3 作者 Ray ([email protected]) www.TimeGIS.com
0. 目標
Paracraft 是 LiXiZhi 開發的一種類似我的世界 Minecraft 的 3D 編輯軟體 ,
作者開發了他的原始碼 ,可以在 https://github.com/LiXizhi 找到更多資訊 。
本文介紹使用 NPL 語言(一種類似 LUA 的語言)開發 Paracraft 的一個 Mod 外掛 :
· 從網頁地圖選擇一個經緯度,將周圍的免費 GIS 地理資訊匯入到 Paracraft : Raster + Vector --> blocks 。 1 米 =1Block
· 參考 http://www.geoboxers.com/ 高度非線性,非正南正北的建築
使得 Paracraft 的世界具備 GIS 資訊。
操作形式, 為一個新的 Item 。放到世界中,則啟用。
一種可能的效果如下:
http://geoboxers.com/Stavanger/StavangerOverview/index.html#stavanger_isometric_day/0/5/1057/1044/64
1. 關於 OpenStreetMap 地圖
經過 對谷歌地圖 ,百度地圖等 WebMap 的研究,發現我們可以使用 www.OpenStreetMap.Org 的開源地圖 .
百度百科介紹 OpenStreetMap :
OpenStreetMap (簡稱 OSM )是一個網上地圖協作計劃,目標是創造一個內容自由且能讓所有人編輯的世界地圖。具體描述如下:
我們感興趣的原因是它提供了全球的柵格地圖資料和向量地圖資料兩種格式,並且是免費的。
可以讀讀這裡:
OpenStreetMap 初探(一)——瞭解OpenStreetMap
http://blog.csdn.net/scy411082514/article/details/7471499
2. GIS 背景知識
由於我們的需求和地圖相關,所以讀者可以去網上了解一些 GIS, WebGIS 等資訊。看看這篇部落格:
GIS 理論(墨卡託投影、地理座標系、地面解析度、地圖比例尺、 Bing Maps Tile System )
http://www.cnblogs.com/beniao/archive/2010/04/18/1714544.html
因為我們這裡其實是用的 WebGIS 技術,所以我們需要閱讀以下一系列部落格:
http://www.cnblogs.com/naaoveGIS/category/600559.html
尤其是其中的這三篇部落格:
(二)探究本質, WebGIS 前端地圖顯示之地圖比例尺換算原理
(三) WebGIS 前端地圖顯示之根據地理範圍換算出瓦片行列號的原理 ( 核心 )
(四) WebGIS 中通過行列號來換算出多種瓦片的 URL 之離線地圖
讀到這裡,對於 GIS 新手來說,應該是比較累了,但是還要繼續,下面這篇很重要:
國內主要地圖瓦片座標系定義及計算原理
http://www.jianshu.com/p/0b292688b6af
3. 關於柵格地圖在 Paracraft 上的顯示
通過前面的學習,我們知道柵格地圖(或者瓦片地圖) URL 的規則是這樣的:
格式: [Url]http://tile.openstreetmap.org /{ZOOMLEVEL}/{ROW}/{COL}.png[/Url]
名詞解釋: Tiles 地圖切片
Tiles are rectangular slabs of ceramic affixed in a grid arrangement to your bathroom wall! But here we're much more likely to be talking about map tiles: square bitmap graphics displayed in a grid arrangement to show a map. We may also be talking about tiled map data (described below)
網上有的翻譯為瓦片,個人理解為地圖切片。簡單的說,就是把一張大大的地圖,分割成許多小正方形(如下)。這樣在載入地圖的時候,只需要把區域內相關的小正方形加載出來就可以了。
http://tile.openstreetmap.org/7/63/42.png
如上圖, Map tiles 通常是 256 x 256 畫素的,雖然這不是一定的,但由於 Google Map 的影響,這其實已成為實際的標準。
現在我們假設使用者輸入一個經緯度地址 (longitude, Latitude) ,我們
要獲取一個 Tile: http://tile.openstreetmap.org/7/63/42.png
相應的 LUA 語句:
local img = "http://tile.openstreetmap.org/7/66/42.png";
NPL.SyncFile ( img , "42.png", " DownloadCallback ( )", "open1");
據說可以用 System.os.GetUrl ()函式非同步獲取 PNG 柵格影象。
然後我們可以通過呼叫 paracraft 的 blockimage 命令把地圖顯示出來:
NPL.load("(gl)script/apps/Aries/Creator/Game/Commands/CommandManager.lua");
local CommandManager = commonlib.gettable (" MyCompany.Aries.Game.CommandManager ");
CommandManager:RunCommand ("/home");
CommandManager:RunCommand ("/ blockimage - xz open.png");
效果可能如下:這裡是垂直的,其實我們用引數 – xz 地圖就變到了腳底水平。
注意:前面 URL 下載下來的圖是 8bit 的 PNG, ParaEngine 目前只支援真彩色 PNG, 所以需要改一下,
或者用小畫家 Pbrush.exe 工具重新存檔臨時過渡一下。
4. 瓦片地圖的座標計算
瓦片地圖包含經緯度座標資訊,所以我們需要將地圖的位置換算一下
閱讀前面的部落格: 國內主要地圖瓦片座標系定義及計算原理
或者這裡更詳細: http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
假設我們要貼一個 256*256 的單個 PNG 地圖切片到 Paracraft 上, 因為我們有了使用者輸入的經緯度,
可以通過下面的公式求得瓦片座標 tileX , tileY , 這裡 URL 的 ZoomLevel 我們可以 取那個 最大值 19 ,然後拼出整個 URL :
( 格式: [Url]http://tile.openstreetmap.org /{ZOOMLEVEL}/{ROW}/{COL}.png[/Url])
然後我們利用下面的公式求得這個 PNG 的左下角和右上角的經緯度座標,
256*256 的 PNG 對應 Paracraft 估計是 256×256 個格子
並且可以得知使用者的當前站立座標對應到 Paracraft 格子座標。
5. 關於 3D 校園建築的展現。
經過研究發現, OpenStreetMap.org 也提供了地圖的向量格式檔案,叫做 OSM 檔案。它是一種 XML 檔案。
關於 OSM 檔案格式介紹我們可以讀以下的部落格:
http://www.cnblogs.com/LBSer/p/4451471.html
http://wiki.openstreetmap.org/wiki/Elements
並且在 OSM 檔案內部,它 部分 提供了一些著名建築的三維結構圖。
http://wiki.openstreetmap.org/wiki/3D
之所以做部分,因為地圖的構建是很耗時間的,據說 OpenStreetMap 生成了德國全境的三維地圖,
但是中國境內的地圖就比較少了,將來有機會我們可以參與構建地圖,:)
關於 OpenStreetMap 中 3D 的例子我們可以訪問這裡:
http://wiki.openstreetmap.org/wiki/3D_development
利用其他軟體,我從 OpenStreetMap 網站下載了浙江大學的校園地圖,並利用一個外掛把它的三維效果圖也顯示了出來,從圖中我們可以驚喜地看到,校園建築的輪廓已經有了,不過建築的不同高度資訊缺乏。
關於 OSM 的手工獲取方法可以訪問 www.openstreetmap.org 網站,然後 Export 出一個 osm 檔案到本地。
這裡我們下載上海陸家嘴的例子來說明。
lujiazui.osm 的檔案內容示例如下:
<?xml version="1.0" encoding="UTF-8"?>
< osm version="0.6" generator=" CGImap 0.5.8 (5035 thorn-02.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/ odbl /1-0/">
<bounds minlat ="31.2312000" minlon ="121.4892000" maxlat ="31.2484000" maxlon ="121.5136000"/>
<node id="59608490" visible="true" version="3" changeset="10130036" timestamp="2011-12-16T10:45:50Z" user="DAJIBA" uid ="360397" lat ="31.2321150" lon ="121.4917826">
<tag k="source" v="PGS"/>
</node>
。。。
<way id="40779113" visible="true" version="13" changeset="43126825" timestamp="2016-10-24T15:28:02Z" user="lukys1" uid ="514683">
< nd ref="495634718"/>
。。。
< nd ref="495634718"/>
<tag k="building" v="yes"/>
<tag k=" building:levels " v="6"/>
<tag k="name" v=" 正大廣場 "/>
<tag k=" name:en " v="Super Brand Mall"/>
<tag k="shop" v="mall"/>
</way>
我們注意到 OSM 其實就是一種 XML 檔案格式,可以利用 LUA 語言來分析提取其中的建築座標資訊。
查詢檔案中的 Way 節點,我們可以提取 building 的輪廓組成一個個 polygon ,它們帶了經緯度座標資訊,我們可以通過公式換算後,對應到 Paracraft 座標,把它“畫”出來。
<![if !supportLists]> n <![endif]> CommandManager:RunCommand ("/take 126");
<![if !supportLists]> n <![endif]> CommandManager:RunCommand ("/box 1 1 1");
幸運的話,著名的建築都有 building:levels 高度資訊,可以使用它表示建築的高度,但是一般校園好像沒有。
那麼如何通過程式設計的方式下載 OSM 檔案呢? OpenStreetMap 網站提供了相應的 API ,這裡提供了說明:
http://wiki.openstreetmap.org/wiki/API_v0.6
http://wiki.openstreetmap.org/wiki/Osmapi
GET / api /0.6/ map?bbox = left , bottom , right , top
例如 http://api.openstreetmap.org/api/0.6/map?bbox=120,30.1,120.25,30.2
這裡有個 C# 包裝 API 的例子可以參考: https://github.com/yrtimiD/osm-api-dotnet
http://wiki.openstreetmap.org/wiki/3D
另外 OSM 有個工具叫 JOSM 可以開啟 OSM 檔案。
http://josm.openstreetmap.de/wiki/Introduction
並且有個外掛可以顯示 3D 建築 http://wiki.openstreetmap.org/wiki/JOSM/Plugins/Kendzi3D
我改寫了一個 C# 程式 https://github.com/BjornDeRijcke/OpenStreetMap-3D
可以分析 osm 檔案並顯示建築,效果如下:
其實最終我們需要的如下結果:(此圖拼湊而成)
注:有個 OpenStreetMap 結合 Unity3D 例子,它也用 C# 分析了 OSM 檔案,可以參考。
https://github.com/ActionStreetMap/demo
6. 後記
將來,如果覺得建築不夠細緻,我們可能需要詳細解析 OSM 檔案。
關於 OSM 的詳細解析我們需要閱讀下面的標準,並得到類似 osm2wolrd 的效果
https://wiki.openstreetmap.org/wiki/Simple_3D_buildings
其他參考:
關於地圖的儲存,我們可以直接從 OpenStreetMap 讀取,也可事先下載到某個伺服器, 前面部落格 中有介紹。
關於顯示柵格地圖,前面只提到了一個瓦片地圖 PNG 的顯示,可能我們需要一次讀取多個(比如 4 個)相鄰的瓦片地圖,並同時顯示到一個場景中。
關於需求中提到一個格子表示一米,可能我們需要根據 ZOOMLEVEL 最大值時獲取的瓦片地圖( 256×256 大小)來計算,估計比一米要大,需要進一步研究,但是這個比例應該是可以顯示校園了。
7. 後記二
Minecraft 是一款來自瑞典 的沙盒建造 獨立遊戲,玩家可以在一個由程式隨機產生的三維世界內以帶材質貼圖的立方體為基礎建造建築物。遊戲最初由瑞典人馬庫斯·阿列克謝·泊松( Markus 'Notch' Persson )單獨開發,隨後自 2009 年起成立 Mojang 公司開發此遊戲。遊戲中的其他活動包括探索世界,採集資源,合成物品及對戰。 TrueCraft 是 Minecraft 1.7.3 的一個完全開源的實現,使用 C# 語言開發,因此也可以用它 來結合 OpenStreetMap 生成 3D 城市。
更多內容 , 請訪問 時空地圖網站: www.TimeGIS.com