利用OpenStreetMap(OSM)資料搭建一個地圖服務

zhanlijun發表於2015-04-23

 http://www.cnblogs.com/LBSer/p/4451471.html

圖 利用OSM資料簡單釋出的北京地圖服務

 

一、OSM是什麼

       開放街道圖(OpenStreetMap,簡稱OSM)是一個網上地圖協作計劃,目標是創造一個內容自由且能讓所有人編輯的世界地圖(wiki:http://wiki.openstreetmap.org/wiki/Main_Page)。尤其值得稱道的是,osm資料開源,可以自由下載使用。

二、OSM資料結構

       OpenStreetMap包括空間資料以及屬性資料。其中空間資料主要包括三種:點(Nodes)、路(Ways)和關係(Relations),這三種原始構成了整個地圖畫面。其中,Nodes定義了空間中點的位置;Ways定義了線或區域;Relations(可選的)定義了元素間的關係。

        屬性資料Tags用於描述上述向量資料基元。(http://wiki.openstreetmap.org/wiki/Elements

2.1. Node 

       node通過經緯度定義了一個地理座標點。同時,還可以height=*標示物體所海拔;通過layer=* 和 level=*,可以標示物體所在的地圖層面與所在建築物內的層數;通過place=* and name=*來表示物件的名稱。同時,way也是通過多個點(node)連線成線(面)來構成的。

 2.2. Way   

       通過2-2000個點(nodes)構成了way。way可表示如下3種圖形事物(非閉合線(Open polyline )、閉合線(Closed polyline)、區域(Area ))。對於超過2000 nodes的way,可以通過分割來處理。

       a)Open polyline 

        非閉合線:收尾不閉合的線段。通常可用於表示現實中的道路、河流、鐵路等。

       b)Closed polyline 

        閉合線:收尾相連的線。例如可以表示現實中的環線地鐵。

       c)Area 

        區域:閉合區域。通常使用landuse=* 來標示區域等。 

2.3. Relation 

       一個Relation是用來描述兩個或多個基元的相互關係(nodes, ways 或者其他的relations),相互的關係通過role來定義,包括:

       a)route :定義公路、自行車道、鐵路等

       b)多個多邊形:定義area例如建築、河堤等

       c)邊界:裝門用來定義行政邊界

       d)限制:用於描述限制比如“非左轉”

2.4. Tag 

       標籤不是地圖基本元素,但是各元素都通過tag來記錄資料資訊。通過'key' and a 'value'來對資料進行記錄(瞭解xml或者資料庫的應該都比較清楚了吧?)。例如,可以通過highway=residential來定義居住區道路;同時,可以使用附加的名稱空間來新增附加資訊,例如:maxspeed:winter=*就表示冬天的最高限速。

三、OSM資料及下載

osm資料格式主要有以下幾種,可以通過以下網站下載資料。

osm資料格式:

OSM XML – xml-format provided by the API

PBF – highly compressed, optimized binary format similar to the API

o5m – for high-speed processing, uses PBF coding, has same structure as XML format

OSMJSON – json variant of OSM XML

osm資料下載網站:

GeoFabrik:http://www.geofabrik.de/

Metro Extracts:http://metro.teczno.com/

HOT Exports:http://hot.openstreetmap.org/

BBBike:http://extract.bbbike.org/

 

四、基於OSM資料搭建一個地圖服務

        OSM wiki提供了張架構圖,很有價值,我們可以按此架構圖一步步進行探索。

 

4.1. 資料庫

      Postgresql+外掛PostGIS非常適合儲存地理空間資料,上面架構圖的底層資料庫也是此搭配,因此我們也使用此搭配。

      a)下載postgresql+postGIS外掛

sudo apt-get install postgresql postgresql-contrib postgis postgresql-9.1-postgis

安裝完畢,我們需要更改postgres使用者的密碼,否則我們就沒法使用這個資料庫伺服器。以postgres這個系統使用者的身份執行psql命令,在終端中輸入如下:

sudo su postgres -c psql template1

這時候會出現新的提示符,輸入下面兩個命令,用新密碼替換 <***password***>:

ALTER USER postgres WITH PASSWORD ' <***password***> ';

  b)建立使用者及資料庫

postgres# CREATE USER zhanlijun WITH PASSWORD 'xxxx';

postgres# CREATE DATABASE osm;

postgres# GRANT ALL PRIVILEGES ON DATABASE osm to zhanlijun;

c)為資料庫新增空間擴充套件

CREATE EXTENSION postgis;

-- Enable Topology

CREATE EXTENSION postgis_topology;

-- fuzzy matching needed for Tiger

CREATE EXTENSION fuzzystrmatch;

-- 地理編碼

CREATE EXTENSION postgis_tiger_geocoder;

-- 用於儲存屬性tags,key-value

CREATE EXTENSION hstore;

 

4.2. 匯入資料

      從網站上下載的osm資料一般是檔案格式(如xml、pbf等),為了使用我們需要將其匯入到資料庫中,這就需要匯入工具,架構圖使用了osmpsis,但是使用起來並不友好,推薦使用osm2pgsql。

      a)安裝osm2pgsql

Run sudo apt-get install software-properties-common to install the command add-apt-repository if the command can't be found.

Run sudo add-apt-repository ppa:kakrueger/openstreetmap to add the PPA

Run sudo apt-get update to update your packaging system.

Run sudo apt-get install osm2pgsql to install the osm2pgsql package.

    b)安裝protobuf(為了匯入pbf格式資料)

sudo apt-get install libprotobuf-c0-dev protobuf-c-compiler

   c)匯入資料庫

osm2pgsql -s -U zhanlijun -d osm /Users/zhanlijun/Downloads/planet_116.104,39.667_116.892,40.066.osm.pbf -H localhost -W;

注:osm2pgsql匯入資料有兩種模式, normal and slim mode。

normal mode會在記憶體中產生如下三張中間表,並在匯入結束後丟棄,因此速度較快。

  • planet_osm_nodes
  • planet_osm_ways
  • planet_osm_rels

而slim mode則將中間結果完全放置到資料庫中。slim模式的好處是方便更新。

兩者使用的區別在於是否加“-s”,加了表示slimmode,本文使用slim mode。

使用slim mode匯入資料後在資料庫中會產生如下表。

 

4.3. 渲染

       資料已經匯入到postgresql了,下面需要將資料渲染出來,也就是將postgresql中的向量資料渲染成圖片。

4.3.1 使用Mapnik進行渲染

目前最出名的開源地圖渲染引擎莫過於Mapnik。

 Mapnik可以渲染多種資料來源,包括資料庫如postgresql,以及檔案格式資料例如shapefile、osm.xml格式等。

 這裡以shapefile格式資料為例,下載需要渲染的向量資料:http://www.naturalearthdata.com/

 1)開啟python編輯器

 1 python 

2)匯入mapnik python bindings

 1 import mapnik 

3)建立地圖

1 m = mapnik.Map(600,300) #建立一個地圖:寬600 高300
2 #m.srs 是該地圖的投影,預設是'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
3 m.background = mapnik.Color('steelblue') #設定背景色

4)建立樣式

根據我們需求設定樣式,樣式決定了最終渲染的結果。

 1 s = mapnik.Style() #style物件
 2 r = mapnik.Rule() #rule物件來管理符號 
 3 #多邊形填充符號
 4 polygon_symbolizer = mapnik.PolygonSymbolizer(mapnik.Color('#f2eff9'))
 5 r.symbols.append(polygon_symbolizer)
 6 #多邊形邊界填充符號
 7 line_symbolizer = mapnik.LineSymbolizer(mapnik.Color('rgb(50%,50%,50%)'),0.1)
 8 r.symbols.append(line_symbolizer)
 9 s.rules.append(r)
10  #將樣式加入地圖
11 m.append_style('My Style',s)

 5) 建立資料來源

 1 ds=mapnik.Shapefile(file='Users/zhanlijun/Downloads/110m-admin-0-countries/ne_110m_admin_0_countries.shp')  

 6)建立圖層

mapnik的layer是資料的基礎容器。

1 layer = mapnik.Layer('world')#新建一個叫world的圖層
2 #layer.srs 預設是'+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
3 layer.datasource = ds
4 layer.styles.append('My Style')

 7)準備map渲染

1 m.layers.append(layer) #將layer加到地圖
2 m.zoom_all() #將資料zoom_all,如果不用,結果將是空白

 8)渲染地圖

最後我們得到一張png格式的世界地圖:world.png

4.3.2 使用TileMill進行渲染

      Mapnik使用起來並不容易,尤其是配置樣式的時候,下面我們使用TileMill進行渲染,TileMill的核心是Mapnik。

      TileMill的好處是所見即所得,右邊配置樣式,左邊能馬上顯示出結果。此外還可以將結果展示出來(下圖就是利用TileMill渲染北京osm資料的結果)。

 

4.4 一體化解決方案

 GeoServer + OpenLayers +PostGIS疊加顯示動態向量資料。

安裝geoserver

sudo apt-get update

sudo apt-get install unzip openjdk-6-jre

echo "export JAVA_HOME=/usr/lib/jvm/java-6-openjdk-amd64" >> ~/.bashrc

source ~/.bashrc

wget -c http://sourceforge.net/projects/geoserver/files/GeoServer/2.3.5/geoserver-2.3.5-bin.zip

unzip -a geoserver-2.3.5-bin.zip

cd geoserver-2.3.5/bin

./startup.sh &

訪問: http://localhost:8080/geoserver/

 

 

地圖相關博文:

地圖點聚合優化方案

相關文章