1

I have a pre defined path (polyline).

_path = new google.maps.Polyline({
    path: path,
    editable: false,
    map: map,
    strokeColor: '#ff0000',
    strokeWeight: 3,
    strokeOpacity: 70 / 100,
    geodesic: true
});

Also I have some realtime locations (I receive them via Ajax requests).

// FOREACH new location:
function addMarker(e_location) {
var on_path = google.maps.geometry.poly.isLocationOnEdge(e_location, _path, 0.0007);
var color = (on_path === true) ? '#12cc32' : '#ff1213';


var marker = new google.maps.Marker({
    position: e_location,
    map: map,
    draggable: false,
    animation: google.maps.Animation.DROP,
    icon: {
        path: google.maps.SymbolPath.CIRCLE,
        scale: 3,
        strokeColor: color
    }
});
marker.info = 'some info...';
}

Until now I can check whether the new location resides on the track or not, But I can not determine How long does this location elapse from the beginning of the path.

Let me say I need to know the percentage of distance the new location had make from the path.

enter image description here

green circles refer to points on the path which I want to know the percentage of each one.

Thanks.

Wajih
  • 4,227
  • 2
  • 25
  • 40

4 Answers4

1

here is maybe one solution you can find with google: Find a point in a polyline which is closest to a latlng

Im really not the best in js and also not in solving math. problems, but here a simple solution I use for edit polylines (click on polyline and get back the nearest point). Based on that you can calculate also the meter like described above.

However if you can provide a full working example with path and a marker as car, then maybe someone can change it to the exact needs you have.

HTH, Reinhard

function getNearestVertex(poly, pLatLng) {
// test to get nearest point on poly to the pLatLng point
// marker is on poly, so the nearest vertex is the smallest diff between
    var g = google.maps;    
    var minDist = 9999999999;
var minDiff = 9999999999;
var path = poly.getPath();
var count = path.length || 0;

for (var n = 0; n < count - 1; n++) {
    if (n == 0) {
        point = path.getAt(n);
        dist = g.geometry.spherical.computeDistanceBetween(pLatLng, point);
    }
    var pointb = path.getAt(n + 1);
    distb =  g.geometry.spherical.computeDistanceBetween(pLatLng, pointb);
    distp2p = g.geometry.spherical.computeDistanceBetween(point, pointb);
    var pdiff = dist + distb - distp2p;

    //alert(n + " / " +dist +" + " +distb +" - " +distp2p +" = " +pdiff);
    if (pdiff < minDiff) {
        minDiff = pdiff.toFixed(3);
        index = n;
    }
    point = pointb;
    dist = distb;
} //-> end for
//alert(index +":" + minDiff);
return index +":" + minDiff;

} //-> end of getNearestVertex

Community
  • 1
  • 1
ReFran
  • 897
  • 8
  • 14
  • Thanks for this, I benefit from it. It provide a solution for my problem, I will vote for your answer But can't accept it now because it is a heavy solution, I will accept it if no better solution provide. thanks again – Wajih Apr 06 '16 at 17:48
  • 1
    No problem. If you set up the path you should store the accumulated meters calculated point by point as attribute with the poly (like: _path.meterArray) so the index tell you the meter you drove already and have to drive also. The above for loop calculate all points diff. But based on your awaited path and car movement you can shorten the loop or put a conditional break in it. And finally, just for fun: http://econym.org.uk/gmap/example_cartrip2.htm Good luck, Reinhard – ReFran Apr 07 '16 at 16:19
1

Here you have an efficient approach to your problem. This code will give you a 0.1% precision over the total length of the path.

Have a look at the "timeline" in your inspector. If you feel your application is slow (it shouldn't be) you may want to decrease the 'path_increment' variable. If you want more precision, just increase it.

'path_increment = totaldist/1000' means I am dividing your path into 1000 pieces and looking for the closest one to your marker.

Working example: http://jsfiddle.net/fcoramos/tjm0kpby/1/

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="https://maps.googleapis.com/maps/api/js" ></script>
<script>
var map,
    myCenter = new google.maps.LatLng(-32.7,-70.7)


function initialize() {
  var mapProp = {
    center:myCenter,
    zoom:9,
    mapTypeId:google.maps.MapTypeId.HYBRID,
    scaleControl:true };

  map=new google.maps.Map(document.getElementById('map'),mapProp);


  var _path = new google.maps.Polyline({            //Here goes your _path
           path: [{lat: -33.0, lng: -71.0},
                  {lat: -32.9, lng: -71.0},
                  {lat: -32.8, lng: -70.9},
                  {lat: -32.7, lng: -70.85},
                  {lat: -32.6, lng: -70.7},
                  {lat: -32.5, lng: -70.5}],
           strokeColor: 'orange',
           strokeWeight: 2,  
           map: map
           });

map.addListener('click', addmarker);

function addmarker(event) {
         var marker = new google.maps.Marker({
            position:  event.latLng,
            map: map,
            draggable: false,
            icon: {
                path: google.maps.SymbolPath.CIRCLE,
                scale: 3,
                strokeColor: 'red'
            }});

         var xmarker = marker.getPosition().lng();
         var ymarker = marker.getPosition().lat();

         var vertex = _path.getPath();

         var totaldist = 0; // In pseudodegrees

         // We calculate the total length of path in order to yield a relevant precision.
         for (var i = 1; i < vertex.length; i++) {  
                    x1 = vertex.getAt(i-1).lng();
                    y1 = vertex.getAt(i-1).lat();

                    x2 = vertex.getAt(i).lng();
                    y2 = vertex.getAt(i).lat();

                    totaldist = totaldist + Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
                    }

          var path_increment = totaldist / 1000;    // This means precision on 0.1% of total path legth. Adjust accordingly. 
          var dist_to_marker = 1000;
          var closest_x;
          var closest_y;
          var closest_percentage;
          var partialdist = 0;

          for (var i = 1; i < vertex.length; i++) {
               x1 = vertex.getAt(i-1).lng();
               y1 = vertex.getAt(i-1).lat();

               x2 = vertex.getAt(i).lng();
               y2 = vertex.getAt(i).lat();

              var intervertex_dist = Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2)) ;
              partialdist = partialdist + intervertex_dist;

              var j=0; 
              var accumulated_dist = 0;
              var azimut = Math.atan2((x2-x1),(y2-y1));

              while ( accumulated_dist < intervertex_dist )
                    { 
                      j++;

                      var delta_newx = path_increment * Math.sin(azimut);
                      var delta_newy = path_increment * Math.cos(azimut);

                      var newx = x1 + (delta_newx*j);
                      var newy = y1 + (delta_newy*j);

                      var new_dist_to_marker = Math.sqrt(Math.pow(xmarker-newx,2)+Math.pow(ymarker-newy,2));


                      if (new_dist_to_marker < dist_to_marker) {
                           closest_percentage = ((partialdist - intervertex_dist + ( path_increment * j)) / totaldist ) * 100; 
                           closest_x = newx;
                           closest_y = newy;
                           dist_to_marker = new_dist_to_marker;
                           }
                      accumulated_dist = accumulated_dist + path_increment;
                    }
              }

        var marker = new google.maps.Marker({
            position:  {lat: closest_y, lng: closest_x},
            map: map });

        var infowindow = new google.maps.InfoWindow({ content:Math.round(closest_percentage)+'%'  }); 
        infowindow.open(map,marker);
   }
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map" style="width:500px;height:500px;"></div>
</body>
</html>
Fco
  • 197
  • 1
  • 6
0

Interesting project we have here. Try this.

  1. Determine the original "polyline total length". How this is done has been answered in this thread. You can then assign this to a variable like "original_length".
  2. Since you're using real-time, you have to update the "polyline total length" everytime too. Make another variable like "realtime_length" that receives the updated length.
  3. To determine the percentage of distance elapsed from starting point:

function realtimeUpdate(){

var product = (realtime_length/orginal_length) * 100;
var distance_elapsed_percent = 100 - product;
}
  1. Now, to make sure that an object (car) is within bounds of the "correct path" (to avoid unwanted outcomes), you'll need to learn how to use containsLocation(). Your app logic should make sure that distance elapsed will only be valid if it is within bounds of correct path/contained location.
if( carA && carB is inside polygon){
     calculateDistanceElapsed();
}else{
   print("Car is not on track");
}

Hope the pseudo code helps :)

Community
  • 1
  • 1
ReyAnthonyRenacia
  • 17,219
  • 5
  • 37
  • 56
  • Thanks for this reply, But actually it is not what I want. I computed the length of path, But the problem is that: when a new location received I want to know how long does it elapse from the beginning of the path. I think if I know where the new location resides on path I will solve it. – Wajih Apr 05 '16 at 09:45
  • 1
    the way I understood this was like a car racing game where you were trying to get from point A to point B and you wanted to know how far you were from point A as you moved towards point B, hence my answer above.. – ReyAnthonyRenacia Apr 05 '16 at 13:06
  • You are right about the aim, But consider this: car1 runs in straight way, car2 runs like zigzag way. Then car2 will considered in the front because its path more long than car1. So I need a way that let me know where exactly each car located on the main path. is it clear ? – Wajih Apr 05 '16 at 14:40
  • ok take your time, It is more difficult than you think, best regards ;-) – Wajih Apr 06 '16 at 05:35
  • did you try the containsLocation() sample yet? – ReyAnthonyRenacia Apr 06 '16 at 06:53
  • of course, But it is used to check if a polygon containing the point. For polyline I did not find any thing except `isLocationOnEdge` function. – Wajih Apr 06 '16 at 07:09
  • You told me you dont want the zigzagging car to cheat its way to victory. So make your "main path" to be a polygon, like a long rectangular stretch of a polygon. The cars are the points. Using containsLocation(), cant you do something like: if( carA && carB is inside polygon){ calculateDistanceElapsed(); }else{ print("Car is not on track"); } Anyway, I'll be experimenting my own code with this If I have enough time.. – ReyAnthonyRenacia Apr 06 '16 at 10:47
  • No, you can't do that, `containsLocation` return `True` if the point is inside the over all area of polygon, I am using `isLocationOnEdge` with a specific tolerance to check whether the car on the path or not, But what I really want is a function to know the exact position of car on the path. Thanks for your help. – Wajih Apr 06 '16 at 11:17
  • " But what I really want is a function to know the exact position of car on the path" -use Geolocation then. Longitude & Latititude tells the exact position of an object in Google Maps – ReyAnthonyRenacia Apr 06 '16 at 13:13
  • I said exact location on the path. The location must be on the path – Wajih Apr 06 '16 at 13:21
  • but the path is in Google Maps aint it? lol Anyway, do you have a screenshot of the so called path? I think I have enough time to try this now – ReyAnthonyRenacia Apr 06 '16 at 13:23
  • Dude show as an illustration instead of what you're trying to achieve. Show as a drawing or something.. – ReyAnthonyRenacia Apr 06 '16 at 13:37
0

"...a function to know the exact position of car on the path."

Mmmh, I think you have to calculate / get the nearest path vertex (point) to the car location point. Then you can add up the path km point by point and finally the km of the car point to the nearest vertex.

Would that be an option? Reinhard

PS: You may have a look at this example: http://wtp2.appspot.com/cSnapToRouteDemo.html Calculation for the nearest vertex can also found here, if you really need it. There are much variations and solutions.

ReFran
  • 897
  • 8
  • 14
  • How to know the nearest path vertex to the car location? *this is the core problem*. What do you mean by km? – Wajih Apr 06 '16 at 12:03
  • I know km but I could not recognize what you mean in your answer. Any way the example you provided is helpful I think it contains the solution. – Wajih Apr 06 '16 at 15:40
  • "... the nearest path vertex to the car location .." you will get by calculating the distance in meter (or km = kilometer) from your car location to every path vertex (point). The shortest distance give you the nearest point. Then you have to add up ..(the path km point by point and finally the km of the car point to the nearest vertex) and if your car has no reverse gear and your path no crossing that calculation is relative simple and can be found here, if you don't can set it up by yourself. – ReFran Apr 06 '16 at 15:48
  • Please excuse, the first comment was broken! – ReFran Apr 06 '16 at 15:48