Open Street Map维基世界地图初探--概念、开发

from: http://blog.csdn.net/viewcode/article/details/8179289

1. 什么是open street map(osm)?

2. 开发者应该知道哪些概念?包括地图的内容、格式等

3. OSM开发有哪些环境?

4. libosmscout环境的搭建

5. libosmscout的使用示例、配置文件


1. 什么是OSM?

Open Street Map 维基世界地图,一个开源的在线地图项目,包括软件和地图数据。

官网介绍

http://wiki.openstreetmap.org/wiki/Zh-hans:Main_Page

中文网页

http://wiki.openstreetmap.org/wiki/Main_Page

OSM与其他地图 如google地图的区别在哪里?

正如官网所说,它提供了一种方式,让任何人能编辑地图,能为OSM增加地图数据(当然如果是错误的,别人是有权修改的)。而且,其他地图大部分都不是免费的,或者需要授权使用, google地图是免费的,但它也是被别人授权的,无法随意编辑或在自己的软件中使用的。

所以,人们也可以免费地使用OSM数据,包括开发等。


对OSM的常见问题,可以浏览

http://wiki.openstreetmap.org/wiki/FAQ


对于大部分人而言,为OSM绘图是比较有趣的事。

有关为地图增加数据(绘图)的详细介绍如下:

http://wiki.openstreetmap.org/wiki/Zh-hans:Map_Making_Overview


而对于开发者而言,更关心如何使用OSM数据,用于开发,一个必要的开发介绍和资源入口:

http://wiki.openstreetmap.org/wiki/Develop

里面介绍了 OSM的API, 如何下载map data,map data的数据格式和数据结构,常用的开发工具(已经开发好的小工具),地图要素(有哪些数据),与OSM相关的支持的框架(库和组件)。


OSM自身的框架描述:

http://wiki.openstreetmap.org/wiki/Component_overview


下面先介绍一些与开发相关的概念和环境。

2. OSM相关的一些概念

地图数据的存储方式是xml结构,后缀名可以是xml或osm。


地图的数据结构,即地图要素包括1 Node, 2 Way, 3 Relation4 Tag5 Common attributes

这些地图要素,与普通的地图或导航要素概念相同

Node是空间点,包括经纬坐标,或高度信息。其他一些可选信息,如name等,在tag子数据中表示。类似于shape point 或attribution point

way表示线或区域,能包含2-2000个node点信息。它道路与区域描述的主要形式。类似于link、edge的概念

relation表示不同的元素间的关系,将不同元素间的关系描述出来。类似于connection的概念

tag表示一个元素中包含的一个特征,或者说是包含的一小块数据,如highway=residential,住宅区内的道路。类似于attribution的概念,不过tag的作用远不止attribution的描述。

Common attributes就是node、way、relation的共同属性,包括id, usr, version, timestamp等meta的信息。

更详细的描述参见:

http://wiki.openstreetmap.org/wiki/Data_Primitives

及每个元素的子链接。


有关tag类型的详细介绍和分类在这里有介绍:

http://wiki.openstreetmap.org/wiki/Map_Features


3. 开发框架

OSM目前提供了API 0.6版本的开发接口,xapi是extended api扩展的接口。而这些接口是用于web或Java应用开发的。如下介绍

http://wiki.openstreetmap.org/wiki/Databases_and_data_access_APIs

如果是使用其他语言开发,就必须使用其他的库或组件,这里列举了各种语言支持的库和组件。

http://wiki.openstreetmap.org/wiki/Develop/Frameworks


对于我而言,我采用的c++开发语言,目的是读取OSM数据,并解析,选取一些数据,我就选用libosmscout库。

所以,下面我就介绍libosmscout的开发环境设置。


4. libosmscout环境的搭建

我使用JOSM用于查看和下载地图数据,JOSM只能查看较小的地图数据,其内存支持400多MB,对于更大的数据不支持。OSMOSIS用于数据转换或分割等。

地图数据下载,以下链接里包括各个地区或整个地图的下载路径:

http://wiki.openstreetmap.org/wiki/Planet.osm


libosmscout各个模块的介绍: 

http://wiki.openstreetmap.org/wiki/Libosmscout

闲话少说,环境搭建(非qt版部分):

a. 使用Git从sourceforge上把源码都下载下来

http://sourceforge.net/projects/libosmscout/

b. libosmscout支持windows版本,我使用的是vs2008,所以首先查看README.VisualStudio.txt,里面包含了详细的build windows版本的步骤。

c. 依据readme,将zlib、libxml2、google protocol buffers、protoc.exe下载下来,并配置好。其中zlib、libxml2的版本要匹配,否则会有很因为版本不匹配的链接错误。

d. 依据readme,设置环境变量EXTRALIBS_HEADERS、EXTRALIBS_DEBUGLIBS。

e. 然后编译,这时,若有与DECLARE_COEFFS(SINECOEFF_SSE)相关的编译错误,就查看SSEMath.cpp中,有关math的一系列代码是否是有效的,若无效,加入#define OSMSCOUT_HAVE_SSE2。这个是我遇到的其vs工程中自带的问题,可能是个小bug吧。

f. 此时libosmscout工程、libosmscout-import工程、import工程、demo_AddressLookup工程都能编译通过。有关qt部分的工程我没编译,这里就不写了。


订阅邮件列表,用于知晓它的修改变换,及咨询问题:

https://lists.sourceforge.net/lists/listinfo/libosmscout-development


5. libosmscout使用示例与配置

在使用demo_AddressLookup之前,要获取OSM地图数据及将osm地图数据转换为libosmscout需要的binary数据。

如果手上拿的的有xml格式的数据,可以使用osmosis工具将xml格式的数据转换为osm格式。转换命令示例:

osmosis --read-xml file="planetin.xml" --write-xml file="planetout.osm"
更丰富的,强大的示例在

http://wiki.openstreetmap.org/wiki/Osmosis#Example_Usage

或使用JOSM工具从服务器上下载地图数据,并保存为osm格式,这种方法能直接打开地图数据并查看。


然后,使用编译好的import.exe,将osm格式的数据转换为binary数据。在运行程序之前,将libosmscout\map.ost复制到程序当前目录下,因为import需要默认的map.ost参数文件。建立一个用于输出结果的文件夹(libosmscout的binary地图作为输入或输出都是文件夹的形式),如转换planet.xml,运行命令Import.exe planetout.osm --destinationDirectory planet

更详尽的命令参数,请参看源码或import的命令提示。

import的输出会包含很多dat和idx文件,dat是数据文件,idx是dat的索引文件,更详细的说明在libosmscout\libosmscout\ProcessResult.txt中,libosmscout\libosmscout\Resource.txt是一些算法和程序所占资源的说明。

并且map.ost是可以编辑的,可以增加或删除一些选项,如以下一些必要类型保留,其他我都删除,并添加了highway_crossing类型。这样能减少自己不需要的生成的binary数据,当然就会提高效率。

  1. OST  
  2.   
  3. TYPES  
  4.   TYPE "highway_crossing" = NODE ("highway"=="crossing")   
  5.   
  6.   // Do not delete the following type, they are required by the GenCityStreet import step  
  7.   TYPE "boundary_administrative" = WAY AREA ("boundary"=="administrative") OR  
  8.                                    RELATION ("type"=="boundary" AND "boundary"=="administrative") OPTIONS MULTIPOLYGON IGNORESEALAND  
  9.   
  10.   // Do not delete the following types, they are required by the GenCityStreet import step  
  11.   TYPE "place_city" = NODE AREA ("place"=="city")  
  12.   TYPE "place_town" = NODE AREA ("place"=="town")  
  13.   TYPE "place_village" = NODE AREA ("place"=="village")  
  14.   TYPE "place_hamlet" = NODE AREA ("place"=="hamlet")  
  15.   TYPE "place_suburb" = NODE AREA ("place"=="suburb")  
  16.   
  17. END  

自己的一个小的demo,打印地图中highway_crossing的node(前提:自己生成的输入地图中有highway_crossing的数据)。
  1. #include <iostream>  
  2. #include <iomanip>  
  3. #include <vector>  
  4.   
  5. #include <osmscout/Database.h>  
  6. #include <osmscout/TypeConfigLoader.h>  
  7.   
  8. using namespace std;  
  9. const static size_t RESULT_SET_MAX_SIZE = 1000;  
  10.   
  11. int main(int argc, char* argv[])  
  12. {  
  13.   std::string                      map;  
  14.   map=argv[1];  
  15.   
  16.   osmscout::DatabaseParameter databaseParameter;  
  17.   //databaseParameter.SetDebugPerformance(true);  
  18.   osmscout::Database          database(databaseParameter);  
  19.   
  20.   if (!database.Open(map.c_str())) {  
  21.     std::cerr << "Cannot open database" << std::endl;  
  22.   
  23.     return 1;  
  24.   }  
  25.   
  26.   double minlat = 0.f;  
  27.   double minlon = 0.f;  
  28.   double maxlat = 0.f;  
  29.   double maxlon = 0.f;  
  30.   database.GetBoundingBox(minlat, minlon, maxlat, maxlon);  
  31.   
  32.   std::cout << " " << minlat << " " << minlon << " " << maxlat << " " << maxlon << std::endl;  
  33.   
  34.   std::vector<osmscout::NodeRef> nodes;  
  35.   std::vector<osmscout::WayRef> ways;  
  36.   std::vector<osmscout::WayRef> areas;  
  37.   std::vector<osmscout::RelationRef> relationWays;  
  38.   std::vector<osmscout::RelationRef> relationAreas;  
  39.   
  40.   osmscout::TypeConfig typeConfig;  
  41.   
  42.   clock_t startTime = clock();  
  43.   
  44.   if (!osmscout::LoadTypeData(map,typeConfig)) {  
  45.       std::cerr << "Cannot load 'types.dat'!" << std::endl;  
  46.       return false;  
  47.     }  
  48.     std::cout << "typeID:" << typeConfig.GetTypeId("highway_crossing") << endl;  
  49.   
  50.   osmscout::TypeSet types;  
  51.   types.SetType(typeConfig.GetTypeId("highway_crossing"));  
  52.   std::cout << types.HasTypes() << std::endl;  
  53.   
  54.   database.GetObjects(minlon, minlat, maxlon, maxlat,types, nodes, ways, areas, relationWays, relationAreas);  
  55.   clock_t endTime = clock();  
  56.   
  57.   std::cout << "Time:" << (endTime - startTime) << std::endl;  
  58.   
  59.   std::cout << "nodes: " << nodes.size() << " ways:" << ways.size() << " areas:" << areas.size() << std::endl    
  60.       << "relationWays:" << relationWays.size() << " relationAreas:" << relationAreas.size() << std::endl;  
  61.   
  62.   for (unsigned int i=0; i<nodes.size(); ++i)  
  63.   {  
  64.       std::cout << i << "GetLat:" << nodes[i].Get()->GetLat() << std::endl;  
  65.       std::cout << i << "GetLon:" << nodes[i].Get()->GetLon() << std::endl;  
  66.       std::cout << i << "GetId:         " << nodes[i].Get()->GetId() << std::endl;  
  67.       if (nodes[i].Get()->GetTagCount() > 0)  
  68.       {  
  69.           std::cout << i << "GetTagCount:" << nodes[i].Get()->GetTagCount() << std::endl;  
  70.           std::cout << i << "GetTagKey:" << nodes[i].Get()->GetTagKey(0) << std::endl;  
  71.           std::cout << i << "GetTagValue:" << nodes[i].Get()->GetTagValue(0) << std::endl;  
  72.       }  
  73.       std::cout << i << "GetType:" << nodes[i].Get()->GetType() << std::endl;  
  74.   }  
  75.   
  76.   database.Close();  
  77.   
  78.   std::cout << "database close ..." << std::endl;  
  79.   
  80.   return 0;  
  81. }  

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值