Java 地理工具 : how to find distance from a point to closest polygon in shape file

标签 java polygon distance geotools

所以我有一个包含一堆多边形的 shp 文件。在这种情况下,多边形是一片内陆水域(如湖泊等)。

我的系统正在跟踪一个移动的物体,所以为了确定这个物体是什么,我想看看这个物体​​是在水中还是在陆地上以及它离最近的海岸有多远(是的,如果它在或出水)。我会时不时地从物体上取一个样本点并进行测试。

系统是用Java写的,我导入了GeoTools snapshot 17。但是如果其他的utils比较好用,就没有要求用这个。

要测试该点是否在水中(即在多边形内),此方法有效:

private void findPolygonsForPoint(Coordinate point) {
    Filter filter = null;
    SimpleFeatureIterator iterator = null;
    try {
        filter = CQL.toFilter("CONTAINS(the_geom, POINT(" + point.x + " " + point.y + "))");

        SimpleFeatureCollection collection = source.getFeatures(filter);
        if(collection.size() < 1) {
            System.out.println(coordinate2String(point) + " is NOT in a polygon");
        } else {
            System.out.println(coordinate2String(point) + " IS in a polygon");
            insidePolygon++;
            iterator = collection.features();

            while(iterator.hasNext()) {
                SimpleFeature feature = iterator.next();
                //find nearest edge of the polygon
            }
        }
    } catch(CQLException e) {
        aLog.error("", e);
    } catch(IOException e) {
        aLog.error("", e);
    } finally {
        if(iterator != null) {
            iterator.close();
        }
    }
}

现在问题:

1) 如果该点不在多边形中,我如何找到源中最近的多边形(作为 SimpleFeatureSource)?

2) 如何找到到最近的多边形边缘的距离?

任何帮助将不胜感激!尤其是代码示例 - 我对数学和几何有点生疏。

谢谢。

最佳答案

最简单的答案是使用 SpatialIndexFeatureCollection 为您完成繁重的工作,它会找到最近的多边形,然后您可以检查您是在内部还是外部。

像这样一个简单的类:

public class NearestPolygon {
  private static FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
  private static GeometryFactory gf = new GeometryFactory();
  private SpatialIndexFeatureCollection index;
  private SimpleFeature lastMatched;

  public NearestPolygon(SimpleFeatureCollection features) {

    index = new SpatialIndexFeatureCollection(features.getSchema());
    index.addAll(features);
  }



  public Point findNearestPolygon(Point p) {
    final double MAX_SEARCH_DISTANCE = index.getBounds().getSpan(0);
    Coordinate coordinate = p.getCoordinate();
    ReferencedEnvelope search = new ReferencedEnvelope(new Envelope(coordinate),
        index.getSchema().getCoordinateReferenceSystem());
    search.expandBy(MAX_SEARCH_DISTANCE);
    BBOX bbox = ff.bbox(ff.property(index.getSchema().getGeometryDescriptor().getName()), (BoundingBox) search);
    SimpleFeatureCollection candidates = index.subCollection(bbox);

    double minDist = MAX_SEARCH_DISTANCE + 1.0e-6;
    Coordinate minDistPoint = null;
    try (SimpleFeatureIterator itr = candidates.features()) {
      while (itr.hasNext()) {

        SimpleFeature feature = itr.next();
        LocationIndexedLine line = new LocationIndexedLine(((MultiPolygon) feature.getDefaultGeometry()).getBoundary());
        LinearLocation here = line.project(coordinate);
        Coordinate point = line.extractPoint(here);
        double dist = point.distance(coordinate);
        if (dist < minDist) {
          minDist = dist;
          minDistPoint = point;
          lastMatched = feature;
        }
      }
    }
    Point ret = null;
    if (minDistPoint == null) {
      ret = gf.createPoint((Coordinate) null);
    } else {
      ret = gf.createPoint(minDistPoint);
    }
    return ret;
  }

  public SimpleFeature getLastMatched() {
    return lastMatched;
  }
}

可以使用如下代码调用:

  public static void main(String[] args) throws IOException {
    String lakes = "/data/natural_earth/10m_physical/ne_10m_lakes.shp";
    HashMap<String, Object> params = new HashMap<>();
    params.put("url", DataUtilities.fileToURL(new File(lakes)));
    DataStore ds = DataStoreFinder.getDataStore(params);

    String name = ds.getTypeNames()[0];
    SimpleFeatureSource source = ds.getFeatureSource(name);
    SimpleFeatureCollection features = source.getFeatures();
    NearestPolygon polyFinder = new NearestPolygon(features);
    for (int i = 0; i < 100; i++) {
      Point p = GenerateRandomData.createRandomPoint();
      Point pointOnLine = polyFinder.findNearestPolygon(p);
      if (!pointOnLine.isEmpty()) {
        System.out.println(i+" At " + pointOnLine + " is closest to " + p);
        SimpleFeature lastMatched2 = polyFinder.getLastMatched();
        String attribute = (String) lastMatched2.getAttribute("name");
        if(attribute.isEmpty()) {
          attribute = (String) lastMatched2.getAttribute("note");
        }
        if (((Geometry) (lastMatched2.getDefaultGeometry())).contains(p)) {
          System.out.println("is in lake " + attribute);
        } else {
          System.out.println("nearest lake is " + attribute);
        }

      }
    }
  }

关于Java 地理工具 : how to find distance from a point to closest polygon in shape file,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44045598/

相关文章:

java - 从外部目录加载属性文件

java - 断言对象是特定类型

java - 如何在容器中存储不同类型的对象?

Android 将 map 中的多边形保存为所有设备大小相同的位图

r - 在 ggplot2 中绘制带有海洋的 map 的一小块区域

java - ThreadPoolExecutor 不消耗数据

pattern-matching - 部分多边形匹配

c++ - 制作字典图的有效方法

r - 一种快速计算点到 R 中 y=x 的正交距离的方法

r - 用于重复距离矩阵计算和超大距离矩阵分块的高效(内存方面)函数