MultiPolygon转H3仅填充首个多边形的通用解决方案问询
解决MultiPolygon全量生成H3网格的问题
针对你遇到的multiPolygonToH3仅处理首个多边形的问题,核心原因是原教程的函数逻辑没有遍历MultiPolygon下的所有子多边形。以下是通用解决方案,能适配任意结构的MultiPolygon:
核心思路
- 先判断输入几何类型:如果是
MultiPolygon,循环遍历其包含的每一个子Polygon;如果是单个Polygon则直接处理。 - 对每个子
Polygon,分别提取外环坐标和所有内环(孔洞)坐标,调用H3的多边形填充方法生成对应H3索引。 - 收集所有子多边形生成的H3索引,去重后返回最终结果。
代码实现(以Scala为例,适配Databricks环境)
import org.locationtech.jts.geom.{Geometry, Polygon, MultiPolygon} import org.apache.spark.sql.functions._ import com.uber.h3core.H3Core def multiPolygonToH3UDF(resolution: Int) = udf((geometry: Geometry) => { val h3 = H3Core.newInstance() val h3Indexes = scala.collection.mutable.Set[String]() geometry match { case mp: MultiPolygon => // 遍历MultiPolygon下的所有子Polygon for (i <- 0 until mp.getNumGeometries) { val polygon = mp.getGeometryN(i).asInstanceOf[Polygon] // 提取外环坐标 val outerRing = polygon.getExteriorRing.getCoordinates.map(coord => Array(coord.getY, coord.getX)) // 提取所有内环(孔洞)坐标 val holes = (0 until polygon.getNumInteriorRing).map(j => polygon.getInteriorRingN(j).getCoordinates.map(coord => Array(coord.getY, coord.getX)) ).toArray // 生成当前子Polygon的H3索引并加入集合 h3Indexes ++= h3.polyfill(outerRing, holes, resolution).map(_.toString) } case p: Polygon => // 单个Polygon的处理逻辑 val outerRing = p.getExteriorRing.getCoordinates.map(coord => Array(coord.getY, coord.getX)) val holes = (0 until p.getNumInteriorRing).map(j => p.getInteriorRingN(j).getCoordinates.map(coord => Array(coord.getY, coord.getX)) ).toArray h3Indexes ++= h3.polyfill(outerRing, holes, resolution).map(_.toString) case _ => // 非Polygon/MultiPolygon类型返回空 } h3Indexes.toArray })
关键说明
- 用
Set存储H3索引自动去重,避免不同子多边形重叠区域重复生成索引。 - 通过
getNumGeometries和getGeometryN(i)遍历所有子多边形,不管MultiPolygon包含多少个独立区域都能处理。 - 对每个子Polygon单独处理外环和孔洞,确保每个区域的H3网格都正确生成。
使用示例
在Databricks中注册UDF后,即可直接调用:
val df = spark.read.parquet("/path/to/your/data") val resultDf = df.withColumn("h3_indexes", multiPolygonToH3UDF(6)($"geometry"))
内容的提问来源于stack exchange,提问作者gjin
相关产品推荐
相关产品推荐

