我的世界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