Skip to content Skip to sidebar Skip to footer

Snap A Marker To A Specific Road

I'm working on a project where I'm tracking user feedback for a section of construction, but it spans over a pretty long distance. What I'd like to be able to happen is a user clic

Solution 1:

My solution is a few levels of adaption from various sources. I liked the link above that pointed me towards padding the points, but in the end, it just didn't hit the accuracy I was hoping for. Remembering math class from way back when, I know it was possible to find this. In the end, this script cycles through the points in the path, then calculating the closest point between them to where the user clicked.

The inefficiency is that this has to loop through an entire set of points every time. Unfortunately, I just don't know a better way to do it, since a path of multiple points can move in any direction, there's no way to know until the end of the set whether or not you've found the closest point in the paths. The beauty of this is that it'll get the absolute closest point in the path, without snapping to anything.

The first parameter in this is the marker point. This is a single lat/lng pair. The second is the array of lat/lng points in your path. What it returns is the lat/lng on the path that comes closest to your individual point. If you wanted, this can be modified a lot to report more information, but for my purposes, this does exactly what I wanted it to do.

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

    returnnew google.maps.LatLng(theLat, theLng);
}

functionpoint_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];
}

Post a Comment for "Snap A Marker To A Specific Road"