如何找到其他两点之间的地理点

发布于 2024-12-08 18:47:01 字数 1144 浏览 0 评论 0原文

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

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

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

  2. 根据我发现的时间

    从 A 到 B 的速度(以微度/毫秒为单位)

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

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

此工作流程会在地图上产生错误,因此 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

For my application I have to find the position of a point on Google map knowing only that it's located between 2 other points and the time (in ms) when the coordinates have been caught.

In my code, assumed A and B as the points given and X as the point to find, I:

  1. calculate distance between A and B

  2. basing on time I found out the speed (in micro degrees /ms) to travel from A to B

  3. I found the distance from point A and point X (using time and speed)

  4. using similar triangle's rule, I calculate latitude and longitude of point X from point A

This workflow bring out errors on the map, so, often the X marker is not on the line between A and B markers.

How can I make it works better? Is it a problem with the sphericity of the globe?

Thank you to all.

Here is the code:

    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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蘸点软妹酱 2024-12-15 18:47:01

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

  • 计算点 A 和 B 的距离。这种计算称为求解“逆测地线问题”,这在 CFF Karney 的文章“测地线算法,2012。下面的代码使用Haversine 公式,该公式不如 中介绍的算法准确使用卡尼的文章。
    公式正确的话,Android的微度,就是getLatitude
    而getLongitude返回,必须转换为弧度,
    使用这样的公式:

     双弧度 = Math.toRadians((双)微度/1000000);
    
  • 计算 A 点和 B 点的方位(方向)(使用以下公式
    在同一页上)。这与毕达哥拉斯公式不同,因为
    地球是圆的,不是平的。

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

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

     int 微度 = (int)(Math.toDegrees(弧度)*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

Your problem can be solved by taking the following steps.

  • Calculate the distance from points A and B. This calculation is called solving the "inverse geodesic problem", and this is discussed in C.F.F. Karney's article "Algorithms for geodesics, 2012. The code below uses the Haversine formula, which is not as accurate as the algorithms presented in Karney's article. To use the
    formula correctly, Android's microdegrees, which is what getLatitude
    and getLongitude return, must be converted to radians,
    using a formula like this:

      double radians = Math.toRadians((double)microdegrees/1000000);
    
  • Calculate the bearing (direction) from points A and B (use the formula
    on the same page). This will be different from the Pythagorean formula because the
    earth is round, not flat.

  • Then you can choose a new distance and calculate point X given
    point A and the bearing found in the previous step. This is called solving the "direct geodesic problem".

  • Convert the radians from the generated point into microdegrees using this formula:

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

Putting it all together, we have the following function, which I place in the public domain:

    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};
    }

And here's how it's used:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文