【问题标题】:How to find a geographic point between two other points如何在其他两个点之间找到一个地理点
【发布时间】:2011-10-06 15:41:50
【问题描述】:

对于我的应用程序,我必须在谷歌地图上找到一个点的位置,只知道它位于其他 2 个点之间以及捕获坐标的时间(以毫秒为单位)。

在我的代码中,假设 A 和 B 作为给定点,X 作为要查找的点,我:

  1. 计算 A 和 B 之间的距离

  2. 根据时间,我发现了从 A 到 B 的速度(以微度/毫秒为单位)

  3. 我找到了A点和X点的距离(使用时间和速度)

  4. 使用相似三角形的规则,我从点A计算点X的经纬度

此工作流程会在地图上显示错误,因此 X 标记通常不在 A 和 B 标记之间的线上。

我怎样才能让它更好地工作?是不是地球的球度有问题?

谢谢大家。

代码如下:

    int ax = oldPoint.getLatitude();
    int ay = oldPoint.getLongitude();

    int bx = currentPoint.getLatitude();
    int by = currentPoint.getLongitude();

    long at = oldPoint.getDataRilevamento(); //get time first point
    long bt = currentPoint.getDataRilevamento(); // get time second point
    long xt = x.getDate(); // time of point to find

    int c1 = bx-ax;
    int c2 = by-ay;
    double hyp =  Math.sqrt(Math.pow(c1, 2) + Math.pow(c2, 2));

    double vel = hyp / (bt-at);

    double pos = vel*(xt - at);

    int posx = (int)((pos*c1)/hyp);
    int posy = (int)((pos*c2)/hyp);

    x.setLatitude(ax+posx); //set the latitude of X
    x.setLongitude(ay+posy); // set the longitude of X

【问题讨论】:

    标签: java android maps latitude-longitude


    【解决方案1】:

    您的问题可以通过以下步骤来解决。

    • 计算点 A 和 B 的距离。这个计算称为求解“逆测地线问题”,这在 C.F.F. 中有讨论。 Karney 的文章“Algorithms for geodesics, 2012。下面的代码使用了Haversine formula,它不如 Karney 文章中介绍的算法准确。要使用 公式正确,Android 的微度数,即 getLatitude 和 getLongitude 返回,必须转换为弧度, 使用这样的公式:

        double radians = Math.toRadians((double)microdegrees/1000000);
      
    • 从A点和B点计算方位角(方向)(使用公式 在同一页上)。这将不同于毕达哥拉斯公式,因为 地球是圆的,不是平的。

    • 然后你可以选择一个新的距离并计算给定的点 X 点 A 和在上一步中找到的轴承。这被称为解决“直接测地线问题”。

    • 使用以下公式将生成点的弧度转换为微度:

        int microdegrees = (int)(Math.toDegrees(radians)*1000000);
      

    综上所述,我们有以下功能,我将其置于公共领域:

        public static int[] getIntermediatePoint(
            int startLatMicroDeg,
            int startLonMicroDeg,
            int endLatMicroDeg,
            int endLonMicroDeg,
            double t // How much of the distance to use, from 0 through 1
        ){
            // Convert microdegrees to radians
            double alatRad=Math.toRadians((double)startLatMicroDeg/1000000);
            double alonRad=Math.toRadians((double)startLonMicroDeg/1000000);
            double blatRad=Math.toRadians((double)endLatMicroDeg/1000000);
            double blonRad=Math.toRadians((double)endLonMicroDeg/1000000);
            // Calculate distance in longitude
            double dlon=blonRad-alonRad;
            // Calculate common variables
            double alatRadSin=Math.sin(alatRad);
            double blatRadSin=Math.sin(blatRad);
            double alatRadCos=Math.cos(alatRad);
            double blatRadCos=Math.cos(blatRad);
            double dlonCos=Math.cos(dlon);
            // Find distance from A to B
            double distance=Math.acos(alatRadSin*blatRadSin +
                                      alatRadCos*blatRadCos *
                                      dlonCos);
            // Find bearing from A to B
            double bearing=Math.atan2(
                Math.sin(dlon) * blatRadCos,
                alatRadCos*blatRadSin -
                alatRadSin*blatRadCos*dlonCos);
            // Find new point
            double angularDistance=distance*t;
            double angDistSin=Math.sin(angularDistance);
            double angDistCos=Math.cos(angularDistance);
            double xlatRad = Math.asin( alatRadSin*angDistCos +
                                       alatRadCos*angDistSin*Math.cos(bearing) );
            double xlonRad = alonRad + Math.atan2(
                Math.sin(bearing)*angDistSin*alatRadCos,
                angDistCos-alatRadSin*Math.sin(xlatRad));
            // Convert radians to microdegrees
            int xlat=(int)Math.round(Math.toDegrees(xlatRad)*1000000);
            int xlon=(int)Math.round(Math.toDegrees(xlonRad)*1000000);
            if(xlat>90000000)xlat=90000000;
            if(xlat<-90000000)xlat=-90000000;
            while(xlon>180000000)xlon-=360000000;
            while(xlon<=-180000000)xlon+=360000000;
            return new int[]{xlat,xlon};
        }
    

    它的使用方法如下:

    int ax = oldPoint.getLatitude();
    int ay = oldPoint.getLongitude();
    
    int bx = currentPoint.getLatitude();
    int by = currentPoint.getLongitude();
    
    long at = oldPoint.getDataRilevamento(); //get time first point
    long bt = currentPoint.getDataRilevamento(); // get time second point
    long xt = x.getDate(); // time of point to find
    
    // Find relative time from point A to point B
    double t=(bt==at) ? 0 : ((double)(xt-at))/((double)(bt-at));
    // Find new point given the start and end points and the relative time
    int[] xpos=getIntermediatePoint(ax,ay,bx,by,t);
    x.setLatitude(xpos[0]); //set the latitude of X
    x.setLongitude(xpos[1]); // set the longitude of X
    

    【讨论】:

    • 感谢您发布此算法。我需要为我的项目做类似的事情,我相信这会做到!你介意我把它包装起来并作为一个 npm 模块发布吗?
    • 三年多之后:起首!
    • 谢谢!我将它重写为 PL/SQL 用于服务器端功能,它可以满足我的需求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 2014-07-23
    • 2021-10-16
    • 2014-02-01
    • 2015-02-10
    • 1970-01-01
    相关资源
    最近更新 更多