【问题标题】:Parse GeoJSON file with Java Topology Suite or GeoTools使用 Java Topology Suite 或 GeoTools 解析 GeoJSON 文件
【发布时间】:2018-12-28 10:57:16
【问题描述】:

例如,如果您有一个像这样带有多边形的 GeoJSON 文件(用于测试的简单文件)

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              -4.658203125,
              41.343824581185686
            ],
            [
              -5.6689453125,
              39.13006024213511
            ],
            [
              -1.9335937499999998,
              39.16414104768742
            ],
            [
              -1.3623046875,
              41.21172151054787
            ],
            [
              -4.658203125,
              41.343824581185686
            ]
          ]
        ]
      }
    }
  ]
}

重点:

Geometry point2 = new WKTReader().read("POINT (-3.2958984375 40.44694705960048)");

你想在你的程序中加载geoJSON文件来测试这个多边形包含点,你怎么能在Java中使用JTS呢?


其他选项可以使用带有 GeoJson 插件的 GeoTools,但我无法解析 GeoJson 文件


我的尝试

使用像this这样的GEOTOOLS

String content = new String(Files.readAllBytes(Paths.get("file.geojson")), "UTF-8");
GeometryJSON gjson = new GeometryJSON();
Reader reader = new StringReader(content);
Polygon p = gjson.readPolygon(reader);
System.out.println("polygon: " + p);

这里的问题是多边形 p 只包含 geojson 文件的最后一个多边形。如果这个文件有很多多边形,我应该如何解析它?

使用 JTS2GEOJSON,例如 this

String content = new String(Files.readAllBytes(Paths.get("file.geojson")), "UTF-8");
System.out.println("content: " + content);
GeoJSONReader reader1 = new GeoJSONReader();
Geometry geometry = reader1.read(content);

此代码失败是这一行:

Geometry geometry = reader1.read(content);

出现此错误:

Exception in thread "main" java.lang.UnsupportedOperationException
    at org.wololo.jts2geojson.GeoJSONReader.read(GeoJSONReader.java:51)
    at org.wololo.jts2geojson.GeoJSONReader.read(GeoJSONReader.java:21)
    at org.wololo.jts2geojson.GeoJSONReader.read(GeoJSONReader.java:16)

这个错误是由于我试图从 GeoJson 文件中读取 FeatureCollections。如果我尝试使用这个简单的字符串,它会起作用:

   String content = "{\n" +
                "        \"type\": \"Polygon\",\n" +
                "        \"coordinates\": [\n" +
                "          [\n" +
                "            [\n" +
                "              -4.141845703125,\n" +
                "              40.9218144123785\n" +
                "            ],\n" +
                "            [\n" +
                "              -4.603271484375,\n" +
                "              40.002371935876475\n" +
                "            ],\n" +
                "            [\n" +
                "              -3.5595703125,\n" +
                "              39.757879992021756\n" +
                "            ],\n" +
                "            [\n" +
                "              -2.548828125,\n" +
                "              40.43858586704331\n" +
                "            ],\n" +
                "            [\n" +
                "              -3.2080078125,\n" +
                "              41.12074559016745\n" +
                "            ],\n" +
                "            [\n" +
                "              -4.141845703125,\n" +
                "              40.9218144123785\n" +
                "            ]\n" +
                "          ]\n" +
                "        ]\n" +
                "      }";

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 我在主帖@IanTurton 中添加了更多细节

标签: java geotools jts


【解决方案1】:

如果您使用的是GeoTools,那么您需要开始考虑DataStoresFeatureCollections。有很多内置的智能(大部分使用 JTS)来处理 filtering 等,如果潜在问题可以为您节省很多。

File inFile = new File("/home/ian/Data/states/states.geojson");
Map<String, Object> params = new HashMap<>();
params.put(GeoJSONDataStoreFactory.URLP.key, URLs.fileToUrl(inFile));
DataStore newDataStore = DataStoreFinder.getDataStore(params);
String pt = "POINT (-107 42)";

FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
SimpleFeatureSource featureSource = newDataStore.getFeatureSource(newDataStore.getTypeNames()[0]);
Filter f = ff.contains(ff.property(featureSource.getSchema().getGeometryDescriptor().getLocalName()),
    ff.literal(pt));
SimpleFeatureCollection collection = featureSource.getFeatures(f);
if (collection.size() > 0) {
  try (SimpleFeatureIterator itr = collection.features()) {
    while (itr.hasNext()) {
      System.out.println(itr.next());
    }
  }
}

这将需要您的pom.xml 中的以下内容:

<dependency>
   <groupId>org.geotools</groupId>
   <artifactId>gt-geojsondatastore</artifactId>
   <version>${geotools.version}</version>
</dependency>
<dependency>
   <groupId>org.geotools</groupId>
   <artifactId>gt-shapefile</artifactId>
   <version>${geotools.version}</version>
 </dependency>

【讨论】:

  • 可以使用 InputStream inFile 代替 File inFile 吗?我已经尝试过,但在这里不起作用:URLs.fileToUrl(inFile) 我所做的方式是从 InputStream 中读取,创建一个临时文件并复制到他,但是如果我在 AWS 中运行此代码,它会失败,我认为是由于创建文件(因为在本地运行没有问题)
  • 不,您需要一个真实的 URL 或转换为 URL 的文件。可能使用 java.tempfile 可能会有所帮助?
  • 这就是我们正在使用的:File tempFile = File.createTempFile("prefix-", ".geojson"); tempFile.deleteOnExit();,如果我使用 apache Flink 在本地运行它,一切正常。问题是当我在 Kinesis Data Analytics 中运行它时,没有显示错误,但该方法不起作用,因为我没有任何结果
  • 我认为这对于 AWS 专家来说可能是一个新问题 - 我只能建议检查代码中是否存在文件?
  • 嗨@IanTurton,你能帮我解决这个问题吗? gis.stackexchange.com/q/330030/146554
【解决方案2】:

使用 GeoJsonReader 类,您可以将 GeoJson Geometry 从 JSON 片段读取到 Geometry:

http://locationtech.github.io/jts/javadoc/org/locationtech/jts/io/geojson/GeoJsonReader.html

然后,测试几何(geojson 多边形)是否包含参数几何(wkt 点):

http://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/Geometry.html#contains(org.locationtech.jts.geom.Geometry)

【讨论】:

  • 根据我在主帖中添加的代码,我应该如何使用 GeoJSONReader?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 2018-03-08
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
  • 2016-05-28
相关资源
最近更新 更多