java - 如何使用Java正确地将多边形创建到shapefile中?

标签 java polygon shapefile geotools

我正在尝试从坐标列表创建形状文件,它看起来好像可以工作,但是当我尝试在形状文件查看器中查看形状文件时,我的形状中似乎没有坐标。另外,如果我将 shapefile 下载为 geoJSON,它看起来是空的,如下所示: {"type":"GeometryCollection", "geometries": []}

所以我有一个Java类,我首先在其中创建一些虚拟数据,然后创建一个Polygon SimpleFeatureType,然后将我的点列表转换为多边形,最后尝试将该多边形写入shapefile。我没有收到任何错误,并且一切看起来都运行顺利,直到我尝试在浏览器中查看它。

这是我的类(class),其中包含一些调试打印:

import org.geotools.data.DefaultTransaction;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Polygon;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;

public class Main {

    private static SimpleFeature toFeature(List<PolygonPoint> locations, SimpleFeatureType POLYGON,
            GeometryFactory geometryFactory) {

        Coordinate[] coords = new Coordinate[locations.size()];

        int i = 0;
        for (PolygonPoint location : locations) {
            Coordinate coord = new Coordinate(location.x, location.y, 0);
            coords[i] = (coord);
            i++;
        }

        Polygon polygon = geometryFactory.createPolygon(coords);

        System.out.println(polygon.toString());
        /**
         * Degub print in this point looks like this: POLYGON ((60.15396170672204
         * 24.665516804291176, 60.1548304906673 24.67437097771886, 60.156868902093464
         * 24.684907435753292, 60.16053593400762 24.681227944085034, 60.16351621152651
         * 24.677017850437107, 60.1641222365678 24.670587380672547, 60.163303711361145
         * 24.664257803508647, 60.16193970279525 24.6590194867117, 60.158682674758644
         * 24.65963863846621, 60.15396170672204 24.665516804291176)) So looks okay so
         * far...
         */
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(POLYGON);
        featureBuilder.add(polygon);
        return featureBuilder.buildFeature(null);
    }

    static class PolygonPoint {
        public double x;
        public double y;

        public PolygonPoint(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }

    private static void initData(List<PolygonPoint> locations) {
        locations.add(new PolygonPoint(60.1539617067220433, 24.6655168042911761));
        locations.add(new PolygonPoint(60.1548304906673010, 24.6743709777188585));
        locations.add(new PolygonPoint(60.1568689020934642, 24.6849074357532920));
        locations.add(new PolygonPoint(60.1605359340076191, 24.6812279440850340));
        locations.add(new PolygonPoint(60.1635162115265132, 24.6770178504371067));
        locations.add(new PolygonPoint(60.1641222365677990, 24.6705873806725471));
        locations.add(new PolygonPoint(60.1633037113611451, 24.6642578035086473));
        locations.add(new PolygonPoint(60.1619397027952516, 24.6590194867116992));
        locations.add(new PolygonPoint(60.1586826747586443, 24.6596386384662090));
        locations.add(new PolygonPoint(60.1539617067220433, 24.6655168042911761));
    }

    public static void main(String[] args) throws IOException, SchemaException {

        List<PolygonPoint> locations = new ArrayList<>();
        initData(locations);

        // create simple feature builder for the locations
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName("polygonFeature");
        builder.setCRS(DefaultGeographicCRS.WGS84);
        builder.add(Polygon.TYPENAME_POLYGON, Polygon.class);
        SimpleFeatureType POLYGON = builder.buildFeatureType();

        DefaultFeatureCollection collection = new DefaultFeatureCollection();
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);

        SimpleFeature feature = toFeature(locations, POLYGON, geometryFactory);
        collection.add(feature);
        collection.forEach(name -> System.out.println(name));
        /**
         * Degub print in this point looks like this:
         * SimpleFeatureImpl:polygonFeature=[SimpleFeatureImpl.Attribute:
         * Polygon<Polygon id=fid-77f7c041_174f9627c85_-8000>=POLYGON
         * ((60.15396170672204 24.665516804291176, 60.1548304906673 24.67437097771886,
         * 60.156868902093464 24.684907435753292, 60.16053593400762 24.681227944085034,
         * 60.16351621152651 24.677017850437107, 60.1641222365678 24.670587380672547,
         * 60.163303711361145 24.664257803508647, 60.16193970279525 24.6590194867117,
         * 60.158682674758644 24.65963863846621, 60.15396170672204 24.665516804291176))]
         * So looks okay still...
         */

        File shapeFile = new File(new File("2020-").getAbsolutePath() + "shapefile.shp");

        Map<String, Serializable> params = new HashMap<>();
        params.put("url", shapeFile.toURI().toURL());
        params.put("create spatial index", Boolean.TRUE);

        ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();

        ShapefileDataStore dataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
        dataStore.createSchema(POLYGON);

        Transaction transaction = new DefaultTransaction("create");

        String typeName = dataStore.getTypeNames()[0];
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName);

        if (featureSource instanceof SimpleFeatureStore) {
            SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
            featureStore.setTransaction(transaction);
            try {
                featureStore.addFeatures(collection);
                transaction.commit();

            } catch (Exception problem) {
                transaction.rollback();
            } finally {
                transaction.close();
            }
        }
    }
}

然后这 5 个文件就按预期创建了。但是形状不正确并且没有显示任何内容。我正在用这个工具测试它们:https://mapshaper.org/但人们可以通过谷歌搜索一些 shapefile 在线查看器。

最佳答案

感谢 Ian Turton 链接答案,通过替换以下内容解决了问题:

builder.add(Polygon.TYPENAME_POLYGON, Polygon.class);

这样:

builder.add("the_geom", Polygon.class);

关于java - 如何使用Java正确地将多边形创建到shapefile中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64211953/

相关文章:

r - 在 R 中合并边界 shapefile

R 如何在具有多个多边形的 shapefile 中合并多边形要素? (可重现的代码示例)

java - 从 QBytearray 创建 QImage

java - 如何创建数据类型不是 EMF 类的 EAttribute?

java - 需要一个独立的 Java 库来对纬度/经度数据执行空间计算

algorithm - 三角形的天际线算法

java - ActivityOptions 在某些 Android 版本上返回 NoClassDefFoundError

java - Swing 面板/框架中的布局组件作为一个方面

r - 使用 terra 将列添加到 shapefile?