Punto más cercano en una línea (proyección esférica / de Mercator)

9

Tengo una línea (Ax, Ay - Bx, By) sobre una proyección de mercator (google maps) y un punto aleatorio (Cx, Cy) más cercano a esa línea, me gustaría saber el punto más cercano (azul transparente en la imagen) sobre esa línea para señalar (azul en la imagen)

EDITAR: para aclarar que esto está en una proyección de Mercator (proyección esférica) ingrese la descripción de la imagen aquí

Colas
fuente
3
esta publicación tiene una solución muy útil que puede interesarle stackoverflow.com/questions/3120357/get-closest-point-to-a-line
vinayan
1
Ese azul claro no se parece al más cercano, el más cercano debería crear un ángulo de 90 grados cuando se conecta al azul oscuro, ¿es eso lo que quieres decir?
Glenn Plas
Hice la foto a mano, así que sí, es posible
Colas
@vinayan La publicación a la que hace referencia resuelve un problema diferente de encontrar el punto más cercano a una línea , mientras que lo que se necesita aquí parece querer el punto más cercano a un segmento de línea .
whuber
1
El segmento debe tener alrededor de 20-100 metros de largo, el punto de centímetros a 30 metros tanto del segmento
Colas

Respuestas:

2

mira este enlace , me hizo usar la siguiente función para calcular distancias a segmentos de línea.

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

Luego puede usar las funciones de proyección para calcular distancias, estoy usando la fórmula anterior para calcular el tiempo en ese punto dada una velocidad promedio y funciona realmente bien.

Si desea una buena biblioteca PHP para calcular distancias entre coordenadas en PHP, consulte la clase GeoCalc

Glenn Plas
fuente
Hola Glenn Plas, tu clase parece tener un pequeño desplazamiento hacia la izquierda o hacia la derecha, hice una captura de pantalla en Google Earth, verás ese desplazamiento, la foto: enlace , el código que usépoint_to_line_segment_distance(41.421649, 2.600410, 41.413851, 2.594356, 41.415710, 2.600638))
Colas
No es mi clase, solo la encontré después de buscar mucho ;-) Pero uso precisión de 8 dígitos en mis problemas, parece que usas 6. Esa podría ser la razón, nunca noté ningún desplazamiento aquí. Gracias por señalarlo, volveré a verificar esto tan pronto como sea necesario.
Glenn Plas
Tal vez estás en lo cierto, no puedo obtener más decilmas en gEarth, por cierto, en mi última foto el segmento tenía 1000 metros de largo, el desplazamiento era de ~ 110 metros
Colas
Eso es sobre la escala en la que lo uso, no más que eso. Lo uso para ver a qué hora un autobús (transporte público) pasa la parada más cercana. Sin embargo, voy a verificarlo dos veces y ponerlo en un mapa para 'ver' si se proyecta bien en una esfera.
Glenn Plas
Oh ... pensé que esa función estaba hecha para proyecciones esféricas, así que ahora entiendo el desplazamiento
Colas
1

puede usar la función computeDistanceBetween () de la API de Google Map .

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

La distancia entre dos puntos es la longitud del camino más corto entre ellos. Este camino más corto se llama geodésico. En una esfera, todas las geodésicas son segmentos de un gran círculo. Para calcular esta distancia, llame a computeDistanceBetween (), pasándole dos objetos LatLng.

En su lugar, puede usar computeLength () para calcular la longitud de una ruta dada si tiene varias ubicaciones

Espero que te ayude...

Aragón
fuente
primero necesito saber el punto (azul claro) para calcular la distancia entre
Colas
Mi solución a continuación hace eso, el punto en el segmento es desconocido. De hecho, tengo un problema / solución bastante similar al mencionado. Puede usarlos de manera segura a pequeña escala.
Glenn Plas