ГАЗ - Рассчитать расстояние - PullRequest
1 голос
/ 23 октября 2019

Я знаю, что одним из лучших сценариев для расчета расстояния между двумя точками является VBA-скрипт, который я нашел здесь ....

Теперь я попытался "преобразовать""этот скрипт из VBA в Google Apps Script. Даже я действительно пытался преобразовать это шаг за шагом, но я получаю совершенно другой (неправильный) результат, и я не вижу причины для этого. Что не так с кодом? Я знаю, что есть и другие функции, обеспечивающие результат. Но ни один из них не такой точный, как этот.

function toRad(degree){
return degree * Math.PI / 180;
}

function quadrat(quadrat){
return Math.pow(quadrat,2);
}


function distances(lon1, lat1, lon2, lat2) {  

  var EPSILON = 0.000000000001;
  var low_a = 6378137;
  var low_b = 6356752.3142;
  var f = 1 / 298.257223563;
  var L = toRad((lon2 - lon1));
  var U1 = Math.atan((1 - f) * Math.tan(toRad(lat1))); //Atn = Atan!!!
  var U2 = Math.atan((1 - f) * Math.tan(toRad(lat2))); //Atn = Atan!!!

  var sinU1 = Math.sin(U1);
  var cosU1 = Math.cos(U1);
  var sinU2 = Math.sin(U2);
  var cosU2 = Math.cos(U2);

  var lambda = L;
  var lambdaP = 2 * Math.PI;
  var iterLimit = 100; // can be set as low as 20 if desired.

  while ( (Math.abs((lambda - lambdaP)) > EPSILON && iterLimit > 0)){
    iterLimit = (iterLimit - 1);
    var sinLambda = Math.sin(lambda);
    var cosLambda = Math.cos(lambda);
    var sinSigma = Math.sqrt( (quadrat((cosU2 * sinLambda))  + quadrat(((cosU1 * sinU2) - (sinU1 * cosU2 * cosLambda)))) );

    if (sinSigma == 0){
      var distances = 0; //co-incident points
      break;
    }
    var cosSigma = ((sinU1 * sinU2) + (cosU1 * cosU2 * cosLambda));
    var sigma = Math.atan2(cosSigma, sinSigma);
    var sinAlpha = ((cosU1 * cosU2 * sinLambda) / sinSigma);
    var cosSqAlpha = (1 - (sinAlpha * sinAlpha));

    if (cosSqAlpha == 0){ //check for a divide by zero
      var cos2SigmaM = 0; //2 points on the equator
    }
    else{
      cos2SigmaM = (cosSigma - ((2 * sinU1 * sinU2) / cosSqAlpha));
      }
    var c = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
    lambdaP = lambda;
    var P1 = (-1 + (2 * quadrat(cos2SigmaM)));
    var P2 = (sigma + (c * sinSigma * (cos2SigmaM + (c * cosSigma * P1))));
    lambda = (L + ((1 - c) * (f * sinAlpha * P2)));
    }

  var uSq = cosSqAlpha * (quadrat(low_a) - quadrat(low_b)) / quadrat(low_b);

  P1 = (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
  var upper_A = 1 + uSq / 16384 * P1;
  var upper_B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
  P1 = (-3 + 4 * quadrat(sinSigma)) * (-3 + 4 * quadrat(cos2SigmaM));
  P2 = upper_B * sinSigma;
  var P3 = (cos2SigmaM + upper_B / 4 * (cosSigma * (-1 + 2 * quadrat(cos2SigmaM)) - upper_B / 6 * cos2SigmaM * P1));
  var deltaSigma = P2 * P3;
  var S = low_b * upper_A * (sigma - deltaSigma); 
  var finalresult = +S.toFixed(3);

  return finalresult; 
}

Кстати ... этот работает, но он не такой точный, как VBA-скрипт.

function distVincenty(lon1, lat1, lon2, lat2) {

  var R = 6371000; // radius of the earth in meters, https://en.wikipedia.org/wiki/Earth_radius
  var dLon = (lon2-lon1) * Math.PI / 180; // Convert degrees to radians
  var dLat = (lat2-lat1) * Math.PI / 180; // Convert degrees to radians
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) *
          Math.sin(dLon/2) * Math.sin(dLon/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;

  // Distance in meters, rounded to an integer.
  return d
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...