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).
我有一个shp文件,里面存有一些多边形。在本例中,多边形代表内陆水体(像湖和类似的东西)。
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.
这个系统是用Java写的,我已经导入了Geotools-snapshot-17。但是如果有更易用的,就没必要用这个。
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(); } } }
现在,问题是:
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.
最简单的方法是使用SpatialIndexFeatureCollection来帮你做这份沉重的活,它会查找到最近的多边形,然后你可以检查是否在内部还是外部。
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; } }
>>GeoTools入门(六)-- 查询那点事:https://blog.csdn.net/oYinHeZhiGuang/article/details/118316074