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

问题描述

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

因此,我有一个java类,首先创建一些虚拟数据,然后创建polygon SimpleFeatureType,然后将点列表转换为多边形,最后尝试将该多边形写入shapefile。我没有收到任何错误,并且在我尝试在浏览器中查看它之前,所有看起来都运行平稳。

这是我的班级,上面有一些调试照片:

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.156868902093464 24.684907435753292,* 60.16351621152651 24.677017850437107,* 60.163303711361145 24.664257803508647,* 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/,但一个人可以用Google搜索一些shapefile在线查看器。

解决方法

感谢Ian Turton给出的答案,该问题已通过替换此问题得以解决:

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

与此:

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

,

每当我看到某个事务未写入数据时,就会查看该事务的处理方式。您实际上做到了很好,因为在发生异常时回滚。但我强烈建议您也发送一些日志消息,指出发生了哪种异常。尤其是当您抓到通用Exception时。

请参见catch块:

if (featureSource instanceof SimpleFeatureStore) {
    SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
    featureStore.setTransaction(transaction);
    try {
        featureStore.addFeatures(collection);
        transaction.commit();
    } catch (Exception problem) {
        problem.printStackTrace(System.err); // print out the stack trace of the exception
        transaction.rollback();
    } finally {
        transaction.close();
    }
}

这将至少使您有机会查看问题所在。