自己搭建网站的步骤,网站备案许可证号,做一家网站的成本,深圳网站设计兴田德润i简介开发背景 接上文我求的两经纬度点之间的方位角#xff0c;我的需求里还提到了要计算距离#xff0c;当然这个距离也是为后面的需求做铺垫的#xff0c;因此需要求两个经纬度电之间的距离。 不要妄想用勾股定理求出来#xff0c;实际上距离的计算还是稍微复杂些。这里使用的…开发背景 接上文我求的两经纬度点之间的方位角我的需求里还提到了要计算距离当然这个距离也是为后面的需求做铺垫的因此需要求两个经纬度电之间的距离。 不要妄想用勾股定理求出来实际上距离的计算还是稍微复杂些。这里使用的是Haversine公式用于在给定两个地理坐标点的情况下计算它们之间的球面距离我直接将这个公式的数学计算实现为一个方法然后再代码中调用。
生产环境使用球面短距离计算 Haversine公式的数学理论基于球面三角学和三角恒等式的推导通过近似计算大圆航线距离适用于小距离的球面距离计算。这基本符合我的需求因为我的计算都是基本是短距离计算的基本不会跨省实际效果也不错如果你是超远距离计算比如跨国跨洲了可以先试试然后再考虑使用。 来源 https://wikipredia.net/zh/Haversine_formula#Formulation
说完理论部分我就要开始上代码了基本上你配置完spark环境直接把我的代码扔上去就能看到输出结果因为我是做了很多遍验证的。
spark代码
这个你可以转成python反正算法基本都一样不过换了一种写法
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._/*** 增加了多对多的方位角计算以及计算对应距离模型计算方法* 代码实现了计算多个点位对多个点位的方位角计算以及对应的距离计算基本算是final版本* 基本实现了角度计算和距离计算* 在实际生产中会出现噪音点以及点位null值等还是提前清洗一下数据为好* 2024年8月6日写几个月前就搞好了一直没空发博客。。。今天又闲下来了干就完了有问题及时联系* email matrix70163.com* author lixh*/
object Angle_MoreToMore_Distance {/*** author lixh* param lon1* param lat1* param lon2* param lat2* return*/// 计算两个经纬度坐标之间的方位角def calculateAzimuth(lon1: Double, lat1: Double, lon2: Double, lat2: Double): Double {val dx lon2 - lon1val dy lat2 - lat1val azimuth math.atan2(dx, dy) * 180 / math.Pi(azimuth 360) % 360}//距离算法 Haversine author lixhdef haversineDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {val toRadians Math.toRadians(_: Double)val dLat toRadians(lat2 - lat1)val dLon toRadians(lon2 - lon1)val a Math.sin(dLat / 2) * Math.sin(dLat / 2) Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *Math.sin(dLon / 2) * Math.sin(dLon / 2)val c 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))val EARTH_RADIUS_KM 6371.0val distance EARTH_RADIUS_KM * cdistance}def main(args: Array[String]): Unit {val spark SparkSession.builder().appName(Azimuth Calculation) // 设置应用程序名称.master(local[*]) // 运行模式这里使用本地模式.getOrCreate()import spark.implicits._// DF A 包含地点信息和经纬度信息 author https://blog.csdn.net/qq_52128187?typeblog val A Seq((101, 北京, 39.9042, 116.4074),(102, 广州, 23.16, 113.23)).toDF(id1, name1, latitudeA, longitudeA)// DF C 包含地点信息和经纬度信息val C Seq((101, 吉林, 43.8171, 125.3235),(101, 黑龙江, 45.8023, 126.5350),(102, 江苏, 32.0603, 118.7969),(102, 浙江, 30.2875, 120.1536),(101,新疆, 43.77, 87.68),(102, 台湾省, 25.05, 121.50)).toDF(id2, name2, latitudeC, longitudeC)val calculateAzimuthUDF udf(calculateAzimuth _)// 执行内连接操作计算方位角并添加到新列 azimuthval azimuthDF A.join(C, A(id1) C(id2)).withColumn(azimuth, calculateAzimuthUDF($longitudeA, $latitudeA, $longitudeC, $latitudeC))// 计算得到的方位角数据azimuthDF.show(false)val haversineDistanceUDF udf((lat1: Double, lon1: Double, lat2: Double, lon2: Double) haversineDistance(lat1, lon1, lat2, lon2))//距离字段添加,author lixhval resultDf azimuthDF.withColumn(distance, haversineDistanceUDF($latitudeA, $longitudeA, $latitudeC, $longitudeC))resultDf.show()spark.stop()}
}代码输出结果 到这里基本就完成了你可以对输出结果进行小数点位限制一个round函数就解决。
参考资料
https://wikipredia.net/zh/Haversine_formula