1. 今天解析shp文件的时候,如果是点或者线就没问题,但是面就会解析报一下错误:
java.lang.NoSuchMethodError: org.locationtech.jts.geom.Polygon.getExteriorRing()Lorg/locationtech/jts/geom/LineString;
然后一通好找,发现是依赖包的版本问题,用这两个版本,就好了:geotools: 21.0 JTS: compile group: 'org.locationtech.jts', name: 'jts-core', version: '1.16.1'
2. wkt和Geometry互转
wkt转Geometry:
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKTReader;
WKTReader wktReader = new WKTReader();
Geometry geometry = wktReader.read(wkt);
geometry.setSRID(4326);
Geometry转wkt:
String wkt = geometry != null ? geometry.toText() : "";
3. shp解析核心部分代码
@ApiOperation(value = "导入shp文件", notes = "导入shp文件")
@RequestMapping(value = "shp", method = {RequestMethod.GET, RequestMethod.POST})
public Result shp(MultipartFile[] file, int tag) {
try {
File ff = null;
if (ff != null) {
Map<String, Object> columnsMap = new HashMap<>();
List<Columns> columns = new ArrayList<>();
ShapeLoader loader = new ShapeLoader(ff);
int i = 0;
if (loader != null) {
FeatureCollection collection = loader.getFeatureCollection();
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
i++;
Feature feature = features.next();
GeoData geoData = new GeoData();
// 获取geometry列的属性名称
String geometryColumnName = feature.getDefaultGeometryProperty().getName().toString();
Geometry geometry = (Geometry) ((SimpleFeature) feature).getDefaultGeometry();
Geometry targetGeometry = loader.transform(geometry);
geoData.setGeometry(targetGeometry);
geoData.setWkt(geoData.getWkt());
geoDataService.saveData(geoData);
PropertyValues prop = new PropertyValues();
// 获取所有属性列表
Collection<Property> properties = feature.getProperties();//(
if (properties != null) {
Map<String, Object> map = new HashMap<>();
properties.forEach(property -> {
String name = property.getName().toString(); // 获取属性名称
if (!StringUtils.equalsIgnoreCase(geometryColumnName, name)) {
String type = property.getDescriptor().getType().getBinding().getSimpleName();
columnsMap.put(name, type);
System.out.println(name + "===" + property.getDescriptor().getType().getBinding().getSimpleName() + "===" + property.getValue());
Object value = property.getValue();
if("Double".equals(type)){
value =BeanUtil.isEmpty(value)?"0":new BigDecimal(BeanUtil.nullToEmpty(value)).toPlainString();
}
map.put(name, value);
}
});
prop.setValues(JSONObject.toJSONString(map));
prop.setGeometryType(geometry.getGeometryType());
prop.setSource("shp");
}
}
}
}
logger.info("导入数据完成,共计{}条", i);
return new Result().setSuccess("导入成功");
} else {
logger.warn("未找到shp后缀文件");
return new Result().setError("请上传完整的文件。包含[shp,shx,bdf,prj]");
}
} catch (Exception e) {
e.printStackTrace();
}
return new Result().setSuccess("导入成功!");
}
Shape文件加载工具:
package com.trgis.thematicdata.util;
import org.geotools.data.FeatureSource;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.feature.FeatureCollection;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.type.FeatureType;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.Charset;
/**
* Shape文件加载工具
*/
public class ShapeLoader {
private File shapefile; // 保存需要解析的shapefile文件
private FeatureSource featureSource; // 读取出来的FeatureSource
private CoordinateReferenceSystem crs; // 获取shape文件的坐标系统
private MathTransform mathTransform; // 获取坐标系转换算法数据
public ShapeLoader(File shapefile) throws Exception {
this.shapefile = shapefile;
this.featureSource = loadFeatureSource(shapefile);
}
/**
* 计算从shapefile转到目标坐标系统的数学参数
* @param targetCRS
* @return
*/
public MathTransform calculateMathTransform(CoordinateReferenceSystem targetCRS) throws FactoryException {
try {
FeatureType schema = this.featureSource.getSchema();
System.out.println("this.featureSource.getSchema() = " + schema);
this.crs = this.featureSource.getSchema().getCoordinateReferenceSystem();
this.mathTransform = CRS.findMathTransform(this.crs,targetCRS,true);
return this.mathTransform;
} catch (FactoryException e) {
e.printStackTrace();
throw e;
}
}
public Geometry transform(Geometry geometry) throws TransformException, FactoryException {
if(this.mathTransform == null) {
// 默认转到WGS84坐标系
calculateMathTransform(CRS.decode(DefaultGISConfig.EPSG4326,true));
}
Geometry geom = JTS.transform(geometry,this.mathTransform);
geom.setSRID(DefaultGISConfig.SRID);
return geom;
}
/**
* 读取shapefile获取FeatureSource
* @param shapefile
*/
private FeatureSource loadFeatureSource(File shapefile) {
if(shapefile != null) {
if(this.shapefile == null) this.shapefile = shapefile;
ShapefileDataStore dataStore = null;
try {
dataStore = new ShapefileDataStore(shapefile.toURI().toURL());
if(dataStore != null) {
this.featureSource = dataStore.getFeatureSource();
dataStore.setCharset(Charset.forName("UTF-8"));
if(this.featureSource != null){
// 获取坐标系统
this.crs = featureSource.getSchema().getCoordinateReferenceSystem();
}
} else {
throw new IOException("加载shapefile时出错");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return this.featureSource;
}
public FeatureSource getFeatureSource() {
return featureSource;
}
public FeatureCollection getFeatureCollection() throws IOException {
if(this.getFeatureSource() != null) {
return getFeatureSource().getFeatures();
}
return null;
}
}