geoserver源码学习与扩展——kml/kmz转shapefile文件
geoserver通过工作空间Workspace-数据源DataStore-图层Layer管理地理数据,默认只支持shapefile格式的文件发布,不支持kml/kmz、csv的文件格式,所以存在将这些数据转换为shapefile的需求。
kml/kmz的文件解析基于JavaAPIforKml包完成,该包支持kml和kmz的文件解析;
import de.micromata.opengis.kml.v_2_2_0.Kml; /*解析kml文件*/
Kml kml = Kml.unmarshal(kmlFile);
processKml(kml,typeName); /*解析kmz文件*/
Kml[] kmls = Kml.unmarshalFromKmz(kmzFile);
for(Kml kml : kmls){
processKml(kml,typeName);
}
将Kml转换为shapefile文件也是通过如下2步完成:
1、将Kml转换为FeatureCollection;
2、利用ShapefileDumper类将FeatureCollection转存到硬盘(详见http://www.cnblogs.com/HandyLi/p/8616115.html,不再赘述);
/*
* Kml to FeatureCollection
*/
private void processKml(Kml kml, String typeName){
try{
Feature kmlFeature = kml.getFeature();
if(kmlFeature instanceof Document){
Document doc = (Document)kmlFeature; List<Feature> folderList = doc.getFeature();
for(Feature folder: folderList){
if(folder instanceof Folder){
//one Folder to one SimpleFeatureCollection
//get Field info
List<String> typeSpec = new ArrayList<String>();
typeSpec.add("the_geom:Point:srid="+ SRID);// <- the geometry attribute: Point type
typeSpec.add("name:String");
List<SimpleField> simpleFields = doc.getSchema().get(0).getSimpleField();
for(SimpleField simField : simpleFields){
String fieldType = simField.getType();
String fieldName = simField.getName();
typeSpec.add(fieldName + ":" + fieldType);
}
if(CreateCluster)//add Field:cluster
typeSpec.add("cluster:String");
String typeSpecs = String.join(",", typeSpec);
final SimpleFeatureType TYPE = DataUtilities.createType(typeName,
typeSpecs // all attributes
); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
/*
* We create a FeatureCollection into which we will put each Feature created from a record
* in the input csv data file
*/
ListFeatureCollection collection = new ListFeatureCollection(TYPE); List<Feature> placeList = ((Folder) folder).getFeature();
for(Feature place: placeList){
if(place instanceof Placemark){
Geometry kmlGeo = ((Placemark)place).getGeometry();
com.vividsolutions.jts.geom.Geometry jtsGeom = toJTSGeometry(kmlGeo);
featureBuilder.add(jtsGeom);
//Placemark name value
featureBuilder.add(((Placemark)place).getName()); ExtendedData exData = ((Placemark)place).getExtendedData();
List<SimpleData> simDatas = exData.getSchemaData().get(0).getSimpleData();
for(SimpleData sData : simDatas){
featureBuilder.add(sData.getValue());
}
if(CreateCluster)
featureBuilder.add(""); //add cluster field value
SimpleFeature feature = featureBuilder.buildFeature(null);
collection.add(feature);
}
}
// write to shapefile
writeShapeFile(collection);
}
}
}
}
catch(Exception ex){
throw new IllegalArgumentException("KML parse error: " + ex.getMessage());
}
}
注意:toJTSGeometry函数用于将Kml封装的Geometry类转换为JTS库里的Geometry类。
/*
* de.micromata.opengis.kml.v_2_2_0.Geometry transform to com.vividsolutions.jts.geom.Geometry
*/
private com.vividsolutions.jts.geom.Geometry toJTSGeometry(Geometry kmlGeo){
if(kmlGeo == null)
return null; GeometryFactory geoFactory = JTSFactoryFinder.getGeometryFactory(null);
if(kmlGeo instanceof MultiGeometry){
List<com.vividsolutions.jts.geom.Geometry> geoList = new ArrayList<com.vividsolutions.jts.geom.Geometry>();
List<Geometry> kmlGeoList = ((MultiGeometry)kmlGeo).getGeometry();
for(Geometry kmlSubGeo : kmlGeoList){
geoList.add(toJTSGeometry(kmlSubGeo));
}
GeometryCollection gc = geoFactory.createGeometryCollection(geoList.toArray(new com.vividsolutions.jts.geom.Geometry[0]));
return gc;
}
else if(kmlGeo instanceof de.micromata.opengis.kml.v_2_2_0.Point){
double dLong = ((de.micromata.opengis.kml.v_2_2_0.Point)kmlGeo).getCoordinates().get(0).getLongitude();
double dLat = ((de.micromata.opengis.kml.v_2_2_0.Point)kmlGeo).getCoordinates().get(0).getLatitude();
return geoFactory.createPoint(new Coordinate(dLong, dLat));
}
else if(kmlGeo instanceof LineString){
List<Coordinate> geoCoords = new ArrayList<Coordinate>(); List<de.micromata.opengis.kml.v_2_2_0.Coordinate> coordList = ((LineString)kmlGeo).getCoordinates();
for(de.micromata.opengis.kml.v_2_2_0.Coordinate kmlCoord : coordList){
double dLong = kmlCoord.getLongitude();
double dLat = kmlCoord.getLatitude();
geoCoords.add(new Coordinate(dLong, dLat));
}
return geoFactory.createLineString(geoCoords.toArray(new Coordinate[0]));
}
else if(kmlGeo instanceof LinearRing){
List<Coordinate> geoCoords = new ArrayList<Coordinate>();
List<de.micromata.opengis.kml.v_2_2_0.Coordinate> coordList = ((LinearRing)kmlGeo).getCoordinates();
for(de.micromata.opengis.kml.v_2_2_0.Coordinate kmlCoord : coordList){
double dLong = kmlCoord.getLongitude();
double dLat = kmlCoord.getLatitude();
geoCoords.add(new Coordinate(dLong, dLat));
}
return geoFactory.createLinearRing(geoCoords.toArray(new Coordinate[0]));
}
else if(kmlGeo instanceof Polygon){
List<com.vividsolutions.jts.geom.LinearRing> holes = new ArrayList<com.vividsolutions.jts.geom.LinearRing>();
com.vividsolutions.jts.geom.LinearRing shell = convertLinearRing(geoFactory, ((Polygon)kmlGeo).getOuterBoundaryIs().getLinearRing());
List<Boundary> innerBoundaryList = ((Polygon)kmlGeo).getInnerBoundaryIs();
for(Boundary inner : innerBoundaryList){
holes.add(convertLinearRing(geoFactory,inner.getLinearRing()));
}
return geoFactory.createPolygon(shell, holes.toArray(new com.vividsolutions.jts.geom.LinearRing[0]));
}
else{
throw new IllegalArgumentException("Unrecognized geometry type: " + kmlGeo);
}
}
private com.vividsolutions.jts.geom.LinearRing convertLinearRing(GeometryFactory geoFactory, LinearRing geometry){
List<Coordinate> geoCoords = new ArrayList<Coordinate>();
List<de.micromata.opengis.kml.v_2_2_0.Coordinate> coordList = (geometry).getCoordinates();
for(de.micromata.opengis.kml.v_2_2_0.Coordinate kmlCoord : coordList){
double dLong = kmlCoord.getLongitude();
double dLat = kmlCoord.getLatitude();
geoCoords.add(new Coordinate(dLong, dLat));
}
return geoFactory.createLinearRing(geoCoords.toArray(new Coordinate[0])); }
geoserver源码学习与扩展——kml/kmz转shapefile文件的更多相关文章
- geoserver源码学习与扩展——跨域访问配置
在 geoserver源码学习与扩展——restAPI访问 博客中提到了geoserver的跨域参数设置,本文详细讲一下geoserver的跨域访问配置. geoserver的跨域访问依赖java-p ...
- geoserver源码学习与扩展——restAPI访问
产生这篇文章的想法是在前端通过js调用restAPI时,总是不成功,发送ajax请求时还总是出现类似跨域的问题,后来查找才发现,默认情况下restAPI的访问都需要管理员权限,而通过ajax请求传输用 ...
- geoserver源码学习与扩展——自动发布shapefile图层
geoserver通过工作空间Workspace-数据源DataStore-图层Layer管理地理数据,这些信息都通过Catalog进行组织和管理,要完成自动发布只需要在Catalog中增加相应的信息 ...
- geoserver源码学习与扩展——增加服务接口
参看:http://www.cnblogs.com/sillyemperor/archive/2011/01/11/1929420.html 上文写的很详细了.
- geoserver源码学习与扩展——CSV转shapefile文件
基于geotools实现csv转换为shapefile文件. 1.读取CSV文件,将其装入FeatureCollection: 2.利用ShapefileDumper类将FeatureCollecti ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
- MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)
前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...
- MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)
前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...
- ddms(基于 Express 的表单管理系统)源码学习
ddms是基于express的一个表单管理系统,今天抽时间看了下它的代码,其实算不上源码学习,只是对它其中一些小的开发技巧做一些记录,希望以后在项目开发中能够实践下. 数据层封装 模块只对外暴露mod ...
随机推荐
- log4j中将SocketAppender将日志内容发送到远程服务器
1.服务端配置 1)服务端配置文件log4j-server.properties #Define a narrow log category. A category like debug will p ...
- ubuntu首次给root用户设置密码和root用户登录设置
1 ubuntu首次给root用户设置密码 给root用户设置密码输入命令sudo passwd,然后系统会让你输入密码,这时输入的密码就是root用户的密码了,设置完成之后就可以切换root用户登录 ...
- UNION ALL与UNION
UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每条 SELECT 语句中的列 ...
- Nginx/LVS/HAProxy 负载均衡软件的优缺点对比
Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,一般对负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术,具体的应用需求还得具体分析. 如果是中小型的Web应用,比 ...
- Powershell Get-registerkey(susid)
$servers=get-content D:\serverregister.txt Get-registerkey -ComputerName $servers | select computer, ...
- <2014 03 18> Term BreakPoint
- IO 包中的其他类
打印流 PrintWriter 和 PrintWriter 直接操作输入流和文件 序列流 SequenceInputStream 对多个输入流进行合并 操作对象 ObjectInputStream 和 ...
- AHOI2019退役记
$DAY\quad -1$: 连作业都不写了来刷题... 希望能长点$RP$吧... 反正也是抱着退役的心情来考试... 我要是到了周日还不出长门我就退游!!! $DAY\quad 0$: 早上一起来 ...
- python创建进程的两种方式
1.方式1 import time import multiprocessing def task(arg): time.sleep(2) print(arg) def run(): # 进程1 p1 ...
- Flask(4)- flask请求上下文源码解读、http聊天室单聊/群聊(基于gevent-websocket)
一.flask请求上下文源码解读 通过上篇源码分析,我们知道了有请求发来的时候就执行了app(Flask的实例化对象)的__call__方法,而__call__方法返回了app的wsgi_app(en ...