计算经纬度中的拐弯点

该博客介绍了如何从行车轨迹中识别拐弯点。通过将经纬度视为平面坐标并计算连续三点形成的角度,利用直线斜率和三角函数计算夹角。在遇到斜率为无穷大时,用特定值替代以避免NaN。当斜率相等表示线段平行,角度设为0。最终,根据角度阈值筛选拐点,实现轨迹的可视化分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一段行车轨迹,要求将所有拐弯点找出来,拐弯有个明显的特征就是前后轨迹点的朝向会发生明显的变化,我们只要将角度变化的轨迹点找出来即可。

怎么做呢?首先我们可以把地球的经纬度网格视为一个平面直角坐标系,经纬度就是这个坐标系上的一个个点,我们只要计算轨迹上连续的三个点组成的两个线段的夹角即可,上过初中的小伙伴都知道,坐标系上的直线可以用以下公式计算:

y = ax + b

其中 ( x , y ) 就是我们已知的经纬度,b是直线的偏移量,a是直线的斜率,也就是说只要我们知道两条直线的斜率,就有办法计算它们形成的夹角。

比如我们有经纬度分别如下:

[{"x":0,"y":0},{"x":1,"y":1},{"x":2,"y":0},{"x":3,"y":1},{"x":4,"y":0}]

在地图上它长这样子:

可以看出,这个麦当劳的汉堡还是很..啊呸,这组经纬度形成了一个M形折线,按照需求我们需要将其中的3个拐弯点找出来(BCD),我们先取出ABC三个点,即:

JSONObject aPoint = JSONObject.parseObject("{\"x\":0,\"y\":0}");
JSONObject bPoint = JSONObject.parseObject("{\"x\":1,\"y\":1}");
JSONObject cPoint = JSONObject.parseObject("{\"x\":2,\"y\":0}");

运用一下远古时期学过的小学知识:两点确定一条直线!我们可以得到AB线段和BC线段,并且通过上图我们可以看出这两个线段形成了一个夹角B。上面提到了我们需要计算这两条线段对应的斜率,直接套公式:

k = ( y1 - y2 ) / ( x1 - x2 )

AB的斜率k1 = ( 0 - 1 ) / ( 0 - 1 ) = 1

BC的斜率k2 = ( 1 - 0 ) / ( 1 - 2 ) = -1

有了斜率,我们就可以通过三角函数 tan 来表示角B:

tanB = (k1 - k2) / ( 1 + ( k1 * k2 ) )

再通过Java的反正切函数算出其角度值:

double angle = Math.atan(tanB) * 180 / 3.1415926;

到这里我们就可以得出其角度值为 90.0 度,循环已有的轨迹列表,即可算出所有的角度,再根据角度值来判断是否满足拐弯的特征,比如目前我们采用的是角度的绝对值在 45 ~ 135 之间。

在具体处理真实的轨迹的时候,我们还要考虑一些特殊的情况,比如众所周知正切函数的取值范围是负无穷 到 正无穷之间的,两个无穷值分别是 负90度 和 正90度,即角度是90的整数倍时计算得到的斜率会等于无穷大,此时如果将无穷大套用上面的公式得出结果是NaN,我们只要简单判断一下如果斜率是负无穷或者正无穷时,将其赋予一个足够大或者足够小的数,后面计算角度值的时候通过四舍五入保留小数,因为我们不需要计算一个特别精准的角度值,客观事实是我们的GPS设备采集回来的经纬度其实也达不到这样的精度,附上处理无穷大的代码:

k1 = Double.NEGATIVE_INFINITY == k1 ? -1000000.0 : k1;
k1 = Double.POSITIVE_INFINITY == k1 ? 1000000.0 : k1;
k2 = Double.NEGATIVE_INFINITY == k2 ? -1000000.0 : k2;
k2 = Double.POSITIVE_INFINITY == k2 ? 1000000.0 : k2;

还有一个情况就是,当 k1 = k2 时,表示两条线段平行,此时可以直接返回角度值 = 0

通过上面的逻辑,我们将真实的轨迹导进去运行,并将切割点前后分成不同的颜色,效果如下:

 局部特写:

### 使用 arcpy 计算网络分析中最短路径 在 ArcGIS 中,`arcpy.na` 模块提供了用于执行网络分析的功能。以下是基于提供的引用以及 `arcpy` 的功能实现最短路径计算的一个完整示例。 #### 准备工作 为了成功运行此脚本,需确保已安装并配置好 ArcPy 和相应的许可模块(Network Analyst 扩展)。此外,还需准备一个有效的网络数据集作为输入[^1]。 #### 示例代码 以下是一个完整的 Python 脚本,展示如何利用 `arcpy` 进行最短路径分析: ```python import arcpy # 设置工作空间 workspace = r"C:\path\to\your\network_dataset.gdb" arcpy.env.workspace = workspace # 定义网络数据集和分析图层名称 network_dataset = "Transportation/Street_ND" # 替换为实际的网络数据集路径 output_layer_name = "ShortestPath" # 创建网络分析图层 analysis_layer = arcpy.na.MakeRouteLayer(network_dataset, output_layer_name)[0] # 获取子图层列表 sub_layers = arcpy.na.GetNAClassNames(analysis_layer) # 加载停靠 (Stops) stops_layer = analysis_layer.listLayers(sub_layers.stops)[0] stop_features = [ ["Point", (-118.2437, 34.0522)], # 停靠 A (经度, 纬度) ["Point", (-118.2988, 34.0645)] # 停靠 B (经度, 纬度) ] arcpy.management.AddLocations(stops_layer, stop_features) # 设置分析参数 parameters = { "Impedance": "Length", "Restrictions": None, "U-Turns": "No U-Turns" } for param_key, param_value in parameters.items(): arcpy.na.SetSolverProperty(analysis_layer, param_key, param_value) # 解决分析 arcpy.na.Solve(analysis_layer) # 输出结果到文件地理数据库 result_output = r"C:\path\to\your\results.gdb\ShortestPathResult" arcpy.conversion.FeatureClassToFeatureClass( analysis_layer.listLayers(sub_layers.routes)[0], result_output.split("\\")[-2], # 文件夹路径 result_output.split("\\")[-1] # 结果名称 ) print(f"最短路径分析完成,结果保存至 {result_output}") ``` #### 参数说明 上述代码中涉及的关键参数解释如下: - **网络数据集**:指定要使用的网络数据集路径。 - **输出图层名**:定义生成的临时网络分析图层名称。 - **停靠加载**:通过经纬度坐标手动添加起和终位置[^2]。 - **阻抗属性**:设置为 `"Length"` 表示按距离计算最短路径;也可以更改为其他阻抗类型(如时间)[^3]。 - **求解器属性**:控制诸如转弯限制、通行条件等细节。 --- ###
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘尾田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值