Point le plus proche sur une ligne (projection sphérique / Mercator)

9

J'ai une ligne (Axe, Ay - Bx, By) sur une projection mercator (google maps) et un point aléatoire (Cx, Cy) le plus proche de cette ligne, je voudrais connaître le point le plus proche (bleu transparent sur l'image) sur cette ligne au point (bleu dans l'image)

EDIT: pour préciser qu'il s'agit d'une projection Mercator (projection sphérique) entrez la description de l'image ici

Colas
la source
3
ce message a une solution très utile qui peut vous intéresser stackoverflow.com/questions/3120357/get-closest-point-to-a-line
vinayan
1
Ce bleu clair ne ressemble pas au plus proche, le plus proche devrait créer un angle de 90 degrés lorsqu'il est connecté au bleu foncé, c'est ce que vous voulez dire?
Glenn Plas
J'ai fait la photo à la main alors oui, c'est possible
Colas
@vinayan Le message que vous référencez résout un problème différent de recherche du point le plus proche d'une ligne , alors que ce qui est nécessaire ici semble vouloir le point le plus proche d'un segment de ligne .
whuber
1
Le segment devrait être d'environ 20 à 100 mètres de long, le point de centimètres à 30 mètres autant du segment
Colas

Réponses:

2

consultez ce lien , il m'a fait utiliser la fonction suivante pour calculer les distances aux segments de ligne.

En PHP:

function point_to_line_segment_distance($startX,$startY, $endX,$endY, $pointX,$pointY) {

   // list($distanceSegment, $x, $y) = point_to_line_segment_distance($startX,$startY, $endX,$endY, $pointX,$pointY);

    // Adapted from Philip Nicoletti's function, found here: http://www.codeguru.com/forum/printthread.php?t=194400

    $r_numerator = ($pointX - $startX) * ($endX - $startX) + ($pointY - $startY) * ($endY - $startY);
    $r_denominator = ($endX - $startX) * ($endX - $startX) + ($endY - $startY) * ($endY - $startY);
    $r = $r_numerator / $r_denominator;

    $px = $startX + $r * ($endX - $startX);
    $py = $startY + $r * ($endY - $startY);

    $s = (($startY-$pointY) * ($endX - $startX) - ($startX - $pointX) * ($endY - $startY) ) / $r_denominator;

    $distanceLine = abs($s) * sqrt($r_denominator);

    $closest_point_on_segment_X = $px;
    $closest_point_on_segment_Y = $py;

    if ( ($r >= 0) && ($r <= 1) ) {
       $distanceSegment = $distanceLine;
    }
    else {
       $dist1 = ($pointX - $startX) * ($pointX - $startX) + ($pointY - $startY) * ($pointY - $startY);
       $dist2 = ($pointX - $endX) * ($pointX - $endX) + ($pointY - $endY) * ($pointY - $endY);
       if ($dist1 < $dist2) {
          $closest_point_on_segment_X = $startX;
          $closest_point_on_segment_Y = $startY;
          $distanceSegment = sqrt($dist1);
       }
       else {
          $closest_point_on_segment_X = $endX;
          $closest_point_on_segment_Y = $endY;
          $distanceSegment = sqrt($dist2);
       }
    }

    return array($distanceSegment, $closest_point_on_segment_X, $closest_point_on_segment_Y);
}

Vous pouvez ensuite utiliser les fonctions de projection pour calculer les distances, j'utilise la formule ci-dessus pour calculer le temps à ce point étant donné une vitesse moyenne et cela fonctionne très bien.

Si vous voulez une bonne bibliothèque PHP pour calculer les distances entre les coordonnées en PHP, consultez la classe GeoCalc

Glenn Plas
la source
Hé Glenn Plas, ta classe semble avoir un petit décalage à gauche ou à droite, j'ai fait une capture d'écran sur Google Earth, tu verras ce décalage, la photo: lien , le code que j'ai utilisépoint_to_line_segment_distance(41.421649, 2.600410, 41.413851, 2.594356, 41.415710, 2.600638))
Colas
Ce n'est pas ma classe, je l'ai juste trouvé après avoir beaucoup cherché ;-) Mais j'utilise une précision à 8 chiffres dans mes problèmes, vous semblez en utiliser 6. Cela pourrait être la raison, je n'ai jamais remarqué de décalage ici. Merci de l'avoir signalé, je revérifierai cela dès que j'aurai besoin de le savoir.
Glenn Plas
Peut-être que vous êtes rihgt, je ne peux pas obtenir plus de décilmas sur gEarth, btw dans ma dernière photo, le segment mesurait 1000 mètres de long, le décalage était de ~ 110 mètres
Colas
C'est à peu près l'échelle sur laquelle je l'utilise, pas plus que cela. Je l'utilise pour voir à quelle heure un bus (transports en commun) passe un arrêt le plus proche. Je vais cependant le vérifier et le mettre sur une carte pour «voir» s'il se projette bien sur une sphère.
Glenn Plas
Oh ... je pensais que cette fonction était faite pour les projections sphériques, alors maintenant je comprends le décalage
Colas
1

vous pouvez utiliser la fonction computeDistanceBetween () de Google Map API .

distance = google.maps.geometry.spherical.computeDistanceBetween(firstCoord, secondCoord);

La distance entre deux points est la longueur du chemin le plus court entre eux. Ce chemin le plus court est appelé géodésique. Sur une sphère, toutes les géodésiques sont des segments d'un grand cercle. Pour calculer cette distance, appelez computeDistanceBetween (), en lui passant deux objets LatLng.

Vous pouvez à la place utiliser computeLength () pour calculer la longueur d'un chemin donné si vous avez plusieurs emplacements

J'espère que ça t'aide...

Aragon
la source
je dois d'abord connaître le point (bleu clair) pour calculer la distance entre
Colas
Ma solution ci-dessous fait cela, le point sur le segment est inconnu. J'ai en fait un problème / solution assez similaire à celui mentionné. Vous pouvez les utiliser en toute sécurité à petite échelle.
Glenn Plas