After exploring various sources, I developed a unique solution by combining different ideas. While the suggestion to pad the points was helpful, it didn't quite achieve the level of accuracy I desired. Drawing upon my distant math class memories, I recalled a method that could potentially solve this problem. In the end, I created a script that iterates through the path's points and calculates the closest point based on user input.
The drawback of this approach is its inefficiency as it requires looping through all points each time. Unfortunately, due to the unpredictable nature of paths with multiple points moving in any direction, determining the closest point remains challenging until the full set is processed. Nonetheless, the advantage lies in pinpointing the absolute closest point without snapping to any specific location.
The function takes two parameters: the marker point (a single lat/lng pair) and an array of lat/lng points representing your path. It returns the lat/lng coordinates on the path closest to the specified marker point. While this function can be customized for additional information retrieval, it perfectly serves my current needs.
function find_closest_point_on_path(marker_pt,path_pts){
var lowest = 9999999999999999;
var theLat = 0;
var theLng = 0;
$.each(path_pts,function(key, path_pt){
if(typeof path_pts[key+1] != "undefined"){
var test = point_to_line_segment_distance(path_pt.lat(),path_pt.lng(), path_pts[key+1].lat(),path_pts[key+1].lng(), marker_pt.lat(),marker_pt.lng());
if(test[0] < lowest){
lowest = test[0];
theLat = test[1];
theLng = test[2];
}
}
});
return new google.maps.LatLng(theLat, theLng);
}
function 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 = Math.abs(s) * Math.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 = Math.sqrt(dist1);
}
else {
closest_point_on_segment_X = endX;
closest_point_on_segment_Y = endY;
distanceSegment = Math.sqrt(dist2);
}
}
return [distanceSegment, closest_point_on_segment_X, closest_point_on_segment_Y];
}