9

I have a line (Ax,Ay - Bx,By) over a mercator projection (google maps) and a random point (Cx,Cy) nearest to that line, i would to know the closest point (transparent blue on the image) over that line to point (blue in the image)

EDIT: to clarify that this is in a Mercator projection (spherical projection) enter image description here

8
  • 3
    this post has very useful solution that may interest you stackoverflow.com/questions/3120357/get-closest-point-to-a-line
    – vinayan
    Dec 28, 2012 at 14:38
  • 1
    That light blue doesn't look like the closest, the closest should create a 90 degrees angle when connected to the dark blue, is that what you mean ?
    – Glenn Plas
    Dec 28, 2012 at 15:29
  • I made the pic by hand so yeah, it's posible
    – Colas
    Dec 28, 2012 at 16:03
  • @vinayan The post you reference solves a different problem of finding the nearest point to a line, whereas what is needed here appears to want the nearest point to a line segment.
    – whuber
    Dec 28, 2012 at 16:10
  • 1
    The segment should be around 20-100 meters long , the point from centimeters to 30 meters as much from the segment
    – Colas
    Dec 28, 2012 at 16:56

2 Answers 2

2

check out this link , it made me use the following function to calculate distances to line segments.

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

You can then use projection functions to calculate distances, I'm using the above formula to calculate the time at that point given a average speed and it works really well.

If you want a good PHP library to calculate distances between coordinates in PHP, check out GeoCalc class

8
  • Hey Glenn Plas, your class seem to have a little offset to the left or right,i made a screenshot on Google earth you will see that offset, the pic:link, the code i used point_to_line_segment_distance(41.421649, 2.600410, 41.413851, 2.594356, 41.415710, 2.600638))
    – Colas
    Dec 28, 2012 at 16:44
  • It's not my class, just found it after searching a lot ;-) But I use 8 digits precision in my problems, you seem to use 6. That could be the reason, I never noticed any offset here. Thanks for pointing it out, I will doublecheck this soon as I need to know.
    – Glenn Plas
    Dec 28, 2012 at 16:55
  • Maybe you are rihgt, i can't obtain more decilmas on gEarth, btw in my last pic the segment was 1000 meters long, the offset was ~110meters
    – Colas
    Dec 28, 2012 at 17:06
  • That's about the scale I use it on, no more than that. I use it to see at what time a bus (public transport) passes a stop the closest. I am going to doublecheck it though and put it in a map to 'see' if it projects well on a sphere.
    – Glenn Plas
    Dec 28, 2012 at 17:18
  • Oh... I thought that function was made for spherical projections, so now i understand the offset
    – Colas
    Dec 28, 2012 at 17:26
1

you can use computeDistanceBetween() function from google map api.

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

The distance between two points is the length of the shortest path between them. This shortest path is called a geodesic. On a sphere all geodesics are segments of a great circle. To compute this distance, call computeDistanceBetween(), passing it two LatLng objects.

You may instead use computeLength() to calculate the length of a given path if you have several locations

i hope it helps you...

2
  • first I need to know the point (light blue) to compute the distance between
    – Colas
    Dec 28, 2012 at 16:12
  • My solution below does that, the point on the segment is unknown. I actually have a rather similar problem/solution as mentioned. You can safely use these on small scale's.
    – Glenn Plas
    Dec 28, 2012 at 16:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.