最近项目上需要基于地理信息服务LBS的技术,自然就找几大地图厂商开放平台,只有Android/ios原生的开发sdk。我们在unity开发的话还需要封装一层维护两份代码,最终效果上也只能打开新的activity,不能和我们的3d内容结合。网上有一些瓦片地图的链接,但是拿来也没有3d地图模式和建筑信息,也不能自定义风格。最终打算自己利用OpenStreetMap开源地图数据尝试搭建一个地图服务,我的配置是Ubuntu16.04,2GB RAM,40GB硬盘空间,进行了测试,运行良好。先上架构图:
再上完成后效果图:
这是单个瓦片 http://127.0.0.1:8089/osm_tiles/11/1710/885.png
这是使用瓦片浏览插件可以访问操作的地图 http://127.0.0.1:8089/map.html
###1、升级软件
sudo apt update
sudo apt upgrade
###2、安装语言 ,不然创建数据库会报encoding "UTF8" does not match locale "en_US"
export LANGUAGE="en_US.UTF-8"
export LANG="en_US.UTF-8"
export LC_ALL="en_US.UTF-8"
sudo locale-gen en_US.UTF-8
sudo dpkg-reconfigure locales
###3、安装PostgreSQL Database Server和PostGIS
sudo apt install postgresql
sudo apt install postgresql-contrib
sudo apt install postgis
sudo apt install postgresql-9.5-postgis-2.2
用户postgres将在安装过程中创建。这允许使用对等体认证。让我们切换到postgres用户
sudo -u postgres -i
创建一个PostgreSQL用户。
createuser osm
创建一个数据库gis,同时令osm为数据库的所有者,设置字符编码为utf8
createdb -E UTF8 -O osm gis
创建hstore和postgis扩展。
psql -c "CREATE EXTENSION hstore;" -d gis
psql -c "CREATE EXTENSION postgis;" -d gis
从用户postgre离开
exit
在系统上创建osm用户
sudo adduser osm
###4、下载 Map Stylesheet和Map Data 至/home/osm
首先切换至osm用户
su - osm
下载最新的 CartoCSS map stylesheets到osm用户的家目录
wget https://github.com/gravitystorm/openstreetmap-carto/archive/v2.41.0.tar.gz
解压
tar xvf v2.41.0.tar.gz
下载map data至osm家目录,使用下面的数据下载整个地图的地图数据。也可以选择下载台湾的或者全球的。
wget -c http://download.geofabrik.de/asia/china-latest.osm.pbf
之后离开osm用户
exit
###5、导入map data至PostgreSQL
配置postgresql
sudo vim /etc/postgresql/9.5/main/postgresql.conf
fsync = off 173 行
full_page_writes =off 183 行
synchronous_commit= off 174 行
shared_buffers (2GB) 113 行
maintenance_work_mem (10GB) 123 行
work_mem (50MB) 122 行
effective_cache_size (24GB) 289 行
checkpoint_timeout = 10min 196 行
checkpoint_completion_target = 0.9 199行
为了导入数据,我们需要安装osm2pgsql
sudo apt install osm2pgsql
切换至som用户。
su - osm
使用下面的命令进行导入
osm2pgsql --slim -d gis -C 2048 --hstore -S openstreetmap-carto-2.41.0/openstreetmap-carto.style china-latest.osm.pbf
数据导入保证有足够磁盘空间,耗时几个小时,请耐心等待
exit###6、安装mapnik mod_tile
sudo apt install git
sudo apt install autoconf
sudo apt install libtool
sudo apt install libmapnik-dev
sudo apt install apache2-dev
clone 仓库
sudo git clone https://github.com/openstreetmap/mod_tile.git
cd mod_tile/
编译 安装
sudo apt-get install -y g++
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install
sudo make install-mod_tile
结果:Libraries have been installed in:
/usr/lib/apache2/modules
###7、添加中文支持
sudo apt-get -y install fonts-wqy-zenhei
sudo apt-get install unifont
sudo apt-get install ttf-unifont
下载字体保存在/usr/share/fonts/truetype路径下
替换会出现中文乱码不显示问题
###8、生成Mapnik Stylesheet
sudo apt install curl
sudo apt install unzip
sudo apt install gdal-bin
sudo apt install mapnik-utils
sudo apt install node-carto
切换至osm用户
su - osm
切换至样式目录
cd openstreetmap-carto-2.41.0/
得到 shapefiles,这个步骤要获取很多区域边界文件,耗时比较多,请耐心等待
./get-shapefiles.sh
构建mapnik xml 样式文件
carto project.mml > style.xml
退出osm用户
exit
###9、配置渲染
编辑渲染配置文件。
sudo vim /usr/local/etc/renderd.conf
在[default]节,修改xml和host值。
XML=/home/osm/openstreetmap-carto-2.41.0/style.xml
HOST=localhost
在[mapnik]节,修改plugins_dir值。
plugins_dir=/usr/lib/mapnik/3.0/input/
保存文件。
安装渲染初始化脚本。
sudo cp mod_tile/debian/renderd.init /etc/init.d/renderd
授予执行权限。
sudo chmod a+x /etc/init.d/renderd
编辑初始化脚本。
sudo vim /etc/init.d/renderd
修改下面的变量值。
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="-c /usr/local/etc/renderd.conf"
RUNASUSER=osm
保存文件。
创建下面的文件,设置osm为所有者。
sudo mkdir -p /var/lib/mod_tile
sudo chown osm:osm /var/lib/mod_tile
开始渲染服务。
sudo systemctl daemon-reload
sudo systemctl start renderd
sudo systemctl enable renderd
也可手动启动渲染服务
sudo -u 'osm' renderd -f -c /usr/local/etc/renderd.conf
###10、配置apache
安装apache web server
sudo apt install apache2
创建模块加载文件。
sudo vim /etc/apache2/mods-available/mod_tile.load
写入下面的命令。
LoadModule tile_module /usr/lib/apache2/modules/mod_tile.so
创建链接
sudo ln -s /etc/apache2/mods-available/mod_tile.load /etc/apache2/mods-enabled/
之后编辑默认虚拟主机文件。
sudo vim /etc/apache2/sites-enabled/000-default.conf
在<VirtualHost *:80>粘贴下面语句。
LoadTileConfigFile /usr/local/etc/renderd.conf
ModTileRenderdSocketName /var/run/renderd/renderd.sock
# Timeout before giving up for a tile to be rendered
ModTileRequestTimeout 0
# Timeout before giving up for a tile to be rendered that is otherwise missing
ModTileMissingRequestTimeout 30
保存并重启apache。
sudo systemctl restart apache2
浏览器访问
your-server-ip/osm_tiles/0/0/0.png
这里可以看到世界地图,恭喜你成功了
###11、使用OpenLayer在网页上显示和操作地图
cd /var/www/html
wget https://github.com/openlayers/ol3/releases/download/v3.18.2/v3.18.2-dist.zip
unzip 'v3.18.2-dist.zip'
sudo vim /var/www/html/map.html
添加
<!DOCTYPE html>
<html>
<head>
<title>Accessible Map</title>
<link rel="stylesheet" href="v3.18.2-dist/ol.css" type="text/css">
<script src="v3.18.2-dist/ol.js"></script>
<style>
a.skiplink {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
padding: 0;
border: 0;
height: 1px;
width: 1px;
overflow: hidden;
}
a.skiplink:focus {
clip: auto;
height: auto;
width: auto;
background-color: #fff;
padding: 0.3em;
}
#map:focus {
outline: #4A74A8 solid 0.15em;
}
</style>
</head>
<body>
<a class="skiplink" href="#map">Go to map</a>
<div id="map" class="map" tabindex="0"></div>
<button id="zoom-out">Zoom out</button>
<button id="zoom-in">Zoom in</button>
<script>
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM({
url: 'http://127.0.0.1:8089/osm_tiles/{z}/{x}/{y}.png'
})
})
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: new ol.View({
center: [12973503.936793,4833266.172531],
zoom:5
})
});
document.getElementById('zoom-out').onclick = function() {
var view = map.getView();
var zoom = view.getZoom();
view.setZoom(zoom - 1);
};
document.getElementById('zoom-in').onclick = function() {
var view = map.getView();
var zoom = view.getZoom();
view.setZoom(zoom + 1);
};
</script>
</body>
</html>
保存退出,你就可以在浏览器访问这个网页,查看渲染好的地图。