Najbliższy punkt na linii (rzut sferyczny / Mercator)


9

Mam linię (Ax, Ay - Bx, By) nad projekcją mercatora (Google Maps) i losowy punkt (Cx, Cy) najbliższy tej linii, chciałbym znać najbliższy punkt (przezroczysty niebieski na obrazie) ponad ta linia do punktu (niebieski na obrazie)

EDYCJA: aby wyjaśnić, że jest to projekcja Mercatora (projekcja sferyczna) wprowadź opis zdjęcia tutaj


3
ten post ma bardzo przydatne rozwiązanie, które może Cię zainteresować stackoverflow.com/questions/3120357/get-closest-point-to-a-line
vinayan

1
Jasnoniebieski nie wygląda jak najbliższy, najbliższy powinien stworzyć kąt 90 stopni po podłączeniu do ciemnoniebieskiego, czy to masz na myśli?
Glenn Plas,

Zrobiłem zdjęcie ręcznie, więc tak, jest możliwe
Colas

@vinayan Odwołany post rozwiązuje inny problem ze znalezieniem najbliższego punktu do linii , podczas gdy to, co jest tutaj potrzebne, wydaje się wymagać najbliższego punktu do segmentu linii .
whuber

1
Długość odcinka powinna wynosić około 20–100 metrów, a odległość od centymetrów do 30 metrów tyle, ile wynosi odcinek
Colas

Odpowiedzi:


2

sprawdź ten link , dzięki temu użyłem następującej funkcji do obliczenia odległości do segmentów linii.

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

Następnie możesz użyć funkcji projekcji do obliczenia odległości, używam powyższej formuły do ​​obliczenia czasu w tym punkcie, biorąc pod uwagę średnią prędkość i działa naprawdę dobrze.

Jeśli chcesz, aby dobra biblioteka PHP obliczała odległości między współrzędnymi w PHP, sprawdź klasę GeoCalc


Hej Glenn Plas, twoja klasa wydaje się mieć niewielkie przesunięcie w lewo lub w prawo, zrobiłem zrzut ekranu na Google Earth, zobaczysz to przesunięcie, pic: link , kod, którego użyłempoint_to_line_segment_distance(41.421649, 2.600410, 41.413851, 2.594356, 41.415710, 2.600638))
Colas

To nie moja klasa, właśnie ją znalazłem po wielu poszukiwaniach ;-) Ale w moich problemach używam precyzji 8 cyfr, wydaje się, że używasz 6. To może być powód, dla którego nigdy nie zauważyłem żadnego przesunięcia. Dzięki za zwrócenie uwagi, sprawdzę to jeszcze raz, gdy będę musiał to wiedzieć.
Glenn Plas,

Być może jesteś rihgt, nie mogę uzyskać więcej decylmas na gEarth, btw na moim ostatnim zdjęciu odcinek miał 1000 metrów długości, przesunięcie wynosiło ~ 110 metrów
Colas

Chodzi o skalę, z której korzystam, nie więcej. Używam go, aby zobaczyć, o której godzinie autobus (transport publiczny) mija najbliższy przystanek. Mam zamiar dwukrotnie to sprawdzić i umieścić na mapie, aby „zobaczyć”, czy dobrze rzutuje na kulę.
Glenn Plas

Och ... Myślałem, że ta funkcja została stworzona do projekcji sferycznych, więc teraz rozumiem przesunięcie
Colas

1

możesz użyć funkcji computeDistanceBetween () z interfejsu API Google Maps .

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

Odległość między dwoma punktami to długość najkrótszej ścieżki między nimi. Ta najkrótsza ścieżka nazywa się geodezyjną. Na kuli wszystkie geodetyki są segmentami wielkiego koła. Aby obliczyć tę odległość, wywołaj metodę computeDistanceBetween (), przekazując jej dwa obiekty LatLng.

Zamiast tego możesz użyć metody computeLength () do obliczenia długości danej ścieżki, jeśli masz kilka lokalizacji

Mam nadzieję, że Ci to pomoże...


najpierw muszę znać punkt (jasnoniebieski), aby obliczyć odległość między
Colas

Moje rozwiązanie poniżej to robi, punkt na segmencie jest nieznany. Mam właściwie podobny problem / rozwiązanie jak wspomniano. Możesz bezpiecznie z nich korzystać na małą skalę.
Glenn Plas,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.