我想根据自然地球数据计算一个点到一个shp文件(ports.shp)的最近距离。
例如,我正在加载文件的功能:
... String filename = "10m_cultural/ne_10m_ports.shp"; ... public static void Calcs(String filename) throws IOException, NoSuchAuthorityCodeException, FactoryException, TransformException { HashMap<String, Object> params = new HashMap<>(); params.put("url", DataUtilities.fileToURL(new File(filename))); DataStore ds = DataStoreFinder.getDataStore(params); String name = ds.getTypeNames()[0]; SimpleFeatureSource source = ds.getFeatureSource(name); SimpleFeatureCollection features = source.getFeatures();
}
现在,例如要计算距离的一点是:
GeometryFactory gf = JTSFactoryFinder.getGeometryFactory(); Point p = gf.createPoint(new Coordinate(43, 18));
我知道要计算距离,我会这样做:
CoordinateReferenceSystem crs = CRS.decode("EPSG:4326"); Point start = gf.createPoint(new Coordinate(43, 18)); Point dest = gf.createPoint(new Coordinate(?????)); GeodeticCalculator gc = new GeodeticCalculator(crs); gc.setStartingPosition(JTS.toDirectPosition(start.getCoordinate(), crs)); gc.setDestinationPosition(JTS.toDirectPosition(dest.getCoordinate(), crs)); double distance = gc.getOrthodromicDistance();
但是我不知道如何找到目的地的坐标(ports.shp文件):
Point dest = gf.createPoint(new Coordinate(?????));
我有features从加载文件,但它没有任何getCoordinates()方法。
features
getCoordinates()
而且,正如我所见,它ports.shp由许多POINT几何组成。我是否必须以某种方式计算参考点的每个点,然后选择最接近的点?
ports.shp
POINT
功能部件具有一种getDefaultGeometry可以为您提供所需要点的方法。然后,您可以从该点获取坐标。
getDefaultGeometry
编辑
您的问题是单位不匹配,您MinDist将边界框的宽度设置为度(以度为单位,大约为360),但将其与以米为单位的距离(大约为7800000)进行比较,因此您找不到一个足以保存的点。
MinDist
我开始通过限制初始搜索范围来提高搜索效率,但是即使使用了我无法确定是否有效的填充位置数据集,它也足够快。
final double MAX_SEARCH_DISTANCE = Math.max(index.getBounds().getWidth(), index.getBounds().getHeight()); double searchDist = 0.01; while (searchDist < MAX_SEARCH_DISTANCE) { // start point (user input) Coordinate coordinate = p.getCoordinate(); ReferencedEnvelope search = new ReferencedEnvelope(new Envelope(coordinate), index.getSchema().getCoordinateReferenceSystem()); search.expandBy(searchDist); BBOX bbox = ff.bbox(ff.property(index.getSchema().getGeometryDescriptor().getName()), (BoundingBox) search); SimpleFeatureCollection candidates = index.subCollection(bbox); double minDist = Double.POSITIVE_INFINITY; // can't use // MAX_Search_dist here // as it is degrees and // dists are meters Coordinate minDistPoint = null; double dist = 0; Point dest = null; SimpleFeatureIterator itr = candidates.features(); CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84; try { SimpleFeature feature = null; while (itr.hasNext()) { feature = itr.next(); // destination point dest = (Point) feature.getDefaultGeometry(); GeodeticCalculator gc = new GeodeticCalculator(crs); gc.setStartingPosition(JTS.toDirectPosition(p.getCoordinate(), crs)); gc.setDestinationPosition(JTS.toDirectPosition(dest.getCoordinate(), crs)); // Calculate distance between points dist = gc.getOrthodromicDistance(); // System.out.println(feature.getID()+": "+dist); if (dist < minDist) { minDist = dist; minDistPoint = dest.getCoordinate(); lastMatched = feature; } } } finally { itr.close(); } Point ret = null; if (minDistPoint == null) { searchDist *= 2.0; System.out.println("repeat search"); } else { ret = gf.createPoint(minDistPoint); return ret; } } return gf.createPoint(new Coordinate()); }