找出离某个点最近的点java,Java GeoTools:如何在形状文件中查找从点到最近的多边形的距离...

So I have a shp-file containing a bunch of polygons. In this case, a polygon is a body of in-land water (like lakes and that kind of stuff).

My system is tracking a moving object, so in order to determine what this object is, I would like to see if this object is in water or on land AND how far it is to NEAREST shore (yes, both if it's in or out of water). I will take a sample point from the object once in a while and test it.

The system is written in Java, and I have imported GeoTools snapshot 17. But if other utils is easier to use, there is no requirements to use this.

To test if the point is IN water (that is, inside a polygon), this methods works:

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

}

}

}

Now the questions:

1) If the point is NOT in a polygon, how do I find the nearest polygon in the source (being a SimpleFeatureSource)?

2) How do I find the distance to the edge of the polygon that is closest?

Any help would be highly appreciated! Especially code examples - I'm kind of rusty on math and geometry.

Thank you.

解决方案

The easiest answer is to use a SpatialIndexFeatureCollection to do the heavy lifting for you, it will find the nearest polygon, then you can check if you are inside or outside.

So a simple class like:

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;

}

}

Can be called using some code like:

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

String lakes = "/data/natural_earth/10m_physical/ne_10m_lakes.shp";

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

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值