考虑将shp格式的地图数据发布到webgis上去的想法有一段时间了,正好有空闲时间便忙碌开来,没想到期间遇到了诸多的问题
1.开发工具:
Geoserver,Openlayer,Ext-js,Postgres/Postgis,Python2.6,PIL,TileCache
2.地图数据
我的地图数据是08年的全国地图,按每个省市分隔开来,每个省市又分了若干个图层文件,格式是mapinfo的Tab,容量10G
由于没有全国大比例图,在偶然的一个机会从网上下载到一份C/S的监控系统,没想到安装目录内就有一份全国图,就是比例不高。
3.处理过程
1.Tab转换成shp: Ogr工具可以完成这两种格式的转换,编写python脚本可以轻易处理完
在转换数据之前需要提醒的是,发现在处理多边形图层时,这个多边形图层并不是简单的多边形,也就是那种mapinfo允许存在polygon和pline的图层,这将导致之后的导入空间数据库的失败,因为postgis要求每个图层数据类型必须是一致的,不能存在多种类型,所以编写mapbasic脚本,将这些pline对象从这多边形图层中剔去即可。
2.数据校验: 这个过程非常重要,任何提供的的矢量数据都有可能存在错误数据,所以第一步必须要修复这些可能存在的错误,工具就是ArcGis,使用其工具对每个省市的每个图层文件进行修复。
3.导入空间数据库: 编写脚本,将shp数据转成sql文件,此时必须注意空间数据库的字符编码与sql数据字符编码要吻合或者能够自动转换。pg2sq由于转换成sql时,由于shp数据中某些图层表存储的字符编码不统一导致产生的非法的sql数据,所以必须对这些数据进行修正,并采用ultraedit将数据进行转码成数据的字符集类型,我使用的是utf-8.
4.数据分离: 由于提供的全国地理数据是没有根据应用来分层的,所有的道路都合在同一个叫road的图层内,然后通过属性来区分道路的级别,由于我们在控制显示道路时是需要分层分级别的,所以必须将这些数据要分离成不同的道路图层,道路共10级别(0-9),编写脚本将每个省市的道路切割成road_?10级道路层(select into即可搞定)。
同样,除了道路之外还有其他的比如河流,POI对象等都需要进行分割到不同图层以便更精确的现实控制。
5.配置Geoserver: 数据都有了,接下来就是配置绘制引擎了。Geoserver提供WFS,WMS服务,性能一般,由于是java开发的。不管3721,配置了最新的I5主机,将java虚拟机的内存设置的最大,将postgis的数据库内存也足够调大。手工添加了1,2个图层到geoserver,preview一下,ok!
接下来编写控制这些图层的SLD了,这些花了好些时间学习和开发(学习sld对我以前开发嵌入式地图引擎风格配置也是一种帮助,之后的嵌入式地图引擎也全部使用sld进行配置了!)
由于全国数据分31个省市,每个省市都配置了21个图层,所以要人工11加到geoserver还真是很大的问题,不过没关系,有python在手,然后对geoserver的配置文件研究了一把便写了脚本将几百个图层全加了进去,然后将这些图层按省市进行分组,再次Preview,ok!
6.Cache Tile生成: 使用过GeoWebCache,发现很多地方实在不好理解,幸好找到了TileCache,代码也容易修改,研读了TileCache代码之后修改了N处地方,把效率提高了10倍以上。现在的问题在于Tilecache实现了Disk Cache,Memory Cache,但就是没有DB cache,每个tile将创建一个文件,如果这些文件很小,有的甚至才几十字节也要浪费一个文件块空间,效率不高,如果采用db的话空间就能节省很多,等以后有了时间自己编写一个后端为postgres的Tile Cache吧。
Tile Cache生成有些问题要注意:
1. 空白tile: 由于我设置的绘制设置的BBox非常大,所以在绘制的时候有些空白区域也将提交给geoserver进行处理,这样浪费了处理时间,同时这些产生的小规格图块大大占据了磁盘空间,所以修改的代码将不存储这些空白tile,仅仅存储这些tile的文件名称,而不保存内容
2. tilecache的Resolutions,ZoomLevels,BBox和Openlayers的属性必须一样,否则Opnelayers无法显示正确的tile
3. tile相交检测: 同样是空白区域的绘制,如果每次都提交给geoserver的话,geoserver将根据配置的layer去相交并绘制一次,这就完全没有必要的,我的解决方式就是提前将31个省市产生他们的MBR,然后再tile进行提交给geoserver之前,将请求的tile的bbox与这些省市的mbr进行相交测试,只有相交的图层才送入geoserver绘制
4. 大网格绘制: 每次以256×256的规格给geoserver绘制全国图的话效率实在太低,之后修改成2048×2048规格,整体的绘制效率上升了n倍,绘制完了之后采用split_tile.py将这些大块切割成256规格的小块,必须注意产生的序号
写得好累