Ближайшая точка на линии (сферическая проекция / проекция Меркатора)

9

У меня есть линия (Ax, Ay - Bx, By) над проекцией меркатора (карты Google) и случайная точка (Cx, Cy), ближайшая к этой линии, я бы знал ближайшую точку (прозрачный синий на изображении) над эта линия в точку (синий на изображении)

РЕДАКТИРОВАТЬ: уточнить, что это в проекции Меркатора (сферическая проекция) введите описание изображения здесь

Колас
источник
3
В этом посте есть очень полезное решение, которое может вас заинтересовать stackoverflow.com/questions/3120357/get-closest-point-to-a-line
vinayan
1
Этот светло-синий не выглядит как самый близкий, самый близкий должен создавать угол 90 градусов при соединении с синим, это то, что вы имеете в виду?
Гленн Плас
Я сделал фото вручную, так что да, это возможно
Колас
@vinayan Пост, на который вы ссылаетесь, решает другую проблему нахождения ближайшей точки к линии , тогда как то, что здесь необходимо, похоже, требует ближайшей точки к отрезку линии .
whuber
1
Сегмент должен быть длиной около 20-100 метров, расстояние от сантиметров до 30 метров от сегмента
Colas

Ответы:

2

проверьте эту ссылку , она заставила меня использовать следующую функцию для расчета расстояний до отрезков.

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

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

Если вам нужна хорошая библиотека PHP для вычисления расстояний между координатами в PHP, посмотрите класс GeoCalc

Гленн Плас
источник
Привет, Гленн Плас, у твоего класса, кажется, есть небольшое смещение влево или вправо, я сделал скриншот на Google Earth, ты увидишь это смещение, рис: ссылка , код, который я использовалpoint_to_line_segment_distance(41.421649, 2.600410, 41.413851, 2.594356, 41.415710, 2.600638))
Colas
Это не мой класс, я нашел его после долгих поисков ;-) Но я использую точность 8 цифр в своих задачах, вы, кажется, используете 6. Это может быть причиной, я никогда не замечал здесь никакого смещения. Спасибо за указание на это, я проверю это дважды, как только мне нужно будет знать.
Гленн Плас
Может быть, вы правы, я не могу получить больше децилл на gEarth, кстати, на моем последнем снимке отрезок был длиной 1000 метров, смещение было ~ 110 метров
Colas
Это касается масштаба, на котором я его использую, не более того. Я использую его, чтобы увидеть, в какое время автобус (общественный транспорт) проезжает ближайшую остановку. Я собираюсь перепроверить это и поместить в карту, чтобы увидеть, хорошо ли он проецируется на сферу.
Гленн Плас
Ох ... Я думал, что эта функция была создана для сферических проекций, так что теперь я понимаю смещение
Колас
1

Вы можете использовать функцию computeDistanceBetween () из API карты Google .

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

Расстояние между двумя точками - это длина кратчайшего пути между ними. Этот кратчайший путь называется геодезическим. На сфере все геодезические являются отрезками большого круга. Чтобы вычислить это расстояние, вызовите computeDistanceBetween (), передав ему два объекта LatLng.

Вместо этого вы можете использовать computeLength () для вычисления длины заданного пути, если у вас есть несколько мест

я надеюсь, что это поможет вам ...

Арагон
источник
сначала мне нужно узнать точку (светло-голубую), чтобы вычислить расстояние между
Колас
Мое решение ниже делает это, точка на сегменте неизвестна. У меня на самом деле довольно похожая проблема / решение, как упомянуто. Вы можете безопасно использовать их в небольших масштабах.
Гленн Плас,