我一直在寻找一段时间,但还没有找到我正在寻找的东西。
我正在开发一个将用于赛车的应用程序。它将使驾驶员能够按下按钮来标记开始/终点线。它还将有一个按钮,允许驾驶员设置分段时间。
请记住,轨道可以是我首先要处理的椭圆形。它可能是道路路线,也可能是起点线和终点线不在同一位置的自动十字路口。他们可能彼此相距 50 英尺左右,但汽车永远不会越过它的起点。
我有我的 gps 数据,我将 NMea 消息转换为我的类,并存储 Lat、Lon、Speed、Course 等。在我的研究中,我遇到了这个有趣的问题。GPS将安装在屋顶外以获得更好的信号。它每秒产生 10 次命中。(加明格洛)
http://www.drdobbs.com/windows/gps-programming-net/184405690?pgno=1
它很旧,但它谈到了 UTM 和笛卡尔坐标系。所以使用 DecDeg2UTM,我也将 Lat & Lon 转换为 X & 坐标。
我也一直在尝试使用我找到的 Intersect 公式Here I take the intersect 并尝试将其转换为 C#,我将在最后发布。但是,喂食椭圆形轨道的坐标,它似乎不起作用。另外,我不确定它应该做什么。但是当它在距轨道所在位置 1000 英里的海洋中执行诸如 -35.xxx 和 98.xxxx 之类的操作时返回的坐标。
我正在寻找以下问题的答案。
- 我假设我需要在按下开始/完成或分段按钮时记录的位置,并计算一条垂直于汽车方向的线,以便能够进行某种线交点计算。笛卡尔坐标似乎可以很好地计算方位。但这里的问题是如何获得“左右坐标”。另外,请记住,椭圆形轨道可能有 60 英尺宽。但如前所述,自动交叉轨道可能只有 20 英尺宽,部分轨道可能有 50 英尺宽。请注意,我可以指示设置点,汽车需要慢速行驶或停在点上才能获得一个准确的坐标。有些轨道必须在行走时设置。
- 基于此,我应该尝试使用十进制纬度还是使用基于 UTM 的笛卡尔坐标系是我想要做的更准确的方法?
- 是否有一个 .Net 库或基于 C 的库,其源代码具有进行这些计算的方法?
- 这要如何准确处理。(数学不是很好,代码示例的链接会很有帮助。)
- 接下来,在我获得开始/结束和路段所需的线路或任何东西之后,当我从赛车中获得 GPS 信号时,我需要找出最准确的方法来判断汽车何时越过这些路段。再次,如果我很幸运,我每秒会获得 10 次点击,但它可能会更低。然后,根据轨道和车辆的类型,车辆速度可能会有很大差异。因此,GPS 命中可能是一段“左或右”的许多英尺。此外,它可能在一段之前或之后有很多英尺。
同样,如果那里有一个 GIS 库,我可以提供坐标并计算所有这些,只要它是高性能的,它就会工作得很好。如果不是再次,我试图决定是否最好将坐标分解为 XY 或一些几何公式以十进制格式的坐标。Mods,我认为有确凿的数据来支持任何一种方式的答案,这并不是回应并不完全主观的意见。
这是我从上面的脚本页面中获得的 C# 代码。我开始觉得 UTM 和笛卡尔坐标系在准确性和性能方面会更好。但是,如果存在相反的证据,我再次持开放态度。
谢谢
PS 注意 GeoCoordinate 来自 .Net System.Device.Location 组合。GpsData 只是我用来将 NMEA 消息转换为 Lat、Lon、Course、NumSats、DateTime 等的一个类。
度弧度方法是如下的扩展。
public static double DegreeToRadians(this double angle)
{
return Math.PI * angle / 180.0;
}
public static double RadianToDegree(this double angle)
{
return angle * (180.0 / Math.PI);
}
}
public static GeoCoordinate CalculateIntersection(GpsData p1, double brng1, GpsData p2, double brng2)
{
// see http://williams.best.vwh.net/avform.htm#Intersection
// Not sure I need to use Cosine
double _p1LatRadians = p1.Latitude.DegreeToRadians();
double _p1LonToRadians = p1.Longitude.DegreeToRadians();
double _p2LatToRadians = p2.Latitude.DegreeToRadians();
double _p2LonToRadians = p2.Longitude.DegreeToRadians();
double _brng1ToRadians = brng1.DegreeToRadians();
double _brng2ToRadians = brng2.DegreeToRadians();
double _deltaLat = _p2LatToRadians - _p1LatRadians;
double _deltaLon = _p2LonToRadians - _p1LonToRadians;
var _var1 = 2 * Math.Asin(Math.Sqrt(Math.Sin(_deltaLat / 2) * Math.Sin(_deltaLat / 2)
+ Math.Cos(_p1LatRadians) * Math.Cos(_p2LatToRadians) * Math.Sin(_deltaLon / 2) * Math.Sin(_deltaLon / 2)));
if (_var1 == 0) return null;
// initial/final bearings between points
var _finalBrng = Math.Acos((Math.Sin(_p2LatToRadians) - Math.Sin(_p1LatRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p1LatRadians)));
//if (isNaN(θa)) θa = 0; // protect against rounding
var θb = Math.Acos((Math.Sin(_p1LatRadians) - Math.Sin(_p2LatToRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p2LatToRadians)));
var θ12 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? _finalBrng : 2 * Math.PI - _finalBrng;
var θ21 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? 2 * Math.PI - θb : θb;
var α1 = (_brng1ToRadians - θ12 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 2-1-3
var α2 = (θ21 - _brng2ToRadians + Math.PI) % (2 * Math.PI) - Math.PI; // angle 1-2-3
if (Math.Sin(α1) == 0 && Math.Sin(α2) == 0) return null; // infinite intersections
if (Math.Sin(α1) * Math.Sin(α2) < 0) return null; // ambiguous intersection
α1 = Math.Abs(α1);
α2 = Math.Abs(α2);
// ... Ed Williams takes abs of α1/α2, but seems to break calculation?
var α3 = Math.Acos(-Math.Cos(α1) * Math.Cos(α2) + Math.Sin(α1) * Math.Sin(α2) * Math.Cos(_var1));
var δ13 = Math.Atan2(Math.Sin(_var1) * Math.Sin(α1) * Math.Sin(α2), Math.Cos(α2) + Math.Cos(α1) * Math.Cos(α3));
var _finalLatRadians = Math.Asin(Math.Sin(_p1LatRadians) * Math.Cos(δ13) + Math.Cos(_p1LatRadians) * Math.Sin(δ13) * Math.Cos(_brng1ToRadians));
var _lonBearing = Math.Atan2(Math.Sin(_brng1ToRadians) * Math.Sin(δ13) * Math.Cos(_p1LatRadians), Math.Cos(δ13) - Math.Sin(_p1LatRadians) * Math.Sin(_finalLatRadians));
var _finalLon = _p1LonToRadians + _lonBearing;
var _returnLat = _finalLatRadians.RadianToDegree();
var _latToDegree = _finalLon.RadianToDegree();
var _returnLon = ( _latToDegree + 540) % 360 - 180;
return new GeoCoordinate(_returnLat, _returnLon);
//return new LatLon(φ3.toDegrees(), (λ3.toDegrees() + 540) % 360 - 180); // normalise to −180..+180°
}