接手一个监控类项目,里面用了geotools为地理信息处理核心工具,官方文档及例子还是比较完善,但是作为快速入坑,暂时只关注几个核心问题。
官网 http://www.geotools.org/
github https://github.com/geotools/geotools
使用版本:13.x 官网介绍为13.x为development版本,12.x为stable,但是开发里面最新为14.x 个人来说一般新的工程一般都选stable,或者正在构建的版本的前一个版本,教程标注版本我认为很重要,因为有些项目版本不一样,使用的方法或者api都有相应变化。
对于监控类项目疑似的坑:看描述框架的发展描述以后抛弃UI方面的发展,专注于地理数据的各种处理转换,也就是说UI方面的参考资料会很少。
框架解决geo通用问题,也就是解决地理数据内存优化的问题,没有详细看过代码,但是机制类似按需加载,需要的时候才从文件中读取,但是对于监控类比较快速的需求,地理数据对象本来就不多,就对内存优化就没那么高了,需要一次加载到内存中进行处理。
基本用法:
数据文件的加载
File file = new File("path of .shp file");
ShapefileDataStore shapefile = new ShapefileDataStore(file.toURI().toURL());
SimpleFeatureSource featureSource = shapefile.getFeatureSource();
样式文件的加载
StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory();
File file = new File("path of .sld file");
SLDParser stylereader = new SLDParser(styleFactory, file.toURI().toURL());
Style[] stylearray = stylereader.readXML();
Style style = stylearray[0];
承载数据文件及样式文件的Layer
FeatureLayer tempLayer = new FeatureLayer(featureSource, style);
承载各个Layer的Context
MapContent context = new MapContent();
context.addLayers(tempLayer);
绘制图形的render类
StreamingRenderer renderer = new StreamingRenderer();
renderer.setMapContent(this.content);
geotools提供了一个基本的UI类但是都是在unsupported里面,也就是不支持了对于Java有Swing和SWT,由于项目基于Eclipse的RCP,所以用的SWT的类叫SwtMapPane
SwtMapPane mapPane = new SwtMapPane(mainComposite, SWT.BORDER | SWT.NO_BACKGROUND);
mapPane.setMapContent(context); mapPane.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
StreamingRenderer renderer = new StreamingRenderer();
mapPane.setRenderer(renderer);
SwtMapPane提供了一些基本工具
mapPane.setCursorTool(new PanTool());
还有一些其他工具,主要有重置,放大,缩小。
如何旋转地图:
官网上虽然有写原理,但是不够直接,自己google了半天才找到。
CoordinateReferenceSystem currentCRS=mapPane.getMapContent()
.getCoordinateReferenceSystem();
CoordinateReferenceSystem transformedCRS = currentCRS;
// Create the rotation transform
AffineTransform rotation = new AffineTransform();
rotation.rotate(Math.PI/36);
// Creates the math transform
MathTransform transform = ProjectiveTransform.create(rotation);
// Rotates the CRS
transformedCRS = new DefaultDerivedCRS("rotate", currentCRS, transform,
currentCRS.getCoordinateSystem());
mapPane.getMapContent().getViewport().setCoordinateReferenceSystem(transformedCRS);
基本上还是利用CoordinateReferenceSystem,放大,缩小,平移的原理可以看提供的Tools的源代码。
坐标转换:
SwtMapPane中一看有一个WorldToScreen以及ScreenToWorld,就知道换转肯定要用这两个类,但是我捣鼓了半天发现没有获得到有用的转换,后面才发现了原因,为了不让后面的人为了这个坑,大致讲解下原理。
地理图形有各种坐标系,即使是同一个坐标系也有多种表达方法,之前从MIF文件转换为shp文件后在界面上显示的文件就有问题,后面通过udig进行了格式转换,转换为了WGS84坐标后显示才正常,由于有自定义层,我也采用了WGS84坐标,综合显示看起来一切正常,但是坐标转换的时候就出问题了,原因就是坐标系的不同。
解决原理:
mapPane.getMapContent().getCoordinateReferenceSystem()
这个获得的坐标系系统是一个通用的,具体代码没有详细看,总之如果你的数据文件中有多个坐标系,这个方法获得的是其中一个坐标系。如果你要获得屏幕到你目标坐标系的位置就需要先将屏幕坐标转换到MapContent的坐标,代码可以看提供的Tools工具的源码,然后将这个坐标与你的目标坐标系进行转换,才得到的你希望的的坐标,反之亦然。
暂时写到这,第一次写技术心得,内容带有自己的主观臆断。入坑需谨慎。