const selColor = "#FF5C26"; let d = [{ label:"Altitude,m", data:[], yaxis: 2 }, { label:"Speed,km/h", data:[] }]; let options = { xaxis: { mode: "time", tickLength: 5, zoomRange: [60 * 1000, 1000 * 3600 * 24 * 365] }, /*selection: { mode: "x", color: selColor },*/ yaxes: [{ min: 0, zoomRange: false, panRange: false }, { position: "right", alignTicksWithAxis: 1, min: 0, zoomRange: false, panRange: false }], zoom: { interactive: true }, pan: { interactive: true, cursor: "move", frameRate: 60 } }; let optO = { legend : { show: false }, series: { lines: { show: true, lineWidth: 1 }, shadowSize: 0 }, xaxis: { //ticks: [], mode: "time" }, yaxis: { ticks: [], autoscaleMargin: 0.1 }, selection: { mode: "x", color: selColor, minSize: 0 } }; let gps = new GPS(); let plot, overview; window.onload = function() { fetch("secrets") .then(response => response.json()) .then(secrets => { Cesium.Ion.defaultAccessToken = secrets.cesium_token var extent = {west: -0.2540382220862719, south: 0.6872565916005104, east: 0.6129855406042352, north: 0.9377043806513488}; Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent; Cesium.Camera.DEFAULT_VIEW_FACTOR = 0; bingMapsProvider = new Cesium.BingMapsImageryProvider({ url: 'https://dev.virtualearth.net', key: secrets.bing_maps_key, mapStyle: Cesium.BingMapsStyle.AERIAL_WITH_LABELS }); viewer = new Cesium.Viewer('map', { fullscreenElement: "map", terrainProvider : Cesium.createWorldTerrain({ requestVertexNormals: true, requestWaterMask: true }), //shadows: true }); viewer.scene.globe.enableLighting = true; viewer.resolutionScale = 1.2; viewer.scene.screenSpaceCameraController.enableTilt = !('ontouchstart' in window); viewer.baseLayerPicker.viewModel.selectedImagery = new Cesium.ProviderViewModel({ name: 'Bing Maps Aerial with Labels', iconUrl: Cesium.buildModuleUrl('Widgets/Images/ImageryProviders/bingAerialLabels.png'), tooltip: 'Bing Maps aerial imagery with labels', creationFunction: function () { return bingMapsProvider } }); var paths = []; fetch("trips") .then(response => response.json()) .then(jsonResponse => { gps.parse(jsonResponse); for(const t of gps.trips) { var desc = `Region: ${t.name}
` + `Start: ${timeFormat(t.startTime, "datetime")}
` + `Finish: ${timeFormat(t.endTime, "datetime")}
` + `Track time (full): ${timeFormat(t.totalTime)}
` + `Track time (mov.): ${timeFormat(t.movementTime)}
` + `Alt: ↑${t.ascendHeight.toFixed(1)}m ↓${t.descendHeight.toFixed(1)}m
` + `Distance: ${(t.distance/1000).toFixed(1)}km
` + `top speed: ${t.topSpeed.toFixed(1)}km/h
` + `average speed: ${t.avgSpeed.toFixed(1)}km/h`; const col = Cesium.Color.fromCssColorString(t.color) var path = viewer.entities.add({ name : `Track ${t.id}`, id: `track_${t.id}`, description: desc, polyline : { positions : t.path.map(p => Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.alt)), width : 5, material : new Cesium.PolylineOutlineMaterialProperty({ color : col, }), //clampToGround: true, depthFailMaterial: new Cesium.PolylineOutlineMaterialProperty({ color : Cesium.Color.fromAlpha(col, 0.6), }), shadows: Cesium.ShadowMode.ENABLED } }); paths.push(path); } var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.setInputAction(function (movement) { var pick = viewer.scene.pick(movement.position); if (Cesium.defined(pick) && (pick.id._id.match(/track_([0-9]+)/))) { var id = parseInt(RegExp.$1); var path = paths[id]; show(id); } }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); viewer.flyTo(paths[paths.length - 1], { offset: new Cesium.HeadingPitchRange(0, -90, 0)}); let regionIndex = 0; for(let r=0; r` + `Time (mov.): ${timeFormat(i.movementTime)}
` + `Alt: ↑${(i.ascendHeight).toFixed(1)}m ↓${(i.descendHeight).toFixed(1)}m
` + `Distance: ${(i.distance/1000).toFixed(1)}km
` + `Top speed: ${i.topSpeed.toFixed(1)}km/h
` + `Avg. speed: ${i.avgSpeed.toFixed(1)}km/h
` + `Data points: ${i.points}
` + `Graph`; $(".status").append(html); }); }); plot = $.plot("#placeholder", d, options); overview = $.plot("#overview", d, optO); // now connect the two $("#placeholder").bind("plotpan", updateOverview); $("#placeholder").bind("plotzoom", updateOverview); function updateOverview(event, ranges) { var axes = plot.getAxes(); for(var axis in axes) { axes[axis].from = axes[axis].min; axes[axis].to = axes[axis].max; } overview.setSelection(axes, true); } $("#overview").bind("plotselected", function (event, ranges) { $.each(plot.getXAxes(), function(_, axis) { var opts = axis.options; opts.min = ranges.xaxis.from; opts.max = ranges.xaxis.to; }); plot.setupGrid(); plot.draw(); }); $("#whole").click(function () { setZoom(false,false); }); $("#right").click(function () { var min = plot.getXAxes()[0].options.min; var max = plot.getXAxes()[0].options.max; if(min != null && max != null) setZoom((min+max)/2, max * 1.5 - min/2); }); $("#left").click(function () { var min = plot.getXAxes()[0].options.min; var max = plot.getXAxes()[0].options.max; if(min != null && max != null) setZoom(min * 1.5 - max/2, (min+max)/2); }); } let firstShow = true; function show(id) { if(firstShow) { firstShow = false; d[0].data = smoothOut(gps.data.map(v => v.alt), 0.85); d[1].data = smoothOut(gps.data.map(v => v.speed), 0.85); for(let i=0; i 60 && cur.speed < 0.5) || cur.speed === null) { d[0].data[i] = null; d[1].data[i] = null; } d[0].data[i] = [cur.timestamp*1000, d[0].data[i]]; d[1].data[i] = [cur.timestamp*1000, d[1].data[i]]; } let opts = plot.getXAxes()[0].options; opts.panRange = [ gps.data[0].timestamp*1000, gps.data[gps.data.length-1].timestamp*1000 ]; plot.setData(d); plot.setupGrid(); //only necessary if your new data will change the axes or grid plot.draw(); overview.setData(d); overview.setupGrid(); //only necessary if your new data will change the axes or grid overview.draw(); for(let t of gps.trips) { $("#tracks").append(`
  • `); } } $("#shadow").css("visibility", "visible"); $("#frame").css("visibility", "visible"); console.log(id); let start = gps.trips[id].startTime*1000; let end = gps.trips[id].endTime*1000; setZoom(start,end); $("#track").click(function () { setZoom(start,end); }); }; function hide() { $(".popup").css("visibility", "hidden"); }; function setZoom(Xmin, Xmax) { var opts = plot.getXAxes()[0].options; if(Xmax==false) { Xmax = +new Date() - 60 * new Date().getTimezoneOffset() * 1000; } if(Xmin==false) { Xmin = d[0].data[0][0]; overview.clearSelection(); } else { overview.setSelection({ xaxis: { from: Xmin, to: Xmax}}); } opts.min=Xmin; opts.max=Xmax; plot.setupGrid(); plot.draw(); plot.clearSelection(); return false; } function addInfo(bingMapsProvider, viewer, id, data) { $('.sidebar').append(`
    ` + timeFormat(data.timestamp, "short") + "
    " + data.name + "
    " + (data.distance/1000).toFixed(1) + " km
    "); $('#info_'+id).click(function() { viewer.camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(data.lng, data.lat, data.distance), offset: new Cesium.HeadingPitchRange(0, -90, 0) }); }); }