2012-04-16 3 views
2

Actuellement, la formule que je utilise est ci-dessous, mais il est moins précis que la formule Vincenty, que vous pouvez trouver sur ce lien: http://www.movable-type.co.uk/scripts/latlong-vincenty-direct.htmlJavascript et Google Maps Cercle

Ma question est, quelqu'un peut-il aider à simplifier la code javascript pour que je puisse l'implémenter dans ma formule? J'essaye d'apprendre le javascript mais c'est un peu au-delà de mes capacités.

ex = lat2 ey = Lon2

Im penser la façon la plus simple serait d'exécuter le code et faire un tableau de 360 ​​degrés pour calculer les coordonnées ex/ey.

<script type="text/javascript"> 

function drawCircle(point, radius, dir, addtoBounds) { 
var d2r = Math.PI/180; // degrees to radians 
var r2d = 180/Math.PI; // radians to degrees 
var earthsradius = 6378137; 

    var points = 360; 

    // find the radius in lat/lon 
    var rlat = (radius/earthsradius) * r2d; 
    var rlng = rlat/Math.cos(point.lat() * d2r); 


    var extp = new Array(); 
    if (dir==1) {var start=0;var end=points+1} // one extra here makes sure we connect the 
    else  {var start=points+1;var end=0} 
    for (var i=start; (dir==1 ? i < end : i > end); i=i+dir) 
    { 
    var theta = Math.PI * (i/(points/2));//i is number of points + 1 
var lat1=point.lat()*d2r; 
var lon1=point.lng()*d2r; 
var d=radius; 
var R=earthsradius; 

var ex = Math.asin(Math.sin(lat1)*Math.cos(d/R) + 
       Math.cos(lat1)*Math.sin(d/R)*Math.cos(theta)); 
var ey = lon1 + Math.atan2(Math.sin(theta)*Math.sin(d/R)*Math.cos(lat1), 
       Math.cos(d/R)-Math.sin(lat1)*Math.sin(ex)); 
    extp.push(new google.maps.LatLng(ex*r2d, ey*r2d)); 
    if (addtoBounds) bounds.extend(extp[extp.length-1]); 



    } 
    // alert(extp.length); 
    return extp; 


    } 

Voici la formule directe convertie en PHP. J'essaie de mettre ce code dans le code google maps. Le lien de type mobile a effectivement ce code en javascript, mais depuis que je connais php beaucoup mieux, je l'ai converti pour le tester, cela fonctionne parfaitement.

<?php 
$lat1 = 29.10860062; 
$lon1 = -95.46209717; 
$a = 6378137; 
$b = 6356752.314245; 
$f = 1/298.257223563; // WGS-84 ellipsoid params 
$brng = 32.8; 


$s = 1796884.48; 
$alpha1 = deg2rad($brng); 
$sinAlpha1 = sin($alpha1); 
$cosAlpha1 = cos($alpha1); 
$tanU1 = (1-$f) * tan(deg2rad($lat1)); 
$cosU1 = 1/sqrt((1 + pow($tanU1,2))); 
$sinU1 = $tanU1*$cosU1; 
$sigma1 = atan2($tanU1, $cosAlpha1); 
$sinAlpha = $cosU1 * $sinAlpha1; 
$cosSqAlpha = 1 - pow($sinAlpha,2); 
$uSq = $cosSqAlpha * (pow($a,2) - pow($b,2))/(pow($b,2)); 
$A = 1 + $uSq/16384*(4096+$uSq*(-768+$uSq*(320-175*$uSq))); 
$B = $uSq/1024 * (256+$uSq*(-128+$uSq*(74-47*$uSq))); 
$sigma = $s/($b*$A); 
$sigmaP = 2*pi; 

$limit = 100; 
$counter = 1; 

while ($counter <= $limit) { 
$cos2SigmaM = cos(2*$sigma1 + $sigma); 
$sinSigma = sin($sigma); 
$cosSigma = cos($sigma); 
$deltaSigma = $B*$sinSigma*($cos2SigmaM+$B/4*($cosSigma*(-1+2*pow($cos2SigmaM,2))-$B/6*$cos2SigmaM*(-3+4*pow($sinSigma,2))*(-3+4*pow($cos2SigmaM,2)))); 
$sigmaP = $sigma; 
$sigma = $s/($b*$A) + $deltaSigma; 
$counter = $counter+1; 
}; 

$tmp = $sinU1*$sinSigma - $cosU1*$cosSigma*$cosAlpha1; 
$lat2 = atan2($sinU1*$cosSigma + $cosU1*$sinSigma*$cosAlpha1,(1-$f)*sqrt(pow($sinAlpha,2)+ pow($tmp,2))); 
$lambda = atan2($sinSigma*$sinAlpha1, $cosU1*$cosSigma - $sinU1*$sinSigma*$cosAlpha1); 
$C = $f/16*$cosSqAlpha*(4+$f*(4-3*$cosSqAlpha)); 
$L = $lambda - (1-$C) * $f * $sinAlpha *($sigma + $C*$sinSigma*($cos2SigmaM+$C*$cosSigma*(-1+2*pow($cos2SigmaM,2)))); 

if (deg2rad($lon1)+$L+(3*pi)<(2*pi)) { 
( $lon2 = (deg2rad($lon1)+$L+(3*pi))-pi); 
} else { 
( $lon2 = ((deg2rad($lon1)+$L+3*pi))%(2*pi))-pi;} 

$revAz = atan2($sinAlpha, -$tmp); // final bearing, if required 

?> 
+1

Est-ce que [cette question et sa réponse] (http://stackoverflow.com/questions/10027094/holes-in-a-polygon) aide? –

+1

J'apprécie le temps que vous mettez dans ce code. J'en étais très reconnaissant, mais j'ai aussi creusé. J'ai trouvé que la formule de Haversine était moins précise pour ce dont j'avais besoin. La formule Vincenty est ce que je cherche. J'essaie d'adapter votre code à la nouvelle formule. Toute aide est la bienvenue. Merci encore. –

+1

Aha. Ne correspond pas aux noms. –

Répondre

2

Depuis le lien fourni fournit déjà la formule en javascript le plus dur est terminé, il vous suffit de le copier et l'appeler plutôt que de réécrire dans votre fonction. N'oubliez pas d'attribuer la source. J'ai supprimé les variables qui n'étaient pas utilisées. En outre, j'ai juste codé 361 dans la formule puisque vous étiez en train de l'assigner à une variable de points. Vous pouvez changer cela si vous allez passer le nombre de degrés dans la formule. J'ai séparé les boucles for, pour moi c'est plus lisible, et je ne pense pas que la façon dont vous aviez auparavant fonctionnait comme vous l'aviez prévu. Lorsque je travaille avec des degrés et des radians, je place toujours ces conversions dans des fonctions car cela améliore la lisibilité. Pour ce faire, je les ai accroché à l'objet Number en utilisant JavaScript prototype comme on le voit ici:

Number.prototype.toRad = function() { 
    //'this' is the current number the function is acting on. 
    //e.g. 360.toRad() == 2PI radians 
    return this * Math.PI/180; 
} 

Number.prototype.toDeg = function() { 
    return this * 180/Math.PI; 
} 

Pas trop difficile à comprendre, prototype vous permet d'étendre les objets JavaScript, similaires à l'héritage dans les langues à base de classe. Il y a beaucoup de ressources en ligne qui peuvent aider à clarifier.

est ici la fonction drawCircle retravaillé:

function drawCircle(point, radius, dir, addtoBounds) { 
    //best practice is to use [] rather then new Array(), 
    //both do the same thing. 
    var extp = []; 
    if (dir == 1) { 
     for (var i = 0; i < 361; i++) { 
      //destVincenty function returns a object with 
      //lat, lon, and final bearing.  
      var destPoint = destVincenty(point.lat(), point.lng(), i, radius); 

      //add new point 
      extp.push(new google.maps.LatLng(destPoint.lat, destPoint.lon)); 
      if (addtoBounds) bounds.extend(extp[extp.length - 1]); 
     } 
    } 
    else { 
     for (var i = 361; i > 0; i--) {  
      var destPoint = destVincenty(point.lat(), point.lng(), i, radius); 
      extp.push(new google.maps.LatLng(destPoint.lat, destPoint.lon)); 
      if (addtoBounds) bounds.extend(extp[extp.length - 1]); 
     } 
    } 

    return extp; 
} 

ici est un fiddle of it working.

+1

Ive déterminé pourquoi je suis lent à apprendre javascript, il ne vous dit pas où l'erreur est comme le php. Bryan, Il m'a fallu environ une heure après que tu m'as donné ce code pour le faire fonctionner, j'ai dû changer quelques choses autour d'ect, la formule est parfaite. J'ai ajouté l'ombrage qu'Andrew Leach a fourni la semaine dernière (voir le lien qu'il a posté). Merci beaucoup pour le moment. –

+1

Oui, le débogage JavaScript peut parfois être douloureux. Il existe un certain nombre d'outils qui aident à localiser et déboguer les erreurs. Voici une liste de certains des plus communs. Personnellement, j'aime Firebug et l'outil de développement intégré IE9. http://www.smashingmagazine.com/2008/11/18/15-helpful-in-browser-web-development-tools/ –