Ok così mi sono riusciti a risolvere questo problema. Non è esattamente elegante, e sono sicuro che potrebbe essere migliorato, ma ecco il concetto generale che ho trovato:
Creo una matrice di punti di latlng da un file GPX, ma registrano solo i punti ogni 20s o così. Non è abbastanza granularità per i miei scopi in modo da quello che ho fatto è che ho imbottiti la matrice di punti con circa 10 punti (su una linea retta) tra ogni coppia di punti registrati dal GPX:
$.each(array_of_points_to_pad, function(key, pt) {
var current_point = pt;//The current point
var next_point = array_of_points_to_pad[key + 1];//The point immediately after the current point
//Check that we're not on the last point
if (typeof next_point !== 'undefined') {
//Get a 10th of the difference in latitude between current and next points
var lat_incr = (next_point.lat() - current_point.lat())/10;
//Get a 10th of the difference in longitude between current and next points
var lng_incr = (next_point.lng() - current_point.lng())/10;
//Add the current point to a new padded_points array
padded_points.push(current_point);
//Now add 10 additional points at lat_incr & lng_incr intervals between current and next points (in the new padded_points array)
for (var i = 1; i <= 10; i++) {
var new_pt = new google.maps.LatLng(current_point.lat() + (i * lat_incr), current_point.lng() + (i * lng_incr));
padded_points.push(new_pt);
}
}
});
Ora che ho un Array di punti più raffinato, lo uso per tracciare una polilinea. La polilinea imbottita non apparirà diversa da una polilinea disegnata senza il padding, poiché tutti i punti aggiuntivi si trovano su una linea lineare "as-the-crow-mosche" tra i punti esistenti.
var line = new google.maps.Polyline({
path: polyline_path_points_padded,
strokeColor: '#ff0000',
strokeOpacity: 1.0,
strokeWeight: 2
});
line.setMap(map);
Ora aggiungo un indicatore trascinabile all'inizio della riga:
var latLng = new google.maps.LatLng(startlat,startlng);
var marker = new google.maps.Marker({
position: latLng,
map: map,
draggable:true
});
Tutto quello che resta da fare è controllare la resistenza e dragend eventi di questo indicatore:
google.maps.event.addDomListener(marker,'dragend',function(e){
marker.setPosition(find_closest_point_on_path(e.latLng,padded_points));
});
google.maps.event.addDomListener(marker,'drag',function(e){
marker.setPosition(find_closest_point_on_path(e.latLng,padded_points));
});
Qui semplicemente inviamo la latLng del marker a una funzione find_closest_point_on_path() durante il trascinamento e quando il marker viene rilasciato. Inviamo l'array di punti riempito come percorso per la ricerca.
La funzione è simile al seguente:
function find_closest_point_on_path(marker_pt,path_pts){
distances = new Array();
distance_keys = new Array();
$.each(path_pts,function(key, path_pt){
var R = 6371; // km
var dLat = (path_pt.lat()-marker_pt.lat()).toRad();
var dLon = (path_pt.lng()-marker_pt.lng()).toRad();
var lat1 = marker_pt.lat().toRad();
var lat2 = path_pt.lat().toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
//Store the key of the point on the path that matches this distance
distance_keys[d] = key;
});
//Return the latLng pt on the path for the second closest point
return path_pts[distance_keys[_.min(distances)]+1];
}
Cosa questa funzione fa (con l'aiuto di un gradi di funzionare radianti) è che trova la distanza tra la posizione di marcatori e tutti i punti sulla linea. Quindi trova il punto più vicino al marcatore e restituisce le coordinate per il prossimo punto più vicino dopo quello. In questo modo, quando trascini o rilasci il marcatore "scatta" al punto successivo (invece di rimanere bloccato in un punto).
lavoro JS Fiddle In basso:
http://jsfiddle.net/Z5GwW/4/
non sono cross-browser testati. Funzionando nella versione più recente di Chrome.
cercando di affrontare questo problema io stesso su una piattaforma mobile, tutte quelle funzioni trigonometriche sono un po 'spaventose per un'espressione che gira o n ogni drag tic, potrei suggerire di calcolare una semplice [Manhattan distance] (http://en.wikipedia.org/wiki/Taxicab_geometry) che dovrebbe essere sufficientemente accurata su una scala relativa e utilizza solo operazioni aritmetiche di base – jmaculate