好久没更新了,因为我在–憋--大–招--,对,就是今天这篇。
今天跟大家分享一下我的开源GIS解决方案经历。
–额-- 考虑到单聊技术解决方案你可能会很快睡着,所以我今天会把重点放在我封装地图API这个事情上,以封装地图API的经历为线索,穿插着讲一些当时用到的开源GIS架构。
文章稍微有点长,如果你只是想了解一下最新的开源GIS架构,可以直接跳过前面,去看第五版和最后的总结,但我建议你还是从第一版开始看,因为没有前面的 4 个版本就不会有第五版,只看总结就和读名言警句效果一样,看的时候觉得有道理,过后就忘了,因为不能感同身受。
我一直在传统IT行业的公司工作,公司都是以做政府项目为主,俗称toG业务。
这种公司里,GIS在其中的应用通常为两种,一种是GIS结合公司的业务形成一个xx地理信息系统,或是xx一张图系统,另一种是结合公司业务封装一套地图API,为公司的其它业务系统提供地图技术支撑,类似于高德地图API、百度地图API。地图API的背后通常有一套GIS解决方案作为支撑
今天我们就来聊一聊封装地图API这点事。
从我封装的第一个地图API版本诞生到现在,已经过去了7年时间,中间经历了 3 家公司,迭代了 5 个版本。5 个版本中,第 1 个版本使用的ArcGIS,后面 4 个版本主要使用的开源GIS。
公司做环保业务,业务系统主要用C#开发,业务系统中涉及地图的部分使用ArcGIS Flex API开发,由GIS开发人员负责。那个年代,地图还主要是用Flex开发,因为Flex在那时给人感觉是很炫酷。
随着项目的增加,发现很多业务功能在项目里是通用的,再后来发现,如果把业务功能和地图功能分离,再把Flex编写的地图功能封装一套面向JS的接口,C#开发人员就可以自己完成地图相关的工作,不用受Flex语言的限制了。
于是我们准备封装一套用Felx编写的,面向C#开发人员的JS地图API。
地图API发布后,在做技术支持的过程中发现一个有趣的现象,关于地图API的使用,完全不懂GIS的初级C#开发人员觉得好用,原因是能帮他们解决问题,有困难时可以随时找我们技术支持。
了解一点GIS的中级C#开发人员觉得不好用,他们会拿我们的地图API和ArcGIS JS API对比,觉得后者更好用,但由于ArcGIS JS API的地图偏丑,我们也不提供技术支持,需要他们自己去研究,最终还是选择用我们的地图API。
了解一点GIS的高级C#开发人员基本不用,其中有两个同事的反应令我印象深刻,一个同事说:”你们自己开发的东西,自己都不用“。言外之意是,你们自己都不用的东西不会好用。但我们的想法是,把Flex封装一套JS的地图接口是因为Flex入门有门槛,我们GIS开发人员既然都会Flex了,而且我们开发的地理信息系统,整个都是用Flex开发的,那肯定是直接用ArcGIS Flex API会更灵活,所以不用。
还有一个同事更牛,他直接去研究Flex,不会的就问我们,入门后直接封装了一套地图接口自己用。我们研究过他封装的接口,虽然功能简单了些,但定义接口时的出发点感觉明显和我们不一样,我们是站在功能的角度封装,尽量保证接口的复用度高,比如添加点,添加线,缓冲等功能。他是站在用户的角度封装,比如从数据库查出来一堆数据,把这堆数据直接丢给接口,就在地图上展示出来了。总体而言,他的接口封装度更高,更贴近他的实际使用习惯,而我们的接口更像是把ArcGIS的Flex接口翻译了一套JS的。
还注意到一个现象,经常有使用我们接口的业务开发人员跑过来问,为什么我的地图不显示?经历的多了,发现通常有两种原因,一种是地图服务的地址不对,当时的地图服务都是用ArcGIS server发布的,ArcGIS server地图服务的rest地址是个网页,这个网页打开后,有很多级的链接地址,业务人员不知道应该拷贝哪一级的地址,经常拷错,所以地图出不来。另一种是,添加多个地图时,地图间的坐标不一致,导致添加的地图不显示。
想想也是,地图服务和地图坐标这些知识对于不懂GIS的开发人员来说还是挺难的。
虽然第一版有这样那样的问题,但在当时还是提升了部门的整体工作效率。不光是C#开发人员可以自己去开发地图功能了,GIS组内部也通过这种形式,把分散在各个项目中的技术成果收集了起来,并不断的积累完善。
换公司了,新公司做网安业务,有海量定位数据,GIS在其中的作用是,对定位数据进行提取、分析、展示,从而帮助客户解决业务问题。
公司的所有系统必须部署在客户内网,客户的内网是无法访问互联网的,而地图使用的又是互联网地图,这就需要把互联网地图瓦片下载下来,拷贝到客户内网发布。
公司有一个GIS应用系统,和GIS强关联的业务功会能放在这里。另外,其它部门有地图功能需求时,也会找到我们GIS部门,这个场景和上家公司很像。
所以,二话不说,第二版地图API走起。
换公司了,新公司做管网业务,相比前面两家,业务和GIS的相关性更强一些,业务中需要对管网GIS数据进行编辑、存储、发布和应用。公司之前地图都是使用ArcGIS开发的,正在准备转开源GIS,于是我到公司后就顺理成章的开始了第三版地图API的开发。
在开发之前,我先仔细研究了高德和百度地图API,并问了自己两个问题:
一、为什么非GIS开发人员,能够用高德、百度地图API解决问题,却用不了ArcGIS,openlayers,leaflet?
二、非GIS开发人员在用互联网地图API时遇到了哪些问题?
下面是我自己的理解:
第一个问题是因为:1、非GIS开发人员不需要自己发布地图数据,地图都是官方提供的,只管用就行。2、互联网地图API的帮助文档和示例都是中文的。
第二个问题,我自己尝试使用后发现:1、互联网地图API的离线使用是个问题,它们都只能在线使用,如果遇到不能访问互联网的情况,就无法使用了,这问题在toG业务中还是挺常见的。2、互联网地图API只能用官方提供的地图坐标,不能集成其它坐标的地图资源。
从这一版起,我们开始尝试在用户体验上对标高德、百度地图API,学习对方的优点,避免对方的问题。
GIS前台没有再继续使用openlayers,而是转向了更为轻巧的leaflet,当时的考虑是:
GIS后台选择了geoserver。因为geoserver的资料比较丰富,能同时支持postGIS和SDE空间数据库。
GIS空间数据库选择了 postGIS,空间分析也主要使用 postGIS 的空间分析函数实现。
桌面端开发继续使用ArcGIS Engine,没有去尝试QGIS,主要原因是,公司之前在ArcGIS Engine上有大量的技术积累,已经形成了成熟的产品,转换成本会很高。
在leaflet的基础上封装了一层自己的接口,原生leaflet接口不对外,当时的考虑是:
当需要复杂的GIS空间分析时,编写geoserver的扩展插件,插件连接PostGIS数据库,通过使用PostGIS空间分析功能,自己编写函数完成空间分析工作。
基于geoserver的rest接口实现地图服务的自动发布。在ArcGIS Engine开发的桌面软件中,先将GIS数据导入到空间数据库,再调用geoserver的rest接口发布地图,最终实现的效果和ArcGIS发布地图的体验相同。
搭建一个门户网站,内容包括帮助文档、地图资源、更新说明等,帮助文档以接口为线索,接口内部有接口说明和调用事例。地图资源中提供可以使用的所有地图,包括互联网地图和自己发布的业务地图,每个地图有个id,根据id就可以在API中轻松加载地图,不需要关心地图服务是如何发布的。
将PostGIS、geoserver、tomcat全部修改为绿色版本,方便项目部署。
开发出第三版后,在部门中使用了一年多,整体反应良好,有一部分懂GIS的同事,之前使用的ArcGIS JS API,用了leaflet封装的上一版地图API后,他们的第一反应是这个好轻便,比ArcGIS JS API 小了好多,加载很快。
上一版发布后,我们留意了用户的使用习惯,大家的使用习惯基本都是先看示例,找到示例后,会直接把代码拷走使用,当示例不完全满足要求时,再去翻看API说明,最好的情况就是示例代码注释完善,一眼就能看懂,拷过来就能用。
当然在使用的过程中,也慢慢发现了一些问题。
懂GIS的同事反馈最强烈的是,能不能把原生接口放开。有个同事,每次都会先自己在网上找leaflet代码,确认能实现了再来找我们,让我们添加这个功能,甚至把资料链接都发过来了,整的我们都挺不好意思的。如果能把leaflet原生接口放开,有很多工作他自己就能解决了。
然后是我自己,当我需要研究一个新功能时,我的第一反应不是去用我自己封装的地图API,而是更愿意使用原生leaflet去写,因为是我觉得自己封装的地图API用起来不够灵活。
天呐!!!
这不就和第一版时,同事说:”你们自己开发的东西,自己都不用”,是一样一样的嘛,如果说第一版时还有Flex语言的因素,那这第三版从内到外都是JS写的,没什么好解释的,就是让人家说中了。
我们平时的工作,除了封装地图API,我们还有其它工作要做,上一版中,感觉我们很大一部分精力被消耗在了封装基础功能这件事上,导致没有时间去研究高级地图功能。如果能把原始接口放开,基础功能就可以直接使用原生接口,我们就有更多时间去研究高级地图功能。
要放开原生接口面临几个问题:
解决方案:
针对坐标偏移问题。
有两个方案,一是给用户提供一个坐标转换的接口,用户自己来转换坐标,但这样对用户不友好。二是对互联网地图瓦片进行纠偏,让地图统一坐标,不再偏移,这是最理想的,但有技术难点。不过,我们最终还是攻克了技术难点,采用了第二种解决方案,详见:leaflet中如何优雅的解决百度、高德地图的偏移问题。
针对用户习惯问题。
为什么百度、高德的地图API并没有使用扁平化接口,大家也没有觉得它们难用?我们研究后得出的结论是:在接口没有特别复杂的前提下,地图API如果能做到:能解决用户问题,bug少,示例丰富,说明文档清晰,大家就会觉得好用。接口是否是扁平化其实不怎么重要。而且,leaflet的原生接口本身就已经非常简洁了,单从简洁性考虑的话,没必要再封装。
针对版本向前兼容问题。
我们决定不对上一个版本兼容,让两个版本同时保留,慢慢过渡,新项目新产品推荐大家用这一版,老项目我们继续提供技术支持,但不再做功能升级。这样经过1、2年后,就能慢慢切换过来。事实证明这个决定是对的,现在已经过去2年多时间,部门里大部分系统都已经切换都了新版本。
技术架构在上一版的基础上做如下调整:
这一版还没有完成,年前刚做完技术预研工作,这里先把整体的思路简单和大家分享一下。
总的来说,上一版已经很好用了,现在已经很少有来自用户的负面反馈。产品还曾在大项目中作为技术中台,提供给其他公司使用,同样效果很好。
但我们自己还是有追求的,和高德、百度地图API相比,我们在下面几点上还需要改进:
这一版的目标是解决上面3个问题,并继续优化用户体验。
前台改为使用mapboxgl,不再使用leaflet,原因有两个:
地图配图使用maputnik,业务数据使用geoserver发布矢量瓦片,正常maputnik是不支持geoserver发布的矢量瓦片的,不过我们已经把这个问题解决了,详见:如何让矢量瓦片配图神器maputnik支持 geoserver
底图数据有两种方案:
地图可视化效果使用deck.gl、L7来实现。
解决OSM地图数据量少的问题。
第五版解决方案有一点不完美的地方是,OSM地图在国内的数据量较少,这也是在我年初的Flag中,想要通过机器学习自动提取建筑物轮廓的起因。
研究三维GIS。
之前的工作一直是二维GIS,三维GIS的业务比较少,也研究了cesium、ArcGIS js API 4.x、three.js 等,并在项目上有过使用,但对三维GIS的整体理解还是不像二维GIS那样通透,不能像二维GIS那样信心十足的给出一个自己满意的开源解决方案,所以在这块儿需要继续努力。
在toG业务的公司中,想要通过开源GIS,打造一套在易用性上比肩高德、百度地图的API,需要注意以下几点:
下面是我推荐的两种组合方案,其实都是前面提到过的,这里汇总一下。
轻量版:leaflet + geoserver + postGIS
这个组合网上的资料多,软件简单易用,普适性强,能满足绝大多数人对二维GIS的需求。
矢量瓦片版:mapboxgl + maputnik + geoserver + postGIS + openmaptiles + three.js
这个组合可以搭建出一套类似高德、百度地图的自定义地图,也可以实现白模三维地图,如果你比较看重地图可视化效果,那么推荐你使用这一套。
好了,就到这里吧。如果觉得对你有帮助,可以通过持续关注和多多分享来支持我们。
原文地址:http://gisarmory.xyz/blog/index.html?blog=GISerSolution
关注《GIS兵器库》, 第一时间获得更多高质量GIS文章。
本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名《GIS兵器库》(包含链接: http://gisarmory.xyz/blog/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。