时空地图 www.TimeGIS.com
TimeGIS.com
TimeGIS.com
首页              软件              分享              技术支持              博客              行业              快手网              关于             

我的世界ParaCraft结合开源地图OpenStreetMap生成3D校园的方法简介

版本1.0 日期2019.2.3 作者Ray (82735589@qq.com) www.TimeGIS.com

0. 目标

ParacraftLiXiZhi开发的一种类似我的世界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)是一个网上地图协作计划,目标是创造一个内容自由且能让所有人编辑的世界地图。具体描述如下:

http://baike.baidu.com/link?url=L4kNWqKm1i6DodEJUFm0NZezk-7uq65tQFPhqznM1o-wTqZn5-YgFqZU1DuqFUfZWYXndSXDQaHvhKNd8YpdYnkeiDjcx7HdCpB5ZdDOJTAreCJAy_rKwZniHbWxp7dDzNXMuqzk64h7UpR5DKBsF-dkHaLL32xbjswC8W7xcbO

 

我们感兴趣的原因是它提供了全球的栅格地图数据和矢量地图数据两种格式,并且是免费的。

 

可以读读这里:

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)

网上有的翻译为瓦片,个人理解为地图切片。简单的说,就是把一张大大的地图,分割成许多小正方形(如下)。这样在加载地图的时候,只需要把区域内相关的小正方形加载出来就可以了。

42.png

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栅格图像。

然后我们可以通过调用paracraftblockimage命令把地图显示出来:

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 地图就变到了脚底水平。

n 

 

注意:前面URL下载下来的图是8bitPNG, ParaEngine目前只支持真彩色PNG,所以需要改一下,

或者用小画家Pbrush.exe工具重新存盘临时过渡一下。

4. 瓦片地图的坐标计算

       瓦片地图包含经纬度坐标信息,所以我们需要将地图的位置换算一下

阅读前面的博客:国内主要地图瓦片坐标系定义及计算原理

或者这里更详细:http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames

 

假设我们要贴一个256*256的单个PNG地图切片到Paracraft上, 因为我们有了用户输入的经纬度,

可以通过下面的公式求得瓦片坐标tileX, tileY, 这里URLZoomLevel我们可以取那个最大值19,然后拼出整个URL(格式:[Url]http://tile.openstreetmap.org/{ZOOMLEVEL}/{ROW}/{COL}.png[/Url])

然后我们利用下面的公式求得这个PNG的左下角和右上角的经纬度坐标,

256*256PNG对应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生成了德国全境的三维地图,

但是中国境内的地图就比较少了,将来有机会我们可以参与构建地图,:)

 

关于OpenStreetMap3D的例子我们可以访问这里:

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坐标,把它“画”出来。

n  CommandManager:RunCommand("/take 126");

n  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

其他参考:

http://osm2world.org/screens/

       关于地图的存储,我们可以直接从OpenStreetMap读取,也可事先下载到某个服务器,前面博客中有介绍。

       关于显示栅格地图,前面只提到了一个瓦片地图PNG的显示,可能我们需要一次读取多个(比如4个)相邻的瓦片地图,并同时显示到一个场景中。

       关于需求中提到一个格子表示一米,可能我们需要根据ZOOMLEVEL最大值时获取的瓦片地图(256×256大小)来计算,估计比一米要大,需要进一步研究,但是这个比例应该是可以显示校园了。

 

7.后记二

   Minecraft是一款来自瑞典的沙盒建造独立游戏,玩家可以在一个由程序随机产生的三维世界内以带材质贴图的立方体为基础建造建筑物。游戏最初由瑞典人马库斯·阿列克谢·泊松(Markus 'Notch' Persson)单独开发,随后自2009年起成立Mojang公司开发此游戏。游戏中的其他活动包括探索世界,采集资源,合成物品及对战。TrueCraft Minecraft 1.7.3 的一个完全开源的实现,使用C# 语言开发,因此也可以用它来结合OpenStreetMap 生成3D城市。   

http://static.oschina.net/uploads/img/201505/02080613_E3TD.png

    更多内容请访问时空地图网站:www.TimeGIS.com