求笛卡尔坐标与超球面坐标双向转换的Kotlin实现方案
问题:Kotlin中笛卡尔坐标与超球面坐标的双向转换实现
我一直找不到Kotlin环境下笛卡尔坐标与超球面坐标双向转换的现成实现,折腾了很久终于自己摸索出了一套可行方案,特意在这里分享出来。
回答:
超球面坐标转笛卡尔坐标
超球面坐标在n维空间中包含1个半径参数和n-1个角度参数(前n-2个角度范围为[0, π],最后一个角度范围为[0, 2π)),以下是转换实现:
fun hypersphericalToCartesian(radius: Double, angles: DoubleArray): DoubleArray { require(angles.isNotEmpty()) { "角度参数数组不能为空" } val dim = angles.size + 1 val cartesian = DoubleArray(dim) // 第一个坐标分量 cartesian[0] = radius * angles.fold(1.0) { acc, angle -> acc * Math.sin(angle) } // 中间坐标分量 for (i in 1 until dim - 1) { cartesian[i] = radius * angles.take(i).fold(1.0) { acc, angle -> acc * Math.sin(angle) } * Math.cos(angles[i - 1]) } // 最后一个坐标分量 cartesian[dim - 1] = radius * Math.cos(angles.last()) return cartesian }
笛卡尔坐标转超球面坐标
从笛卡尔坐标反推超球面坐标时,需先计算半径,再依次推导各角度,同时处理零向量的特殊情况:
fun cartesianToHyperspherical(cartesian: DoubleArray): Pair<Double, DoubleArray> { require(cartesian.size >= 2) { "至少需要2维坐标" } val radius = Math.sqrt(cartesian.sumOf { it * it }) // 处理零向量,避免计算异常 if (radius < 1e-10) { return Pair(0.0, DoubleArray(cartesian.size - 1) { 0.0 }) } val angles = DoubleArray(cartesian.size - 1) var sumOfSquares = 0.0 // 计算前n-2个角度 for (i in 0 until cartesian.size - 2) { sumOfSquares += cartesian[i] * cartesian[i] angles[i] = Math.atan2(Math.sqrt(sumOfSquares), cartesian[i + 1]) } // 计算最后一个角度 angles[angles.lastIndex] = Math.atan2(cartesian[0], cartesian.last()) return Pair(radius, angles) }
使用示例
fun main() { // 3维超球面转笛卡尔示例 val radius = 5.0 val angles = doubleArrayOf(Math.PI/4, Math.PI/6) // θ1=45°, θ2=30° val cartesian = hypersphericalToCartesian(radius, angles) println("笛卡尔坐标:${cartesian.contentToString()}") // 笛卡尔转超球面反向验证 val (calcRadius, calcAngles) = cartesianToHyperspherical(cartesian) println("计算得到的半径:$calcRadius") println("计算得到的角度:${calcAngles.contentToString()}") }
补充说明
- 代码加入了参数合法性检查,避免传入不符合要求的参数导致报错
- 零向量处理使用
1e-10作为极小值阈值,可根据实际精度需求调整 - 角度定义遵循通用超球面坐标标准,确保转换结果符合数学定义
内容的提问来源于stack exchange,提问作者Kemsikov
相关产品推荐
相关产品推荐

