阅读:4049回复:3
基于udig(开源GIS软件)二次开发
很早时候就想基于GIS写一点东西,前面基于UDIG做过不短时间的二次开发。当前也有geoserver+openlayers的一些开发经验。未来一段时间每天一个文章好好写一下关于GIS或者RCP的一些东西,刚好UDIG就是基于GIS+RCP的产品。OK,话不多说我们先看看UDIG是个什么东西,大概接下来几天想讲讲UDIG。
百度百科中对udig的讲解是: http://baike.baidu.com/view/3049420.htm uDig是一个 open source (EPL and BSD) 桌面应用程序框架,构建在Eclipse RCP和GeoTools(一个开源的Java GIS工具包)上的桌面GIS(地理信息系统) ;是一款开源桌面GIS软件,基于Java和Eclipse平台,可以进行shp格式地图文件的编辑和查看;是一个开源空间数据查看器/编辑器,对OpenGIS标准,关于互联网GIS、网络地图服务器和网络功能服务器有特别的加强。uDig提供一个一般的java平台来用开源组件建设空间应用。 udig的官网地址为: http://udig.refractions.net/ 官网解释为: A GIS Framework for Eclipse ![]() uDig is an open source (EPL and BSD) desktop application framework, built with Eclipse Rich Client (RCP) technology.
翻译大概为:一个基于eclipse的gis框架, udig是一个开元的桌面应用框架,构建于eclipse RCP产品。 具体的定义和功能大家可以看看官网的定义。由于我做udig二次开发的时候是基于udig1.2的版本,目前官网已经更新到了1.4.所以开发中我可能还是用的1.2的框架,但各个主要功能都差不多。 今天主要的工作是让我们下载udig的插件集合或者源码在本地跑起来。 udig 1.4SDK 是基于eclipse 3.7 开发的,如果想保持一切SDK的吻合性,开发中可以下载3.7的eclipse。我这里用的是4.2的eclipse所以才会出现后来的一个报错。 1。 下载udig的SDK,下载地址 :http://udig.refractions.net/download/ 如果只是想使用udig或者看看udig是什么东西,可以下载安装版或者zip版。udig是基于RCP开发的产品。所以使用习惯上和我们的eclipse保持一致。我们下载SDK版本,因为我们要基于udig做一次二次应用。 趁着现在正在下载SDK,我们乱扯一下。UDIG目前可以对多个数据源的信息进行展示,常见的我们的wms服务、shp文件、postgis等都会支持.另外对于SHP(我在开发中主要用到SHP,通过geotools生成shp然后加载到udig里)支持灰常强大,样式、编辑等等很方便。 我们在udig中常用到的几个视图我一会等SDK下载好了给大家截图说明一下。 2.下载完成后,将 udig-1.4.0-sdk.zip 解压到任意目录。打开eclipse(推荐使用RCP /RAP开发版的eclipse),打开后配置一下target。 2.1: window-->preferences. ![]() 2.2 在右侧点击add新加一个target或者在当期target中进行添加我们的udig SDK,因为我的这个eclipse目前只是用来做UDIG二次开发,所以我选择在当前target中进行编辑。 ![]() 当前显示我们的eclipse中自带的查件有600多个。我们选择add 增加我们的udig的SDK ![]() 这里我们将SDK进行了解压,选择目录,next后 ![]() 点击 finish后我们的SDK挂载完成。 2.3 一切完成后,我们可以看到我们的plugins-ins视图中多了很多的插件。 ![]() 2.4 在plugin-ins视图中我们找到一个 net.refractios.udig这个插件,这个插件就是UDIG这个项目的启动插件,product文件也在这个插件中。在这个插件上我们右键--》import as 选择source 或者bin都可以,完成后,我们切换到 package explorer ,可以看到net.refrations.udig 这个插件已经在这里,我们点开会发现udig.product 文件(这个文件的含义以后我会在RCP的帖子里说明)。点开product文件。 ![]() 我们点击 lanunch an eclipse application 在eclipse应用中启动UDIG。 2.4 启动后如果正常那一切OK,但我这边启动后我们发现报错了,提示 java.lang.RuntimeException: No application id has been found. at org.eclipse.equinox.internal.app.EclipseAppContainer.startDefaultApp(EclipseAppContainer.java:242) at org.eclipse.equinox.internal.app.MainApplicationLauncher.run(MainApplicationLauncher.java:29) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:354) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:181) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:636) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591) at org.eclipse.equinox.launcher.Main.run(Main.java:1450) at org.eclipse.equinox.launcher.Main.main(Main.java:1426) 还有一堆巴拉巴拉的日志说明 缺失插件(!MESSAGE Missing imported package。。。。。) 我们找一下是否哪些插件有异常,因为UDIG是基于feature管理,因此打开 ![]() dependencies后发现只有两个feature,理论上来说语言包插件是不会出现多大问题,我们点开第一个freature, ![]() 这我们发现UDIG引用的RCP插件版本为3.7,我当前的环境是4.2因此是插件版本的问题。反回来我们在udig.product 中补一个4.2的RCP feature即可。 补后启动:OK! ![]() 好了,我们在插件模式下正常启动了UDIG,未来的博客里我会先介绍一下UDIG的一个简单使用。 |
|
|
1楼#
发布于:2015-06-29 12:57
关于UDIG的使用上是在不知道怎么去讲,从网上搜了一下,找到一些文档讲解的还不错,可能有些同学对udig的使用上感觉用E文不是很爽,过几天我会发出来udig的一个汉化插件集合供大家下载。
使用上真正的话还要参见udig的官网文档http://udig.refractions.net/users/ ,其中也有视频有文档。 网上搜到一个文档说明的也算可以 http://live.osgeo.org/zh/quickstart/udig_quickstart.html 只是有很多细节方面没有提到,譬如样式属性等等。这些如果有人感兴趣可以留言我对针对他感兴趣的地方单独列出来。 udig使用上我不做太多描述,下一次开始真正开始讲udig的二次开发,从最基础的解说每个插件的功能开始,和创建一个简单的应用,打包等。 |
|
|
2楼#
发布于:2015-06-29 12:58
今天主要说明一下udig里大部分插件的含义。当然有一些插件对于我们二次开发可能几乎用不到这里可能没有说明到。udig这个产品在插件命名上还是比较规范的,通过相应的插件名称我们基本也可以看出来这个插件的作用。
从插件名称的排序开始说起: 以下介绍均为本人自己理解,如果哪里不对或者有更好的见解请及时联系我纠正以下。 1. net.refractions.udig UDIG的产品运行插件。该插件内部其实并没有代码,里面包含了product等文件。可以看做是启动插件。 2. net.refractions.udig.browser ,UDIG中浏览器插件,内部封装了udig中对浏览器的支持。并包含了udig中支持协议和License信息等。 3.net.refractions.udig.catalog ,这个系列的插件包含了udig对当前数据源的支持和呈现,具体包含了有: net.refractions.udig.catalog.arcgrid,栅格化地图支持 net.refractions.udig.catalog.db2,DB2数据库支持 net.refractions.udig.catalog.geotiff ,tiff格式图片支持 net.refractions.udig.catalog.geotiff , shp文件支持 net.refractions.udig.catalog.wms , WMS服务支持 …….后面还有很多我就不一一介绍了,大家看一下catalog这个下面的插件,基本最后一个单词就代表支持类型,其中net.refractions.udig.catalog.ui插件是该体系插件集合中的UI呈现部分,包含几个视图view(catalog、serach)和基础GIS服务图层导入导出功能。其中我们需要重点关注的有geotools、wms、postgis、wmt这几个插件,因为在后面二次开发的话我们会经常用到。 我注意观察了一下wmt插件还是原来的1.2版本(1.2版本的wmt服务目前还支持OSM-openstreetmap),目前看来想支持google、baidu等地图还需要我们自己重写这个插件了。笔者已经有过这方面经验,以后的文章中我会提到如果扩展udig让其支持online/offline的其他地图服务瓦片和图层。 4. net.refractions.udig.core ,UDIG的一个核心插件、内部提供了注册UDIG自定义扩展点服务的功能。并且内部封装了多个适配器、以及feature过滤接口和适配器,可以为后续二次开发提供图层过滤显示、自定义扩展点加载等。 5. net.refractions.udig.feature.editor.. UDIG中对feature进行编辑支持的插件。内部添加视图有:feature editor(提供当前焦点图层元素编辑)、feature(展示当前图层所有feature)。如果我们要将自己发布的图层进行一些小的编辑或者操作可以用到里面某些方法。 6. net.refractions.udig.help。 UDIG帮助体系主插件。 7. net.refractions.udig.info。 UDIG中信息插件,内部包含的功能有地图中查看某一个经纬度点下的features信息、测距。并提供视图进行查看。实际开发中经常会利用这两个功能进行一些扩展开发,例如我查找某一个点下feature并进行编辑、点击某一个feature进行一些关联性事件等。该插件主要提供一些当前地图上图层信息查看服务。 8、 net.refractions.udig.jai.macosx 。该插件在platform filter中添加的是 (osgi.os=macosx) 所以我也不知道是干嘛的。 9. net.refractions.udig.legend 。该插件提供一些说明和透视图定义。UDIG中的两个透视图 map和style就在该插件中定义。 10. net.refractions.udig.libs 。该系列包含有三个插件,主要我用的还是这个。UDIG中所有插件需要的第三方JAR包都在此插件中进行集中绑定。包含我们的数据库访问JDBC包、geotoools开发包、chart包等等。 11. net.refractions.udig.printing 。该功能性插件包含三个。主要是支持udig中对当前地图或者图层的打印支持。其中三个插件里:model是打印模型的支持。Model.edit是对当前模型进行可编辑支持、ui提供UI界面支持。 12. net.refractions.udig.project 。 project这个下面有4个插件。这几个插件是UDIG中很重要的插件,如果要基于udig进行二次,这几个插件是肯定要用到的。UDIG中创建项目、创建地图、创建图层都要用到。包括UDIG中地图 mapeditor也是在该插件中进行实现。 13. net.refractions.udig.render 该插件集合下面有5个插件。我们重点关注后面带basic的三个插件。这三个插件提供了wms服务(加载web map server)、wmt(web map tiles)、gridcoverage。 其中我们如果后续要扩展加载geoserver中wms服务器的话和让udig支持google map、baidu map的话就需要扩展wms.basic wmt.basic这两个插件。 14. net.refractions.udig.style 。UDIG中对图层的样式编辑就在这里了。地图好看不好看,哪些属性该显示、哪些元素根本就不应该让显示出来就看我们style配置的如何了。其中sld主要针对于shp图层。Wms主要针对于wms 网络服务图层的配置。后面我会主要介绍一些sld如何配置和怎么样通过geotools的代码动态修改当前地图的样式和显示效果。 15. net.refractions.udig.tool。 UDIG中工具类的插件集合。其中主要有三个。Default主要包含基础性的一些工具,譬如地图放大、缩放、缩放一定比例等。Select包含了查看性的一些工具。譬如查看当前bbox下选择的所有feature、显示当前的feature等。Edit主要包含对当前图层中feature或者图层的编辑工具,包含栅格图层中某一个feature、修改某个feature值等。 16. net.refractions.udig.tutorials 该系列的插件我就不讲了。基本如果基于UDIG二次开发的话这里面的插件用的较少(反正我是还没用到)。 总体来说基于UDIG二次开发的话,首先要了解RCP的一个体系结构另外对GIS有一定了解。当然我会在后面的介绍中对RCP开发和GIS常用开发做一些总结和指导。 今天到这里为止,下一篇文章我会开始创建一个小项目,该项目基于UDIG,有菜单有视图,可以通过菜单将csv或者文本文件导入程序,程序讲数据做成shp文件在通过resource加载到udig的地图中。 |
|
|
3楼#
发布于:2015-06-29 12:58
本次主要基于udig做一个简单的二次开发实例,假如我们手里有一批经纬度的信息,想直接在地图上查看。当然这时候方法非常多,譬如我通过postgis+geoserver+openlayers很容易实现,或者在udig里有create point也可以直接绘制,还有通过openlayers的marker只需要一个简单的txt文件也行,完全用不到二次开发,但这里只是说做一个简单的范例看看udig是怎么样加载地图数据和怎么样我们可以生成一份地图数据。 本次我们生成比较通用的shp文件(postgis等以后再说),生成shp我们这里需要用到geotools,不过udig里已经集成进去了geotools的jar包,我们只需要在我们自己的插件里引用net.refractions.udig.libs这个插件即可。闲话不多说,我们开始先创建一个插件项目(因为是DEMO,所以就一个插件,记得勾选RCP)。 1、 创建项目,如图: ![]() 1、 2、创建几个包,如图: ![]() 其中command下我们生成一个类ImportDataCommand extends AbstractHandler ,pojo下我们生成一个基础的点实体类 DemoPoint { private double lon ; private double lat ; private String site_name ; public double getLon() { return lon; } public void setLon(double lon) { this.lon = lon; } public double getLat() { return lat; } public void setLat(double lat) { this.lat = lat; } public String getSite_name() { return site_name; } public void setSite_name(String site_name) { this.site_name = site_name; } } 3、1、 Command中实现 public Object execute(ExecutionEvent event) throws ExecutionException {} 这个方法。里面需要的操作有 a、 a 弹出选择文件对话框,要求使用者导入需要导入的经纬度文件(文件格式预先定义好)。 b、 b 读取文件转换为实体数据 c、 c 根据实体数据生成shp 图层数据文件 d、 d 将shp图层数据文件加载显示到udig的地图中 1、 4、多话不说,我贴代码 a、 a 弹出对话框要求用户选择需要导入的文件。 //弹出选择文件对话框 要求选择文件,要求格式csv 字段要求为LON,LAT,SITE_NAME FileDialog dialog = new FileDialog(Display.getDefault().getActiveShell(), SWT.OPEN); dialog.setText("请选择要导入的文件"); String path = dialog.open(); if(path != null) { //选择的文件不为空 开始读取文件信息 转换为实体数据 } b、 b 解析文件,转换为我们需要的实体数据 /** * 解析文件,转换为我们需要的实体数据 * @param path 文件路径 * @return 演示用的点信息集合 文件不存在时返回空 */ private Collection<DemoPoint> parseFile(String path) { List<DemoPoint> points = new LinkedList<DemoPoint>(); BufferedReader br = null; try { br = new BufferedReader(new FileReader(path)); String line = br.readLine() ;//跳过表头 while((line = br.readLine()) != null) { String[] _ss = line.split(","); //由于是演示 所以这里不做数据检查 DemoPoint point = new DemoPoint(); point.setLon(Double.valueOf(_ss[0])); point.setLat(Double.valueOf(_ss[1])); point.setSite_name(_ss[2]); points.add(point); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if(br != null) { try { br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return points ; } c、c 生成shp图层文件 /** * 根据数据生成图层文件 * @param data * @return 返回生成好的图层文件地图 SHP图层 数据保存在当前workspace下 */ protected String createShpData(Collection<DemoPoint> data){ //拿到当前的workspace路径 String ws = Platform.getInstanceLocation().getURL().getPath(); //文件名用当前系统时间 String layerName = String.valueOf(System.currentTimeMillis()) ; File shpFile = new File(ws , layerName + ".shp"); //图层的属性配置 坐标系采用4326 String layerFeatures = "GEOM:Point:srid=4326,LON:Double,LAT:Double,SITE_NAME:String" ; FeatureWriter<SimpleFeatureType, SimpleFeature> fw = null; try { ShapefileDataStore myData = new ShapefileDataStore(shpFile .toURI().toURL()); myData.setStringCharset(Charset.forName("GBK")); SimpleFeatureType ft = DataUtilities.createType(layerName, layerFeatures); myData.createSchema( ft); //手动事物 发现有时候给自动回出些问题 Transaction tran = new DefaultTransaction(); fw = myData.getFeatureWriter(layerName, tran); GeometryFactory gf = new GeometryFactory(); for(DemoPoint point : data) { Geometry geo = gf.createPoint(new Coordinate(point.getLon(), point.getLat())); SimpleFeature sf = (SimpleFeature) fw.next(); sf.setDefaultGeometry(geo); //添加属性 sf.setAttribute("SITE_NAME",point.getSite_name()); fw.write(); } fw.close(); tran.commit(); tran.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SchemaException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { if(fw != null) fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return shpFile.getAbsolutePath(); } d、 d 创建一个新的地图,加载我们刚才生成的shp图层文件 /** * 创建一个新地图并打开shp图层文件 * @param path 文件路径 */ protected void createMapAndOpenShp(String path) { IRepository local = CatalogPlugin.getDefault().getLocal(); IService service = null; List<IGeoResource> resources = null; try { service = local.acquire( URLUtils.fileToURL(new File(path)), new NullProgressMonitor()); resources = (List<IGeoResource>) service.resources(new NullProgressMonitor()); //发布 ApplicationGIS.createAndOpenMap(resources); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 5、注意事项 插件中引用要因为udig的applicationgis类,并且需要生成图层,所以在当前插件里我们要引入5个插件(本次的开发环境udig为1.2的版本): ![]() 创建product文件后,最好引入udig的所有包(新手必须). 6、1、 好了 打开看看效果 ![]() ![]() ![]() 代码和演示数据在附件中可以下载,有问题请留言或者加我们的 群 251615521 251615521251615521251615521
|
|
|