【问题标题】:midpoint between two latitude and longitude两个纬度和经度之间的中点
【发布时间】:2011-01-11 10:50:22
【问题描述】:

我正在尝试将http://www.movable-type.co.uk/scripts/latlong.html 中给出的代码 sn-p 转换为 java。但我没有得到与网站相同的结果。这是我的代码,用于查找给定纬度和经度的两点之间的中点

midPoint(12.870672,77.658964,12.974831,77.60935);
    public static void midPoint(double lat1,double lon1,double lat2,double lon2)
    {
   double dLon = Math.toRadians(lon2-lon1);
        double Bx = Math.cos(lat2) * Math.cos(dLon);
        double By = Math.cos(lat2) * Math.sin(dLon);
        double lat3 = Math.atan2(Math.sin(lat1)+Math.sin(lat2),Math.sqrt( (Math.cos(lat1)+Bx)*(Math.cos(lat1)+Bx) + By*By) );
        double lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
        System.out.print(lat3 +" " + lon3 );
    }

我不确定 dLon 是否正确。所以请大家帮我弄清楚。 P.S.我需要找到中点的经纬度

【问题讨论】:

    标签: java math maps


    【解决方案1】:

    您需要转换为弧度。将其更改为以下内容:

    public static void midPoint(double lat1,double lon1,double lat2,double lon2){
    
        double dLon = Math.toRadians(lon2 - lon1);
    
        //convert to radians
        lat1 = Math.toRadians(lat1);
        lat2 = Math.toRadians(lat2);
        lon1 = Math.toRadians(lon1);
    
        double Bx = Math.cos(lat2) * Math.cos(dLon);
        double By = Math.cos(lat2) * Math.sin(dLon);
        double lat3 = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By));
        double lon3 = lon1 + Math.atan2(By, Math.cos(lat1) + Bx);
    
        //print out in degrees
        System.out.println(Math.toDegrees(lat3) + " " + Math.toDegrees(lon3));
    }
    

    【讨论】:

    【解决方案2】:

    Android Google Maps Utilities 更容易:

    LatLngBounds bounds = new LatLngBounds(start, dest);
    bounds.getCenter();
    

    更新: 更好地使用构建器(为什么参见Bad Losers Answer):

    LatLngBounds.builder().include(start).include(dest).build().getCenter();
    

    【讨论】:

    • 运行良好,为我节省了一些编码。谢谢。
    • @leonardkraemer 可以,但不完美[未处理反子午线违规] - 请参阅下面的答案。感谢您让我走上正轨。
    • 据我记得构造函数甚至抱怨,当你把 NE 放在 SW 之前,所以一定要使用生成器。我可能让我的答案过于简单,只是为了给人们指明正确的方向。感谢您的提示。
    • 非常感谢您的“更新”部分。解决了我的问题。
    【解决方案3】:

    如果您想正确处理反子午线(经度 +/-180 )。

    这是说明问题的测试:

    LatLng mp = midPoint(new LatLng(-43.95139,-176.56111),new LatLng(-36.397816,174.663496));
    public static LatLng midPoint (LatLng SW, LatLng NE) {
        LatLngBounds bounds = new LatLngBounds(SW, NE);
        Log.d("BAD!", bounds.toString() + " CENTRE: " + bounds.getCenter().toString());
        bounds = LatLngBounds.builder().include(SW).include(NE).build();
        Log.d("GOOD", bounds.toString() + " CENTRE: " + bounds.getCenter().toString());
        return bounds.getCenter();
    }
    

    实际结果:

    BAD!: LatLngBounds{southwest=lat/lng: (-43.95139,-176.56111), northeast=lat/lng: (-36.397816,174.663496)} CENTRE: lat/lng: (-40.174603,-0.948807)
    GOOD: LatLngBounds{southwest=lat/lng: (-43.95139,174.663496), northeast=lat/lng: (-36.397816,-176.56111)} CENTRE: lat/lng: (-40.174603,179.051193)
    

    构造函数技术产生一个中心经度向外 180 度!

    【讨论】:

      【解决方案4】:

      您还需要将其他公式中使用的纬度和经度值转换为弧度。您可以在页面下方约 3/5 的代码中看到这一点。余弦距离公式的球面定律最后给出了线索​​:

      (请注意,此处和所有后续代码片段中,为简单起见,我没有显示从度数到弧度的转换;完整版本请参见下文)。

      【讨论】:

        【解决方案5】:

        以下是@dogbane 的java 代码转换为Kotlin

        private fun midPoint(lat1: Double, lon1: Double, lat2: Double, lon2: Double) : String {
            var lat1 = lat1
            var lon1 = lon1
            var lat2 = lat2
            val dLon: Double = Math.toRadians(lon2 - lon1)
            //convert to radians
            lat1 = Math.toRadians(lat1)
            lat2 = Math.toRadians(lat2)
            lon1 = Math.toRadians(lon1)
            val Bx: Double = Math.cos(lat2) * Math.cos(dLon)
            val By: Double = Math.cos(lat2) * Math.sin(dLon)
            val lat3: Double = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) * (Math.cos(lat1) + Bx) + By * By))
            val lon3: Double = lon1 + Math.atan2(By, Math.cos(lat1) + Bx)
            var result: String = ""
            result = Math.toDegrees(lat3).toString() + "," + Math.toDegrees(lon3).toString()
            return result;
        }
        

        【讨论】:

          【解决方案6】:

          这是@dogbane 的Java 代码转换为TypeScript

          type LatLng = {
            lat: number;
            lng: number;
          };
          
          function calculateMidPoint(latLngA: LatLng, latLngB: LatLng) {
            function toRadians(degress: number): number {
              return degress * (Math.PI / 180);
            }
          
            function toDegrees(radians: number): string {
              return (radians * (180 / Math.PI)).toFixed(4);
            }
          
            const lngDiff = toRadians(latLngB.lng - latLngA.lng);
            const latA = toRadians(latLngA.lat);
            const latB = toRadians(latLngB.lat);
            const lngA = toRadians(latLngA.lng);
          
            const bx = Math.cos(latB) * Math.cos(lngDiff);
            const by = Math.cos(latB) * Math.sin(lngDiff);
          
            const latMidway = toDegrees(
              Math.atan2(
                Math.sin(latA) + Math.sin(latB),
                Math.sqrt((Math.cos(latA) + bx) * (Math.cos(latA) + bx) + by * by)
              )
            );
            const lngMidway = toDegrees(lngA + Math.atan2(by, Math.cos(latA) + bx));
          
            console.log(
              `Midway point between ${latLngA} and ${latLngB} is: Lat: ${latMidway}, lng: ${lngMidway}`
            );
          }
          

          【讨论】:

            【解决方案7】:

            我的上一份工作是制作一个跟踪模块,我使用这个公式来计算 2 个坐标之间的距离。

            //Location lat and lon
            double locLat = -23.548333;
            double locLon = -46.636111;
            
            //Destination lat and lon
            double dstLat = -22.902778;
            double dstLon = -43.206667;
            
            double arcoAB = 90 - (dstLat);
            double arcoAC = 90 - (locLat);
            
            double difLon = locLon - (dstLon);
            
            double cosA = Math.cos(Math.toRadians(arcoAC)) * Math.cos(Math.toRadians(arcoAB)) + Math.sin(Math.toRadians(arcoAC)) * Math.sin(Math.toRadians(arcoAB)) * Math.cos(Math.toRadians(difLon));
            double acosCosA = Math.toDegrees(Math.acos(cosA));
            
            double raio = 2 * Math.PI * 6371;
            double distance = (raio * acosCosA) / 360;
            
            return distance; //Distance in KM, convert to anything else (miles, meters..) if you need..
            

            你可以得到中点除以距离2。

            啊,这另一个公式也有效:

            double dLat = Math.toRadians(dstLat - locLat);
            double dLon = Math.toRadians(dstLon - locLon);
            
            double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
                       + Math.cos(Math.toRadians(locLat)) * Math.cos(Math.toRadians(dstLat))
                       * Math.sin(dLon / 2) * Math.sin(dLon / 2);
            double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            double d = 6371 * c;
            
            return d; //Distance in KM
            

            【讨论】:

            • 但是我需要找到中点的经纬度。该怎么做?
            • @scooby 你找到解决方案了吗?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-10
            • 2012-10-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多