Subversion Repositories SmartDukaan

Rev

Rev 37028 | Rev 37034 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37028 Rev 37032
Line 1269... Line 1269...
1269
// pings. SUGGESTED route = the Google-optimal road route through the journey's
1269
// pings. SUGGESTED route = the Google-optimal road route through the journey's
1270
// checkpoints (green dotted). Both are drawn and compared by distance.
1270
// checkpoints (green dotted). Both are drawn and compared by distance.
1271
function bjDrawRoutes(map, cps, pathPts, takenTime, timedPts){
1271
function bjDrawRoutes(map, cps, pathPts, takenTime, timedPts){
1272
  var legend=bjRouteLegend();
1272
  var legend=bjRouteLegend();
1273
 
1273
 
-
 
1274
  // De-jitter the breadcrumb first: stationary GPS drift (e.g. under a roof)
-
 
1275
  // scatters points around a fixed spot, which makes the road-snapped route weave
-
 
1276
  // back and forth and inflates the taken distance. Collapsing sub-JITTER_MIN_M
-
 
1277
  // hops removes those clusters before we draw or measure the trail.
-
 
1278
  var trail=bjCleanTrail(pathPts, 30);
-
 
1279
 
1274
  // taken — road route traced through the recorded breadcrumb (in order)
1280
  // taken — road route traced through the recorded breadcrumb (in order)
1275
  if(pathPts && pathPts.length>=2){
1281
  if(trail && trail.length>=2){
1276
    var ds1=new google.maps.DirectionsService();
1282
    var ds1=new google.maps.DirectionsService();
1277
    var sample=bjSample(pathPts, 25);                          // Directions cap: 25 incl. ends
1283
    var sample=bjSample(trail, 25);                           // Directions cap: 25 incl. ends
1278
    var o=sample[0], d=sample[sample.length-1];
1284
    var o=sample[0], d=sample[sample.length-1];
1279
    var vias=sample.slice(1,-1).map(function(p){ return {location:new google.maps.LatLng(p.lat,p.lng), stopover:false}; });
1285
    var vias=sample.slice(1,-1).map(function(p){ return {location:new google.maps.LatLng(p.lat,p.lng), stopover:false}; });
1280
    bjRouteRequest(ds1, o, d, vias, false, function(res){
1286
    bjRouteRequest(ds1, o, d, vias, false, function(res){
1281
      bjRenderRoute(map, res, {color:'#e03131', dashed:false, z:55, label:'Route taken (actual GPS)', time:takenTime, timed:timedPts});
1287
      bjRenderRoute(map, res, {color:'#e03131', dashed:false, z:55, label:'Route taken (actual GPS)', time:takenTime, timed:timedPts});
1282
      legend.set('taken', bjRouteKm(res));
1288
      legend.set('taken', bjRouteKm(res));
1283
    }, function(status){
1289
    }, function(status){
1284
      console.warn('Directions (taken) failed:', status);
1290
      console.warn('Directions (taken) failed:', status);
1285
      // fallback: plot the raw breadcrumb (straight hops), with arrows, and measure along it
1291
      // fallback: plot the cleaned breadcrumb (straight hops), with arrows, and measure along it
1286
      var poly=new google.maps.Polyline({path:pathPts,geodesic:false,strokeColor:'#e03131',strokeOpacity:.9,strokeWeight:4,zIndex:55,map:map,
1292
      var poly=new google.maps.Polyline({path:trail,geodesic:false,strokeColor:'#e03131',strokeOpacity:.9,strokeWeight:4,zIndex:55,map:map,
1287
        icons:[{icon:{path:google.maps.SymbolPath.FORWARD_CLOSED_ARROW,strokeColor:'#e03131',fillColor:'#e03131',fillOpacity:1,scale:3},offset:'3%',repeat:'120px'}]});
1293
        icons:[{icon:{path:google.maps.SymbolPath.FORWARD_CLOSED_ARROW,strokeColor:'#e03131',fillColor:'#e03131',fillOpacity:1,scale:3},offset:'3%',repeat:'120px'}]});
1288
      var km=google.maps.geometry.spherical.computeLength(pathPts.map(function(p){ return new google.maps.LatLng(p.lat,p.lng); }))/1000;
1294
      var km=google.maps.geometry.spherical.computeLength(trail.map(function(p){ return new google.maps.LatLng(p.lat,p.lng); }))/1000;
1289
      bjRouteClick(map, poly, '#e03131', 'Route taken (actual GPS)', km, '', takenTime, timedPts);
1295
      bjRouteClick(map, poly, '#e03131', 'Route taken (actual GPS)', km, '', takenTime, timedPts);
1290
      legend.set('taken', km);
1296
      legend.set('taken', km);
1291
    });
1297
    });
1292
  } else {
1298
  } else {
1293
    legend.set('taken', false);
1299
    legend.set('taken', false);
Line 1306... Line 1312...
1306
    if(capped) legend.note('Suggested route limited to first 23 stops');
1312
    if(capped) legend.note('Suggested route limited to first 23 stops');
1307
  } else {
1313
  } else {
1308
    legend.set('suggested', false);
1314
    legend.set('suggested', false);
1309
  }
1315
  }
1310
}
1316
}
-
 
1317
// Collapse stationary GPS jitter: keep the first point, then only points that
-
 
1318
// moved at least `minM` metres from the last kept one; the true final point is
-
 
1319
// always kept so the trail ends at the last known location. This removes the
-
 
1320
// dense drift clusters (weak signal indoors) that otherwise draw back-and-forth
-
 
1321
// loops and inflate the taken distance, while preserving real movement.
-
 
1322
function bjCleanTrail(pts, minM){
-
 
1323
  if(!pts || pts.length<2) return pts ? pts.slice() : [];
-
 
1324
  var out=[pts[0]], last=pts[0];
-
 
1325
  for(var i=1;i<pts.length-1;i++){
-
 
1326
    var p=pts[i];
-
 
1327
    var d=google.maps.geometry.spherical.computeDistanceBetween(
-
 
1328
      new google.maps.LatLng(last.lat,last.lng), new google.maps.LatLng(p.lat,p.lng));
-
 
1329
    if(d>=minM){ out.push(p); last=p; }
-
 
1330
  }
-
 
1331
  out.push(pts[pts.length-1]);   // keep the final fix regardless
-
 
1332
  return out;
-
 
1333
}
1311
// Evenly downsample a list to at most `max` items, always keeping first and last.
1334
// Evenly downsample a list to at most `max` items, always keeping first and last.
1312
function bjSample(arr, max){
1335
function bjSample(arr, max){
1313
  if(arr.length<=max) return arr.slice();
1336
  if(arr.length<=max) return arr.slice();
1314
  var out=[], step=(arr.length-1)/(max-1);
1337
  var out=[], step=(arr.length-1)/(max-1);
1315
  for(var i=0;i<max;i++) out.push(arr[Math.round(i*step)]);
1338
  for(var i=0;i<max;i++) out.push(arr[Math.round(i*step)]);