如何在Java代码中用Osmosis实现边界框过滤读取OSM PBF节点
解决方案:使用Osmosis内置的BoundingBoxFilter实现高效边界过滤
不需要自己用JTS逐个判断节点,Osmosis本身提供了和命令行--bounding-box参数对应的BoundingBoxFilter组件,它能在流式解析阶段直接过滤掉边界框外的实体,效率和命令行完全一致。
修改后的代码示例
data class MapObject( val lat: Double, val lon: Double, val id: Long ) class OsmReader : Sink { val data = mutableListOf<MapObject>() override fun close() {} override fun complete() {} override fun initialize(metaData: MutableMap<String, Any>?) {} override fun process(entityContainer: EntityContainer?) { if (entityContainer is NodeContainer) { val node = entityContainer.entity data.add(MapObject(node.latitude, node.longitude, node.id)) } } } fun readOSM(pathToPBF: String) { // 定义目标边界框参数:最小纬度、最大纬度、最小经度、最大经度 val minLat = 39.90 val maxLat = 39.92 val minLon = 116.38 val maxLon = 116.40 val inputStream = FileInputStream(pathToPBF) // 1. 创建自定义sink val customSink = OsmReader() // 2. 创建边界框过滤器,配置参数 val bboxFilter = BoundingBoxFilter().apply { setLeft(minLon) setRight(maxLon) setBottom(minLat) setTop(maxLat) // 只处理节点,关闭way和关系的处理以提升效率 processNodes = true processWays = false processRelations = false // 将过滤器的输出指向自定义sink setSink(customSink) } // 3. 创建PBF读取器,将输出指向过滤器 val reader = OsmosisReader(inputStream) reader.setSink(bboxFilter) // 启动处理流程 reader.run() println("读取到符合条件的节点数量:${customSink.data.size}") }
关键说明
BoundingBoxFilter会在数据从PBF文件读取后立即过滤,只有边界框内的节点才会被传递到你的自定义OsmReader,避免了加载所有节点再判断的性能开销- 通过设置
processNodes、processWays、processRelations可以精准控制需要处理的实体类型,进一步提升处理速度 - 边界框的坐标顺序要注意:
left对应最小经度,right对应最大经度,bottom对应最小纬度,top对应最大纬度
内容的提问来源于stack exchange,提问作者Jacopo
相关产品推荐
相关产品推荐

