Calculate point between two coordinates based on a percentage

前端 未结 3 863
面向向阳花
面向向阳花 2021-01-02 16:53

I am looking for a function that returns a point (lat, long) between two points (where I also specify their lat, long) and that point is based on a distance percentage.

相关标签:
3条回答
  • 2021-01-02 17:05

    Here is a reference that will help a lot (check the bottom)

    http://www.movable-type.co.uk/scripts/latlong.html

    Intermediate point

    An intermediate point at any fraction along the great circle path between two points can also be calculated.

    Formula:

    a = sin((1−f)⋅δ) / sin δ
    b = sin(f⋅δ) / sin δ
    x = a ⋅ cos φ1 ⋅ cos λ1 + b ⋅ cos φ2 ⋅ cos λ2
    y = a ⋅ cos φ1 ⋅ sin λ1 + b ⋅ cos φ2 ⋅ sin λ2
    z = a ⋅ sin φ1 + b ⋅ sin φ2
    φi = atan2(z, √x² + y²)
    λi = atan2(y, x)
    

    where f is fraction along great circle route (f=0 is point 1, f=1 is point 2), δ is the angular distance d/R between the two points.

    0 讨论(0)
  • 2021-01-02 17:18

    Assuming the coordinate is a decimal number. You can use this equation.

    function midpoint(lat1, long1, lat2, long2, per) {
         return [lat1 + (lat2 - lat1) * per, long1 + (long2 - long1) * per];
    }
    

    Return a new desired coordinate of [lat, long], based on the percentage (such as per=0.2 for 20%).

    0 讨论(0)
  • 2021-01-02 17:20

    Both answers might be useful for specific users, but I would like to point out some issues.

    The solution by lguiel is correct for games or short distances, but does not work for geometric calculations on the earth as a globe.

    The answer by spirographer is correct, but as it is very theoretical it might be too difficult to program.

    I translated the second answer to a practical programming language, so that you can use it for your own projects.

    Full code | Run online

    // Original calculation from https://www.movable-type.co.uk/scripts/latlong.html
    LatLng calculateIntermediatePoint(LatLng point1, LatLng point2, double perc) {
      //const φ1 = this.lat.toRadians(), λ1 = this.lon.toRadians();
      //const φ2 = point.lat.toRadians(), λ2 = point.lon.toRadians();
      double lat1 = degreesToRadians(point1.latitude);
      double lng1 = degreesToRadians(point1.longitude);
      double lat2 = degreesToRadians(point2.latitude);
      double lng2 = degreesToRadians(point2.longitude);
    
      //const Δφ = φ2 - φ1;
      //const Δλ = λ2 - λ1;
      double deltaLat = lat2 - lat1;
      double deltaLng = lng2 - lng1;
    
      //const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2);
      //const δ = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
      double calcA = sin(deltaLat / 2) * sin(deltaLat / 2) +
          cos(lat1) * cos(lat2) * sin(deltaLng / 2) * sin(deltaLng / 2);
      double calcB = 2 * atan2(sqrt(calcA), sqrt(1 - calcA));
    
      //const A = Math.sin((1-fraction)*δ) / Math.sin(δ);
      //const B = Math.sin(fraction*δ) / Math.sin(δ);
      double A = sin((1 - perc) * calcB) / sin(calcB);
      double B = sin(perc * calcB) / sin(calcB);
    
      //const x = A * Math.cos(φ1) * Math.cos(λ1) + B * Math.cos(φ2) * Math.cos(λ2);
      //const y = A * Math.cos(φ1) * Math.sin(λ1) + B * Math.cos(φ2) * Math.sin(λ2);
      //const z = A * Math.sin(φ1) + B * Math.sin(φ2);
      double x = A * cos(lat1) * cos(lng1) + B * cos(lat2) * cos(lng2);
      double y = A * cos(lat1) * sin(lng1) + B * cos(lat2) * sin(lng2);
      double z = A * sin(lat1) + B * sin(lat2);
    
      //const φ3 = Math.atan2(z, Math.sqrt(x*x + y*y));
      //const λ3 = Math.atan2(y, x);
      double lat3 = atan2(z, sqrt(x * x + y * y));
      double lng3 = atan2(y, x);
    
      //const lat = φ3.toDegrees();
      //const lon = λ3.toDegrees();
      return LatLng(radiansToDegrees(lat3), radiansToDegrees(lng3));
    }
    
    0 讨论(0)
提交回复
热议问题