我的世界ParaCraft結合開源地圖OpenStreetMap生成3D校園的方法簡介
版本1.0 日期2019.2.3 作者Ray (82735589@qq.com) www.TimeGIS.com
0. 目標
Paracraft是LiXiZhi開發的一種類似我的世界Minecraft 的3D編輯軟件,
Paracraft開放源碼,可以在 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