前言
記錄一下工作中使用GeoTools解析shp過程。
預設上傳shp檔案為zip格式檔案,shp壓縮包內容如下圖
程式碼流程
1.解壓zip檔案
// 解壓縮zip包
File shpFile = ShpParseUtil.unShapeZip(file.getInputStream(), tempDir);
2.解析shp檔案內容
parseShapeFile(shpFile);
public static void parseShapeFile(File file) throws Exception {
Map<String, Object> map = new HashMap<>(1);
map.put("url", file.toURI().toURL());
DataStore dataStore = DataStoreFinder.getDataStore(map);
//字元轉碼,防止中文亂碼
ShapefileDataStore shpStore = (ShapefileDataStore) dataStore;
// shpStore.setCharset(StandardCharsets.UTF_8);
shpStore.setCharset(Charset.forName("GBK"));
SimpleFeatureSource source = shpStore.getFeatureSource();
SimpleFeatureType schema = source.getSchema();
Query query = new Query(schema.getTypeName());
FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(query);
//獲取shp檔案內容
try (FeatureIterator<SimpleFeature> features = collection.features()) {
while (features.hasNext()) {
SimpleFeature feature = features.next();
String name = feature.getName().toString();
System.out.println("名稱:" + name);
//獲取座標系
CoordinateReferenceSystem coordinateReferenceSystem = feature.getFeatureType().getCoordinateReferenceSystem();
if (coordinateReferenceSystem != null) {
ReferenceIdentifier referenceIdentifier = coordinateReferenceSystem.getCoordinateSystem().getName();
String code = referenceIdentifier.getCode();
System.out.println("座標系:" + code);
}
//獲取shp檔案的屬性資訊
// List<Object> attributes = feature.getAttributes();
String geomType = feature.getFeatureType().getDescriptor("the_geom").getType().getName().toString();
System.out.println("屬性值數量:" + feature.getValue().size());
Map<String, Object> propertoryMap = feature.getValue().stream()
.filter(property -> !"the_geom".equals(property.getName().toString()))
.collect(Collectors.toMap(property -> property.getName().toString(), Property::getValue));
for (Property property : feature.getValue()) {
String propertyName = property.getName().toString();
String typeName = property.getType().getName().toString();
System.out.println("屬性名:" + propertyName + "型別:" + typeName + " 屬性值:" + property.getValue());
}
Geometry geom = (Geometry) feature.getAttribute("the_geom");
String geometryType = geom.getGeometryType();
// 封裝為geojson格式
String geoJson = convertToJson(geom,propertoryMap);
}
}
}
工具類
public class ShpParseUtil {
/**
* 解壓shapefile壓縮包
*/
public static File unShapeZip(InputStream inputStream,File tempDir){
// 解壓shp檔案
File unzipFiles = ZipUtil.unzip(inputStream, tempDir, null);
Optional<File> optional = ListUtil.toList(unzipFiles.listFiles())
.stream()
.filter(file1 -> file1.getName().endsWith(".shp"))
.findAny();
if (!optional.isPresent()) {
throw new JeecgBootException("不存在解壓後shp檔案");
}
return optional.get();
}
/**
* 格式化向量資料為json格式
* @param the_geom
* @return
*/
public static String convertToJson(Geometry the_geom, Map<String, Object> propertoryMap){
String geomType = the_geom.getGeometryType();
// 解析組裝座標Json陣列
JSONArray geoJsonArray = getCoordinates(the_geom);
// 構建 GeoJSON 物件
JSONObject geoJsonFeature = new JSONObject();
geoJsonFeature.put("type", "Feature");
JSONObject geometry = new JSONObject();
geometry.put("type", geomType);
geometry.put("coordinates", geoJsonArray);
geoJsonFeature.put("geometry", geometry);
// 新增屬性
geoJsonFeature.put("properties", propertoryMap);
// 返回 GeoJSON 結果
JSONObject geoJson = new JSONObject();
geoJson.put("type", "FeatureCollection");
geoJson.put("features", new JSONArray().fluentAdd(geoJsonFeature));
return geoJson.toString();
}
/**
* 解析不同型別座標返回JSON陣列
*/
private static JSONArray getCoordinates(Geometry geometry) {
if (geometry instanceof Point) {
Point point = (Point) geometry;
JSONArray geoJsonPoints = new JSONArray();
geoJsonPoints.add(point.getX());
geoJsonPoints.add(point.getY());
return geoJsonPoints;
} else if (geometry instanceof LineString) {
LineString lineString = (LineString) geometry;
org.locationtech.jts.geom.Coordinate[] coordinates = lineString.getCoordinates();
JSONArray geoJsonLineString = new JSONArray();
for (Coordinate coordinate : coordinates) {
geoJsonLineString.add(coordinate.getX());
geoJsonLineString.add(coordinate.getY());
}
return geoJsonLineString;
} else if (geometry instanceof Polygon) {
Polygon polygon = (Polygon) geometry;
return getPolygonCoordinates(polygon);
} else if (geometry instanceof MultiPoint) {
MultiPoint multiPoint = (MultiPoint) geometry;
JSONArray coords = new JSONArray();
for (int i = 0; i < multiPoint.getNumGeometries(); i++) {
Point point = (Point) multiPoint.getGeometryN(i);
coords.add(new JSONArray().fluentAdd(point.getX()).fluentAdd(point.getY()));
}
return coords;
} else if (geometry instanceof MultiLineString) {
MultiLineString multiLineString = (MultiLineString) geometry;
JSONArray coords = new JSONArray();
for (int i = 0; i < multiLineString.getNumGeometries(); i++) {
coords.add(getCoordinates(multiLineString.getGeometryN(i)));
}
return coords;
} else if (geometry instanceof MultiPolygon) {
MultiPolygon multiPolygon = (MultiPolygon) geometry;
JSONArray coords = new JSONArray();
for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
coords.add(getPolygonCoordinates((Polygon) multiPolygon.getGeometryN(i)));
}
return coords;
} else {
return null;
}
}
// 解析獲取多邊形的座標陣列
private static JSONArray getPolygonCoordinates(Polygon polygon) {
JSONArray coords = new JSONArray();
// 多邊形外環
JSONArray exteriorRing = new JSONArray();
for (int i = 0; i < polygon.getExteriorRing().getNumPoints(); i++) {
exteriorRing.fluentAdd(new JSONArray().fluentAdd(polygon.getExteriorRing().getCoordinateN(i).x)
.fluentAdd(polygon.getExteriorRing().getCoordinateN(i).y));
}
coords.add(exteriorRing);
// 多邊形內環
for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
JSONArray interiorRing = new JSONArray();
for (int j = 0; j < polygon.getInteriorRingN(i).getNumPoints(); j++) {
interiorRing.fluentAdd(new JSONArray().fluentAdd(polygon.getInteriorRingN(i).getCoordinateN(j).x)
.fluentAdd(polygon.getInteriorRingN(i).getCoordinateN(j).y));
}
coords.add(interiorRing);
}
return coords;
}
}