Java GeoTools:如何在形状文件中查找点到最近多边形的距离

Java GeoTools:如何在形状文件中查找点到最近多边形的距离,java,polygon,distance,geotools,Java,Polygon,Distance,Geotools,我有一个shp文件,里面有一堆多边形。在本例中,多边形是一个陆地水体(如湖泊等) 我的系统正在跟踪一个移动的物体,所以为了确定这个物体是什么,我想看看这个物体是在水里还是在陆地上,以及它离最近的海岸有多远(是的,无论它在水里还是水外)。我会每隔一段时间从对象中获取一个采样点,并对其进行测试 该系统是用Java编写的,我已经导入了GeoTools snapshot 17。但如果其他UTIL更易于使用,则不需要使用它 要测试点是否在水中(即多边形内部),此方法有效: private void fin

我有一个shp文件,里面有一堆多边形。在本例中,多边形是一个陆地水体(如湖泊等)

我的系统正在跟踪一个移动的物体,所以为了确定这个物体是什么,我想看看这个物体是在水里还是在陆地上,以及它离最近的海岸有多远(是的,无论它在水里还是水外)。我会每隔一段时间从对象中获取一个采样点,并对其进行测试

该系统是用Java编写的,我已经导入了GeoTools snapshot 17。但如果其他UTIL更易于使用,则不需要使用它

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

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();
        }
    }
}
private void findPolygonsForPoint(坐标点){
Filter=null;
SimpleFeatureIterator迭代器=null;
试一试{
filter=CQL.toFilter(“包含(_geom,点(“+POINT.x+”“+POINT.y+”)));
SimpleFeatureCollection=source.getFeatures(过滤器);
if(collection.size()<1){
System.out.println(坐标2字符串(点)+“不在多边形中”);
}否则{
System.out.println(坐标2字符串(点)+“在多边形中”);
insidePolygon++;
迭代器=collection.features();
while(iterator.hasNext()){
SimpleFeature feature=iterator.next();
//查找多边形的最近边
}
}
}捕获(CQE){
平均误差(“,e);
}捕获(IOE异常){
平均误差(“,e);
}最后{
if(迭代器!=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;
  }
}
最近多边形的公共类{
私有静态FilterFactory2 ff=CommonFactoryFinder.getFilterFactory2();
私有静态GeometryFactory gf=新GeometryFactory();
私有空间索引功能集合索引;
私有简单特征;
公共最近多边形(SimpleFeatureCollection要素){
索引=新的SpatialIndexFeatureCollection(features.getSchema());
index.addAll(特性);
}
公共点findNearestPolygon(点p){
最终双最大搜索距离=index.getBounds().getSpan(0);
坐标=p.getCoordinate();
ReferenceDevelope搜索=新的ReferenceDevelope(新信封(坐标),
index.getSchema().getCoordinaterReferenceSystem());
search.expandBy(最大搜索距离);
BBOX BBOX=ff.BBOX(ff.property(index.getSchema().getGeometryDescriptor().getName()),(BoundingBox)搜索);
SimpleFeatureCollection候选者=index.subCollection(bbox);
双重思维=最大搜索距离+1.0e-6;
坐标minDistPoint=null;
try(SimpleFeatureIterator itr=candidates.features()){
while(itr.hasNext()){
SimpleFeature feature=itr.next();
LocationIndexedLine line=新的LocationIndexedLine(((多多边形)特征.getDefaultGeometry()).getBoundary());
此处的LinearLocation=直线项目(坐标);
坐标点=直线提取点(此处);
双距离=点距离(坐标);
if(dist
可以使用以下代码调用:

  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);
        }

      }
    }
  }
publicstaticvoidmain(字符串[]args)引发IOException{
String lakes=“/data/natural_earth/10m_physical/ne_10m_lakes.shp”;
HashMap params=新的HashMap();
params.put(“url”,DataUtilities.fileToURL(新文件(lakes));
DataStore ds=DataStoreFinder.getDataStore(params);
String name=ds.getTypeNames()[0];
SimpleFeatureSource=ds.getFeatureSource(名称);
SimpleFeatureCollection features=source.getFeatures();
NearestPolygon polyFinder=新的NearestPolygon(特征);
对于(int i=0;i<100;i++){
点p=GeneratorAndomData.createRandomPoint();
Point pointOnLine=polyFinder.findNearestPolygon(p);
如果(!pointOnLine.isEmpty()){
System.out.println(在“+pointOnLine+”处的i+”最接近“+p”);
SimpleFeature lastMatched2=polyFinder.getLastMatched();
字符串属性=(字符串)lastmached2.getAttribute(“名称”);
if(attribute.isEmpty()){
attribute=(字符串)lastmached2.getAttribute(“注释”);
}
如果(((几何体)(lastMatched2.getDefaultGeometry()).contains(p)){
System.out.println(“在湖中”+属性);
}否则{
System.out.println(“最近的湖是”+属性);
}
}
}
}

最简单的答案是使用
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;
  }
}
最近多边形的公共类{
私有静态FilterFactory2 ff=CommonFactoryFinder.getFilterFactory2();
私有静态GeometryFactory gf=新GeometryFactory();
私有空间索引功能集合索引;
私有SimpleFeature lastMatch