如何基于WorldWind从内存流将Shapefile转为GeoJSON?
使用WorldWind将内存中的Shapefile转换为GeoJSON
你已经通过内存流成功加载了Shapefile,接下来可以按照以下步骤将其转换为GeoJSON格式:
1. 初始化GeoJSON的FeatureCollection结构
GeoJSON的根结构是FeatureCollection,先创建基础结构并填充边界框信息:
// 初始化FeatureCollection基础结构 Map<String, Object> featureCollection = new HashMap<>(); featureCollection.put("type", "FeatureCollection"); featureCollection.put("bbox", shapefile.getBoundingRectangle()); List<Map<String, Object>> features = new ArrayList<>(); featureCollection.put("features", features);
2. 遍历ShapefileRecord转换为GeoJSON Feature
在你已有的遍历循环中,对每个ShapefileRecord分别处理几何信息和属性:
while (shapefile.hasNext()) { ShapefileRecord record = shapefile.nextRecord(); // 创建单个Feature对象 Map<String, Object> feature = new HashMap<>(); feature.put("type", "Feature"); // 提取属性信息 Map<String, Object> properties = new HashMap<>(); ShapefileAttributes attributes = record.getAttributes(); for (String attrName : attributes.getAttributeNames()) { properties.put(attrName, attributes.getValue(attrName)); } feature.put("properties", properties); // 转换几何信息 Map<String, Object> geometry = convertShapeGeometryToGeoJson(record); feature.put("geometry", geometry); features.add(feature); }
3. 实现几何类型转换逻辑
根据WorldWind的ShapeType,将不同几何类型(点、线、面)转换为GeoJSON对应格式:
private static Map<String, Object> convertShapeGeometryToGeoJson(ShapefileRecord record) { Map<String, Object> geometry = new HashMap<>(); ShapeType shapeType = record.getShapeType(); switch (shapeType) { case POINT: geometry.put("type", "Point"); Location location = record.getPointBuffer(0).getLocations().get(0); // GeoJSON坐标顺序为[经度, 纬度] geometry.put("coordinates", new double[]{location.getLongitude(), location.getLatitude()}); break; case POLYLINE: geometry.put("type", "LineString"); List<double[]> lineCoords = new ArrayList<>(); for (Location loc : record.getPointBuffer(0).getLocations()) { lineCoords.add(new double[]{loc.getLongitude(), loc.getLatitude()}); } geometry.put("coordinates", lineCoords); break; case POLYGON: geometry.put("type", "Polygon"); List<List<double[]>> polygonCoords = new ArrayList<>(); // 处理Shapefile的多环结构(外环+内环) for (int i = 0; i < record.getNumPointBuffers(); i++) { VecBuffer ringBuffer = record.getPointBuffer(i); List<double[]> ringCoords = new ArrayList<>(); for (Location loc : ringBuffer.getLocations()) { ringCoords.add(new double[]{loc.getLongitude(), loc.getLatitude()}); } // 确保GeoJSON环闭合,若Shapefile未闭合则补全起点坐标 if (!ringCoords.isEmpty()) { double[] first = ringCoords.get(0); double[] last = ringCoords.get(ringCoords.size()-1); if (first[0] != last[0] || first[1] != last[1]) { ringCoords.add(first); } } polygonCoords.add(ringCoords); } geometry.put("coordinates", polygonCoords); break; // 按需扩展MULTIPOINT、MULTIPOLYGON等其他类型 default: geometry.put("type", "GeometryCollection"); geometry.put("geometries", Collections.emptyList()); break; } return geometry; }
4. 序列化GeoJSON为字符串
用JSON库(如Jackson)将FeatureCollection转为JSON字符串:
ObjectMapper mapper = new ObjectMapper(); String geoJsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(featureCollection); // 输出或使用转换后的GeoJSON字符串 log.debug("转换完成的GeoJSON: {}", geoJsonString);
注意事项
- GeoJSON坐标顺序为**[经度, 纬度]**,需注意与WorldWind Location(纬度优先)的顺序差异。
- Shapefile的Polygon可能包含内环(表示洞),转换时需保留环的层级结构。
- 可根据需求扩展更多ShapeType的转换逻辑。
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

