GeoTools内缓冲区质心图层属性导出问题及代码报错求助
基于GeoTools内缓冲区质心计算的导出属性问题及错误解决
我基于GeoTools实现了一个方法,通过内缓冲区计算多边形质心并生成点图层添加到地图。生成的点图层能在地图上正常显示,但导出时没有任何属性,需要至少将质心的坐标保存到属性表中。
第一次尝试的代码
/* * Erstellung eines Inneren Puffers mit anschließenden Schwerpunkt für einen * ausgewählten Layer. Diese Daten sind aus etlichen Internetforum * zusammengebaut. die Methode hat leider, so vermute ich es, probleme mit * bestimmten geometrien und somit entstehen Lücken in der Berechnung Variante 1 */ public void InnerBufferCentroid() throws Exception { JLabel label = new JLabel("Wählen Sie einen Layer aus:"); List<Layer> layerList = map.layers(); String[] layerNames = new String[layerList.size()]; for (int i = 0; i < layerList.size(); i++) { layerNames[i] = layerList.get(i).getFeatureSource().getName().toString(); } String selectedLayer = (String) JOptionPane.showInputDialog(null, label, "Layerauswahl", JOptionPane.QUESTION_MESSAGE, null, layerNames, layerNames[0]); FeatureLayer selectedFeatureLayer = null; for (Layer layer : layerList) { if (layer.getFeatureSource().getName().toString().equals(selectedLayer)) { selectedFeatureLayer = (FeatureLayer) layer; break; } } System.out.println("Layerauswahl abgeschlossen"); SimpleFeatureSource featureSource = (SimpleFeatureSource) selectedFeatureLayer.getFeatureSource(); SimpleFeatureCollection featureCollection = featureSource.getFeatures(); SimpleFeatureIterator featureIterator = featureCollection.features(); // Erzeuge eine Liste aus den berechneten Zentroiden List<Point> centroidList = new ArrayList<Point>(); // Berechne für jedes Polygon im Layer den Zentroid int featureCount = featureCollection.size(); int currentFeature = 0; while (featureIterator.hasNext()) { System.out.println("Verarbeite Feature " + currentFeature + " von " + featureCount); currentFeature++; SimpleFeature feature = featureIterator.next(); // Überprüfung des Arbeitsfortschrittes System.out.println("Processing feature with ID: " + feature.getID()); Geometry geometry = (Geometry) feature.getDefaultGeometry(); double originalArea = geometry.getArea(); double bufferArea = originalArea; Geometry buffer = geometry.buffer(0); while (bufferArea >= originalArea * 0.05 && bufferArea > 0) { buffer = buffer.buffer(-500);// aus Performancegründe habe ich mich für 500m Schritte entschieden. Bei // der Größe werden noch für jeden Polygon Zentroide gerechnet, aber die // Berechnung dauert nicht zu lange bufferArea = buffer.getArea(); } Point centr; if (buffer instanceof Polygon) { centr = ((Polygon) buffer).getInteriorPoint(); } else { MultiPolygon multiPolygon = (MultiPolygon) buffer; int numGeometries = multiPolygon.getNumGeometries(); Polygon largestPolygon = null; double largestArea = 0; for (int i = 0; i < numGeometries; i++) { Polygon polygon = (Polygon) multiPolygon.getGeometryN(i); double area = polygon.getArea(); if (area > largestArea) { largestArea = area; largestPolygon = polygon; } } centr = largestPolygon.getCentroid(); } centroidList.add(centr); } System.out.println("Zentroide berechnet"); // Erzeuge ein Feature Collection aus den berechneten Zentroiden SimpleFeatureTypeBuilder featureTypeBuilder = new SimpleFeatureTypeBuilder(); featureTypeBuilder.setName("Centroids"); featureTypeBuilder.setCRS(CRS.decode("EPSG:25832")); featureTypeBuilder.add("centroid", Point.class); SimpleFeatureType featureType = featureTypeBuilder.buildFeatureType(); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); SimpleFeatureCollection centroidFeatureCollection = new DefaultFeatureCollection(); for (Point centroid : centroidList) { featureBuilder.add(centroid); SimpleFeature centroidFeature = featureBuilder.buildFeature(null); ((DefaultFeatureCollection) centroidFeatureCollection).add(centroidFeature); } System.out.println(centroidFeatureCollection.size()); // Erzeuge einen Layer aus den Zentroiden DefaultFeatureCollection defaultFeatureCollection = new DefaultFeatureCollection(null, featureType); defaultFeatureCollection.addAll(centroidFeatureCollection); FeatureSource featureS = new CollectionFeatureSource(defaultFeatureCollection); // Style style = SLD.createPointStyle("Centroid", Color.RED, Color.RED, 0.5f, 5); Style style = SLD.createSimpleStyle(featureType); Layer centroidLayer = new FeatureLayer(featureS, style); System.out.println("zur karte hinzufügen"); // Füge den Layer dem Map Content hinzu map.addLayer(centroidLayer); System.out.println(map.layers()); }
这次尝试的问题是:未传递任何属性,导致导出的几何数据为空。之后我做了如下修改:
修改后的代码片段
// Erzeuge eine Liste aus den Attributen für die Punkte List<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>(); SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Centroids"); builder.setCRS(CRS.decode("EPSG:25832")); GeometryType geometryType = DataUtilities.createType("centroid", Point.class, CRS.decode("EPSG:25832")); builder.add(geometryType); // Erstelle die Feature-Typ-Definition SimpleFeatureType featureType = builder.buildFeatureType(); // Erstelle die Feature-Collection DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", featureType); // Erstelle eine SimpleFeatureBuilder-Instanz zum Erstellen von Feature-Objekten SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); // Iteriere über den centroidList und erstelle für jeden Punkt ein Feature-Objekt for (Point centroid : centroidList) { // Setze den Wert für das Attribut "centroid" im Feature-Objekt featureBuilder.set("centroid", centroid); // Erstelle das SimpleFeature-Objekt SimpleFeature feature = featureBuilder.buildFeature(null); // Füge das Feature der Feature-Collection hinzu featureCollection.addFeature(feature); } // Füge die Feature-Collection dem Layer hinzu FeatureLayer centroidLayer = new FeatureLayer(featureCollection, style); // Füge den Layer dem Map Content hinzu map.addLayer(centroidLayer);
但修改后遇到两个错误:
- 错误1:
The method addFeature(SimpleFeature) is undefined for the type DefaultFeatureCollection. - 错误2:
The method createType(String, String, String) in the type DataUtilities is not applicable for the arguments (String, Class<Point>, CoordinateReferenceSystem)
错误解决及属性添加方案
1. 解决错误2:DataUtilities.createType参数错误
DataUtilities.createType的正确用法是通过字符串定义几何类型,而非直接传入Class<Point>和CRS。你可以直接用SimpleFeatureTypeBuilder.add方法来添加几何属性,无需借助DataUtilities,代码更简洁:
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Centroids"); builder.setCRS(CRS.decode("EPSG:25832")); // 直接添加几何属性,指定名称、类型和CRS builder.add("centroid", Point.class, CRS.decode("EPSG:25832"));
如果一定要用DataUtilities,则需要按格式传入字符串:
GeometryType geometryType = (GeometryType) DataUtilities.createType("centroid:Point:srid=25832");
2. 解决错误1:DefaultFeatureCollection方法名错误
DefaultFeatureCollection添加要素的方法是add(SimpleFeature),而非addFeature,所以把featureCollection.addFeature(feature)改成:
featureCollection.add(feature);
3. 添加坐标属性到属性表
要解决导出无属性的问题,需要在SimpleFeatureType中添加x、y坐标字段,并在创建Feature时赋值:
// 创建FeatureType时添加坐标属性 SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Centroids"); CoordinateReferenceSystem crs = CRS.decode("EPSG:25832"); builder.setCRS(crs); builder.add("centroid", Point.class, crs); // 添加x、y坐标属性 builder.add("x", Double.class); builder.add("y", Double.class); SimpleFeatureType featureType = builder.buildFeatureType(); // 创建Feature时赋值坐标 SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); for (Point centroid : centroidList) { featureBuilder.set("centroid", centroid); // 获取质心坐标并赋值 featureBuilder.set("x", centroid.getX()); featureBuilder.set("y", centroid.getY()); SimpleFeature feature = featureBuilder.buildFeature(null); featureCollection.add(feature); }
完整修正后的核心代码片段
// 替换原代码中创建FeatureCollection及后续的部分 System.out.println("Zentroide berechnet"); // 创建带坐标属性的FeatureType SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Centroids"); CoordinateReferenceSystem crs = CRS.decode("EPSG:25832"); builder.setCRS(crs); builder.add("centroid", Point.class, crs); builder.add("x", Double.class); builder.add("y", Double.class); SimpleFeatureType featureType = builder.buildFeatureType(); // 创建FeatureCollection DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("internal", featureType); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType); // 生成带属性的Feature for (Point centroid : centroidList) { featureBuilder.set("centroid", centroid); featureBuilder.set("x", centroid.getX()); featureBuilder.set("y", centroid.getY()); SimpleFeature feature = featureBuilder.buildFeature(null); featureCollection.add(feature); } // 创建图层并添加到地图 Style style = SLD.createSimpleStyle(featureType); FeatureLayer centroidLayer = new FeatureLayer(featureCollection, style); map.addLayer(centroidLayer); System.out.println("Layer hinzugefügt: " + map.layers());
内容的提问来源于stack exchange,提问作者Marc
相关产品推荐
相关产品推荐

