在两个位置之间的直线上的各个位置推导出 Lat\Lng 坐标

Posted

技术标签:

【中文标题】在两个位置之间的直线上的各个位置推导出 Lat\\Lng 坐标【英文标题】:Deduce Lat\Lng coordinates at various places on a line between two locations在两个位置之间的直线上的各个位置推导出 Lat\Lng 坐标 【发布时间】:2012-10-27 11:43:31 【问题描述】:

我有两组 lat/lng 坐标,我在视觉上在它们之间画了一条线。 当你沿着这条线“走”时,有没有一种方法可以推断出纬度/经度坐标

所以沿线的 10% 处,纬度/经度将是

沿线的 20% 处,纬度/经度将是

沿线的 30% 处,纬度/经度将是

等等。

我希望 sql 中的地理资料可能有一个简单的解决方案..

理想情况下在 SQL(SQL Server 2008 R2 数据库)或 - 如果太棘手 - 可能在 C# 中

任何帮助将不胜感激

谢谢

【问题讨论】:

这条线是在球面上还是在平地? 一个国家只有两个地点——如果有帮助的话——可能在那个国家的任何地方——比如两个城市之间 一条直线 - 就像乌鸦飞过一样 - 就足够了 - 正如你所知道的,地理信息(和术语)不是我的强项 - 想象一下它在两个位置之间的谷歌地图上是一条直线。对不起,如果我没有正确解释这一点 如果我们假设乌鸦可以飞越珠穆朗玛峰,而且你永远不会越过两极或 -180/180 线,那将是微不足道的。 【参考方案1】:

这个 C# 库提供了许多可能有所帮助的工具:

http://www.gavaghan.org/blog/free-source-code/geodesy-library-vincentys-formula/

编辑 这使用地图投影,因此不使用直线。您需要注意,纬度之间的距离或多或少是恒定的,但经度之间的距离取决于纬度。

除了上面的库之外,还有一些更简单的近似值,用于测量两点之间的距离,以及给定距离处的点坐标和从起点开始的方位。

这是一些测量两点之间距离的代码:

double lat1 = FSConvert.DegreesToRadians(start.Latitude.Decimal);
                        double lon1 = FSConvert.DegreesToRadians(start.Longitude.Decimal) * -1;
                        double lat2 = FSConvert.DegreesToRadians(end.Latitude.Decimal);
                        double lon2 = FSConvert.DegreesToRadians(end.Longitude.Decimal) * -1;
                        double result = Math.Acos(Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon1 - lon2));
                        distance = FSConvert.DradtoMeters(result);

这是一些计算轴承的代码:

if (start == null || end == null)
                        
                            return 0.0f;
                        

                        double lat1 = FSConvert.DegreesToRadians(start.Latitude.Decimal);
                        double lon1 = FSConvert.DegreesToRadians(start.Longitude.Decimal) * -1;
                        double lat2 = FSConvert.DegreesToRadians(end.Latitude.Decimal);
                        double lon2 = FSConvert.DegreesToRadians(end.Longitude.Decimal) * -1;
                        double y = Math.Atan2(Math.Sin(lon1 - lon2) * Math.Cos(lat2), Math.Cos(lat1) * Math.Sin(lat2) - Math.Sin(lat1) * Math.Cos(lat2) * Math.Cos(lon1 - lon2));
                        const double x = 2 * Math.PI;
                        double result = y - x * Math.Floor(y / x);
                        bearing = FSConvert.RadiansToDegrees(result);

这是一些代码,用于根据距原点的距离和方位计算终端坐标

double lat1 = FSConvert.DegreesToRadians(start.Latitude.Decimal);
                        double lon1 = FSConvert.DegreesToRadians(start.Longitude.Decimal) * -1;
                        double d = FSConvert.MetersToDrad(distance);
                        double tc = FSConvert.DegreesToRadians(bearing);

                        double lat = Math.Asin(Math.Sin(lat1) * Math.Cos(d) + Math.Cos(lat1) * Math.Sin(d) * Math.Cos(tc));
                        double lon = ((lon1 - Math.Asin(Math.Sin(tc) * Math.Sin(d) / Math.Cos(lat)) + Math.PI) % (2 * Math.PI)) - Math.PI;

                        var returnPoint = new FSPoint 
                            Latitude = 
                                Decimal = FSConvert.RadiansToDegrees(lat)
                            ,
                            Longitude = 
                                Decimal = FSConvert.RadiansToDegrees(lon) * -1
                            
                        ;
                        point = returnPoint;

对 FSConvert 的引用只是更改 RadiansToDegrees 等等 - 这是微不足道的。 FSPoint 只是一个 lat/long 结构。

所以流程是:

    计算两点之间的距离和方位 将距离除以 10 0r 什么的 使用增量距离和方位计算终端坐标。 一直坚持下去,直到到达另一端

如果您需要更多帮助,请告诉我

【讨论】:

【参考方案2】:

在 JAVA 中,您可以使用此代码,并且效果很好(从上面 ScruffyDuck 的回复转换而来)

double x2 = next.latitude; 
                double y2 = next.longitude;
                double x1 = current.latitude;
                double y1 = current.longitude;

                double lat1 = Math.toRadians(x1);
                double lon1 = Math.toRadians(y1) * -1;
                double lat2 = Math.toRadians(x2);
                double lon2 = Math.toRadians(y2) * -1;
                double distance = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));

                double var1 = Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
                double var2 = 2 * Math.PI;
                double bearing = var1 - var2 * Math.floor(var1 / var2);

                double lat = Math.asin(Math.sin(lat1) * Math.cos(distance) + Math.cos(lat1) * Math.sin(distance) * Math.cos(bearing));
                double lon = ((lon1 - Math.asin(Math.sin(bearing) * Math.sin(distance) / Math.cos(lat)) + Math.PI) % (2 * Math.PI)) - Math.PI;

                double x = Math.toDegrees(lat);
                double y = Math.toDegrees(lon) * -1;
                //****************

                Location l = new Location("temp");
                l.setLatitude(x);
                l.setLongitude(y); 

【讨论】:

以上是关于在两个位置之间的直线上的各个位置推导出 Lat\Lng 坐标的主要内容,如果未能解决你的问题,请参考以下文章

MFC如何获取控件在对话框上的位置坐标

地图上的两点怎样计算距离

Segments---poj3304(判断直线与线段的位置关系)

点与线线与线之间的位置关系

表行之间的垂直线。合并两个单元格(标题)

如何使用 GMSMapView 在 iOS 中找到两个位置之间的最短路径并绘制锯齿形路径?