如何在Kotlin中平移GeoJSON FeatureCollection的所有坐标
GeoJSON FeatureCollection坐标平移的最优实现方案(Kotlin + Jackson)
问题描述
我用Kotlin开发,通过Jackson的jacksonObjectMapper解析GeoJSON的FeatureCollection数据,需要平移所有要素内所有几何图形的所有坐标。目前能想到的是针对每种几何类型循环修改每个坐标,想知道有没有更优的实现方法。
示例输入
FeatureCollection数据
{ "type":"FeatureCollection", "features": [ { "type":"Feature", "properties": { "background": "WALLS_LOAD_BEARING" }, "geometry": { "type":"MultiPolygon", "coordinates":[ [[[10.0, 20.0], [15.0, 20.0], [10.0, 25.0]]] ] } }, { "type":"Feature", "properties": { "background":"PARTITIONS" }, "geometry": { "type":"MultiPolygon", "coordinates": [] } }, { "type":"Feature", "properties": { "background":"WALLS_LOAD_BEARING" }, "geometry": { "type":"LineString", "coordinates": [[10.0, 20.0]] } } ] }
平移参数
val moveX = 10.0 val moveY = 5.0
预期输出
{ "type":"FeatureCollection", "features": [ { "type":"Feature", "properties": { "background": "WALLS_LOAD_BEARING" }, "geometry": { "type":"MultiPolygon", "coordinates":[ [[[20.0, 25.0], [25.0, 25.0], [20.0, 30.0]]] ] } }, { "type":"Feature", "properties": { "background":"PARTITIONS" }, "geometry": { "type":"MultiPolygon", "coordinates": [] } }, { "type":"Feature", "properties": { "background":"WALLS_LOAD_BEARING" }, "geometry": { "type":"LineString", "coordinates": [[20.0, 25.0]] } } ] }
最优解决方案
方案1:递归遍历JsonNode(无额外依赖)
利用GeoJSON坐标的嵌套数组特性,写一个递归函数统一处理所有几何类型的坐标,无需针对每种几何类型单独编码,代码简洁且扩展性强。
import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.node.ArrayNode fun translateGeoJsonCoordinates(rootNode: JsonNode, moveX: Double, moveY: Double) { // 遍历所有Feature节点 val features = rootNode.get("features") as? ArrayNode ?: return features.forEach { featureNode -> val geometryNode = featureNode.get("geometry") ?: return@forEach val coordinatesNode = geometryNode.get("coordinates") as? ArrayNode ?: return@forEach // 递归处理所有嵌套坐标 processCoordinates(coordinatesNode, moveX, moveY) } } private fun processCoordinates(node: ArrayNode, moveX: Double, moveY: Double) { node.forEachIndexed { index, element -> when { // 识别最内层的坐标点(长度为2的数组),执行平移 element.isArray && element.size() == 2 -> { val newX = element.get(0).asDouble() + moveX val newY = element.get(1).asDouble() + moveY (element as ArrayNode).set(0, node.objectNodeFactory.numberNode(newX)) (element as ArrayNode).set(1, node.objectNodeFactory.numberNode(newY)) } // 嵌套数组则递归深入处理 element.isArray -> processCoordinates(element as ArrayNode, moveX, moveY) } } } // 使用示例 fun main() { val mapper = ObjectMapper() val geoJsonStr = """你的FeatureCollection JSON字符串""" val rootNode = mapper.readTree(geoJsonStr) // 执行平移 translateGeoJsonCoordinates(rootNode, 10.0, 5.0) // 输出格式化后的结果 println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode)) }
优势:无需额外依赖,代码量少,自动适配所有GeoJSON几何类型(Point、LineString、Polygon、MultiXXX等),新增几何类型时无需修改代码。
方案2:使用专业Geo处理库(适合复杂场景)
如果需要处理更多空间操作(旋转、缩放等),推荐使用专业Geo库(如GeoTools),库会自动处理所有GeoJSON细节,代码更简洁可靠。
依赖配置(build.gradle.kts)
implementation("org.geotools:gt-geojson:28.2")
实现代码
import org.geotools.geojson.feature.FeatureJSON import org.locationtech.jts.geom.Geometry import org.locationtech.jts.geom.util.AffineTransformation import java.io.StringReader import java.io.StringWriter fun translateGeoJsonWithGeoTools(geoJsonStr: String, moveX: Double, moveY: Double): String { val featureJSON = FeatureJSON() // 解析FeatureCollection val reader = StringReader(geoJsonStr) val featureCollection = featureJSON.readFeatureCollection(reader) // 创建平移变换 val affineTransform = AffineTransformation.translationInstance(moveX, moveY) // 遍历所有Feature并平移几何 featureCollection.features().forEach { feature -> val geometry = feature.defaultGeometry as Geometry val translatedGeometry = affineTransform.transform(geometry) feature.defaultGeometry = translatedGeometry } // 序列化回JSON val writer = StringWriter() featureJSON.writeFeatureCollection(featureCollection, writer) return writer.toString() } // 使用示例 fun main() { val geoJsonStr = """你的FeatureCollection JSON字符串""" val translatedGeoJson = translateGeoJsonWithGeoTools(geoJsonStr, 10.0, 5.0) println(translatedGeoJson) }
优势:专业库封装了所有空间操作逻辑,无需手动处理坐标嵌套,代码可读性高,适合有复杂空间需求的项目。
总结
- 仅需简单平移且不想加依赖:选方案1,递归处理JsonNode是最优解
- 有复杂空间操作需求:选方案2,专业Geo库更高效可靠
内容的提问来源于stack exchange,提问作者user2704006
相关产品推荐
相关产品推荐

