C# 使用 lat/long 数组计算多个曲率
Posted
技术标签:
【中文标题】C# 使用 lat/long 数组计算多个曲率【英文标题】:C# Calculate multiple curvatures with lat/long array 【发布时间】:2021-08-20 15:47:59 【问题描述】:我有一系列纬度和经度构成从起点到目的地的整条路线,但我真的很难计算整条铁路路线的所有曲率,包括将左转作为负值,将右转作为正值(或反之亦然,以较容易者为准)。
我也有代码可以给我一个轴承以及两个轴承之间的差异,但这是我所掌握的(代码如下)。
从下图中的绿色标记出发,向西(左)行进,有:
向右轻微弯曲 向右急转 向左转 向左小转 大部分是直的 急左 有点直 紧随其后的是一个急右本质上,它正在计算上述列表/图片中每个转弯的转弯半径。
所需的输出对象
public EdgeCurve[] Curves get; set;
public class EdgeCurve
public double StartLatitude get;s et;
public double StartLongitude get; set;
public double EndLatitude get; set;
public double EndLongitude get; set;
public double Curve get; set;
//Optional
public double Distance get;set;
轴承代号
public static class BearingHelper
/// <summary>
/// Angle between two points, where North is 0 and South is 180.
/// </summary>
/// <param name="lat0">Latitude for point A.</param>
/// <param name="lon0">Longitude for point A.</param>
/// <param name="lat1">Latitude for point B.</param>
/// <param name="lon1">Longitude for point B.</param>
/// <returns>Angle between points A and B, in degrees.</returns>
public static double Degrees(double lat0, double lon0, double lat1, double lon1)
var dlon = (lon1 - lon0).ToRadians();
var dphi = Math.Log(Math.Tan(lat1.ToRadians() / 2 + PI_d4) / Math.Tan(lat0.ToRadians() / 2 + PI_d4));
if (Math.Abs(dlon) > Math.PI)
dlon = dlon > 0 ? -(PI_m2 - dlon) : (PI_m2 + dlon);
return (Math.Atan2(dlon, dphi).ToDegrees() + 360) % 360;
public static double AbsDifference(double bearing0, double bearing1)
double diff = Math.Abs(bearing0 - bearing1);
if (diff > 180)
diff -= 360;
return Math.Abs(diff);
public static class CoordinateMath
/// <summary>
/// PI multiplied by 2.
/// </summary>
public const double PI_m2 = 6.28318530718;
/// <summary>
/// PI divided by 4.
/// </summary>
public const double PI_d4 = 0.78539816339;
/// <summary>
/// Convert degrees to radians.
/// </summary>
public static double ToRadians(this double deg) => deg * 0.01745329252;
/// <summary>
/// Convert radians to degrees.
/// </summary>
public static double ToDegrees(this double rad) => rad * 57.295779513;
纬度/经度数组
[
"Latitude": 53.743647,
"Longitude": -0.347531
,
"Latitude": 53.743635,
"Longitude": -0.348089
,
"Latitude": 53.74365,
"Longitude": -0.348648
,
"Latitude": 53.74369,
"Longitude": -0.349114
,
"Latitude": 53.743754,
"Longitude": -0.3496
,
"Latitude": 53.743867,
"Longitude": -0.35029
,
"Latitude": 53.743941,
"Longitude": -0.350679
,
"Latitude": 53.744063,
"Longitude": -0.351096
,
"Latitude": 53.744518,
"Longitude": -0.352272
,
"Latitude": 53.744557,
"Longitude": -0.352369
,
"Latitude": 53.744888,
"Longitude": -0.353199
,
"Latitude": 53.744925,
"Longitude": -0.353296
,
"Latitude": 53.745078,
"Longitude": -0.353724
,
"Latitude": 53.745176,
"Longitude": -0.354035
,
"Latitude": 53.745339,
"Longitude": -0.354672
,
"Latitude": 53.745494,
"Longitude": -0.355461
,
"Latitude": 53.745591,
"Longitude": -0.356196
,
"Latitude": 53.745644,
"Longitude": -0.356898
,
"Latitude": 53.74566,
"Longitude": -0.357678
,
"Latitude": 53.745633,
"Longitude": -0.358616
,
"Latitude": 53.745577,
"Longitude": -0.359361
,
"Latitude": 53.745521,
"Longitude": -0.359924
,
"Latitude": 53.745439,
"Longitude": -0.360563
,
"Latitude": 53.745344,
"Longitude": -0.361198
,
"Latitude": 53.745192,
"Longitude": -0.362056
,
"Latitude": 53.745051,
"Longitude": -0.362748
,
"Latitude": 53.744811,
"Longitude": -0.363821
,
"Latitude": 53.744539,
"Longitude": -0.364885
,
"Latitude": 53.74428,
"Longitude": -0.365809
,
"Latitude": 53.744023,
"Longitude": -0.366656
,
"Latitude": 53.743862,
"Longitude": -0.367141
,
"Latitude": 53.743723,
"Longitude": -0.367545
,
"Latitude": 53.7434,
"Longitude": -0.368412
,
"Latitude": 53.743096,
"Longitude": -0.369159
,
"Latitude": 53.742528,
"Longitude": -0.370427
,
"Latitude": 53.742197,
"Longitude": -0.371099
,
"Latitude": 53.741909,
"Longitude": -0.371663
,
"Latitude": 53.741679,
"Longitude": -0.372077
,
"Latitude": 53.741462,
"Longitude": -0.372498
,
"Latitude": 53.74131,
"Longitude": -0.372765
,
"Latitude": 53.737842,
"Longitude": -0.379223
,
"Latitude": 53.737396,
"Longitude": -0.380011
,
"Latitude": 53.737152,
"Longitude": -0.380388
,
"Latitude": 53.737006,
"Longitude": -0.380587
,
"Latitude": 53.736736,
"Longitude": -0.380912
,
"Latitude": 53.736466,
"Longitude": -0.381183
,
"Latitude": 53.736294,
"Longitude": -0.381331
,
"Latitude": 53.736187,
"Longitude": -0.381417
,
"Latitude": 53.735827,
"Longitude": -0.381659
,
"Latitude": 53.735664,
"Longitude": -0.381751
,
"Latitude": 53.735378,
"Longitude": -0.381882
,
"Latitude": 53.735185,
"Longitude": -0.381952
,
"Latitude": 53.734976,
"Longitude": -0.382014
,
"Latitude": 53.734575,
"Longitude": -0.382077
,
"Latitude": 53.734372,
"Longitude": -0.382083
,
"Latitude": 53.734044,
"Longitude": -0.382055
,
"Latitude": 53.733148,
"Longitude": -0.381884
,
"Latitude": 53.732913,
"Longitude": -0.381838
,
"Latitude": 53.732526,
"Longitude": -0.381762
,
"Latitude": 53.732156,
"Longitude": -0.381722
,
"Latitude": 53.731976,
"Longitude": -0.381718
,
"Latitude": 53.731854,
"Longitude": -0.381728
]
【问题讨论】:
例如曲线的作用是什么? 2.0 或 -5.7 是什么意思?你本质上是吗?你要求类似***.com/questions/7811761/… 嗨,如果节点太靠近,该链接是关于平滑线的,这是完全不同的。 2.0 表示它朝一个方向转动,-5.7 表示它朝另一个方向转动。我上传了一张更好的照片。 但是量级有什么意义呢?如果我编写了一个代码,将您的曲线声明为 -2312375.234234,这是什么意思?照原样,我认为您的问题不能(或不应该)得到回答,因为它基本上是“这是一个不完整的规范,请为我做我的工作”。将一组线段平滑成一组曲线并不是“完全不同”,这实际上是您显然要求的 当你说线条的平滑时,我会想到 Douglas-Peucker 算法,在该算法中删除数组中的冗余节点。我要问的是..如果火车沿着轨道行驶并开始右转,它开始右转与再次直行或左转之间的角度是多少。我只是不知道所需的数学或伪代码,没有这些,有人怎么知道在哪里看。我是软件开发人员而不是数学家,因此编写需求更加困难。 我想,从算法上讲,如果你站在任何给定的 N 点,那么你应该参考从前一个点 N-1 到当前的。然后,您将知道几件事:下一点是否是航向变化 - 如果不是,那么您处于恒定曲线上,如果是,那么 b) 变化是更靠右还是更靠左,因此(基于无论您已经向右还是向左)它是否更陡或更小,以及它是否代表从右向左的翻转。然后也许只是折叠你的序列 【参考方案1】:假设您对将路径建模为一系列线段感到满意,您可以通过计算相邻线段之间的符号角度来简单地计算曲率。
在伪代码中
for(var i = 1; i < points.Length - 1; i++)
var a = (points[i] - points[i-1]).Normalized;
var b = (points[i+1] - points[i]).Normalized;
// calculate signed angle between vectors
angle = atan2( a.x*b.y - a.y*b.x, a.x*b.x + a.y*b.y );
从finding signed angle between vectors计算符号角的代码
如果你想要一个平滑的插值,比如Bézier spline,你仍然可以创建它,将它分割成更短的线段并使用上面的方法。但是,如果您想要平滑段的单个曲率值,则需要定义该值应该是什么。因为平滑函数将具有连续的曲率范围。
请注意,这是假设平面坐标,如果您有纬度/经度,您可能希望重新投影到平面坐标系,可能每个线段对都有一个。
【讨论】:
以上是关于C# 使用 lat/long 数组计算多个曲率的主要内容,如果未能解决你的问题,请参考以下文章