mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-08-31 15:43:25 +00:00
slope and surface data on elevation profile
This commit is contained in:
@@ -349,7 +349,7 @@ export class TrackSegment extends GPXTreeLeaf {
|
||||
computeSlope(): number[] {
|
||||
const points = this.trkpt;
|
||||
|
||||
return distanceWindowSmoothingWithDistanceAccumulator(points, 250, (accumulated, start, end) => accumulated > 1e-3 ? 100 * (points[end].ele - points[start].ele) / accumulated : 0);
|
||||
return distanceWindowSmoothingWithDistanceAccumulator(points, 50, (accumulated, start, end) => 100 * (points[end].ele - points[start].ele) / accumulated);
|
||||
}
|
||||
|
||||
reverse(originalNextTimestamp: Date | undefined, newPreviousTimestamp: Date | undefined): void {
|
||||
@@ -442,6 +442,10 @@ export class TrackPoint {
|
||||
getPower(): number {
|
||||
return this.extensions && this.extensions["gpxpx:PowerExtension"] && this.extensions["gpxpx:PowerExtension"]["gpxpx:PowerInWatts"] ? this.extensions["gpxpx:PowerExtension"]["gpxpx:PowerInWatts"] : undefined;
|
||||
}
|
||||
|
||||
getSurface(): string {
|
||||
return this.extensions && this.extensions["gpxtpx:TrackPointExtension"] && this.extensions["gpxtpx:TrackPointExtension"]["gpxtpx:Extensions"] && this.extensions["gpxtpx:TrackPointExtension"]["gpxtpx:Extensions"].surface ? this.extensions["gpxtpx:TrackPointExtension"]["gpxtpx:Extensions"].surface : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export class Waypoint {
|
||||
|
31
website/src/lib/assets/surfaces.ts
Normal file
31
website/src/lib/assets/surfaces.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export const surfaceColors: { [key: string]: string } = {
|
||||
'missing': '#d1d1d1',
|
||||
'paved': '#8c8c8c',
|
||||
'unpaved': '#6b443a',
|
||||
'asphalt': '#8c8c8c',
|
||||
'concrete': '#8c8c8c',
|
||||
'chipseal': '#8c8c8c',
|
||||
'cobblestone': '#ffd991',
|
||||
'unhewn_cobblestone': '#ffd991',
|
||||
'paving_stones': '#8c8c8c',
|
||||
'stepping_stones': '#c7b2db',
|
||||
'sett': '#ffd991',
|
||||
'metal': '#8c8c8c',
|
||||
'wood': '#6b443a',
|
||||
'compacted': '#ffffa8',
|
||||
'fine_gravel': '#ffffa8',
|
||||
'gravel': '#ffffa8',
|
||||
'pebblestone': '#ffffa8',
|
||||
'rock': '#ffd991',
|
||||
'dirt': '#ffffa8',
|
||||
'ground': '#6b443a',
|
||||
'earth': '#6b443a',
|
||||
'snow': '#bdfffc',
|
||||
'ice': '#bdfffc',
|
||||
'salt': '#b6c0f2',
|
||||
'mud': '#6b443a',
|
||||
'sand': '#ffffc4',
|
||||
'woodchips': '#6b443a',
|
||||
'grass': '#61b55c',
|
||||
'grass_paver': '#61b55c'
|
||||
}
|
@@ -18,6 +18,7 @@
|
||||
Zap
|
||||
} from 'lucide-svelte';
|
||||
import { GPXFiles } from 'gpx';
|
||||
import { surfaceColors } from '$lib/assets/surfaces';
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let chart: Chart;
|
||||
@@ -53,7 +54,8 @@
|
||||
datasets: {
|
||||
line: {
|
||||
pointRadius: 0,
|
||||
tension: 0.4
|
||||
tension: 0.4,
|
||||
borderWidth: 2
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
@@ -139,11 +141,14 @@
|
||||
data: trackPointsAndStatistics.points.map((point, index) => {
|
||||
return {
|
||||
x: trackPointsAndStatistics.statistics.distance[index],
|
||||
y: point.ele ? point.ele : 0
|
||||
y: point.ele ? point.ele : 0,
|
||||
slope: trackPointsAndStatistics.statistics.slope[index],
|
||||
surface: point.getSurface()
|
||||
};
|
||||
}),
|
||||
normalized: true,
|
||||
fill: true
|
||||
fill: true,
|
||||
order: 1
|
||||
};
|
||||
chart.data.datasets[1] = {
|
||||
label: datasets.speed.label,
|
||||
@@ -210,7 +215,62 @@
|
||||
chart.update();
|
||||
}
|
||||
|
||||
$: console.log(elevationFill);
|
||||
let slopeColors = [
|
||||
'#046307',
|
||||
'#028306',
|
||||
'#2AA12E',
|
||||
'#53BF56',
|
||||
'#7BDD7E',
|
||||
'#A4FBA6',
|
||||
'#edf0bd',
|
||||
'#ffcc99',
|
||||
'#F29898',
|
||||
'#E07575',
|
||||
'#CF5352',
|
||||
'#BE312F',
|
||||
'#AD0F0C'
|
||||
];
|
||||
|
||||
function slopeFillCallback(context) {
|
||||
let slope = context.p0.raw.slope;
|
||||
if (slope <= 1 && slope >= -1) return slopeColors[6];
|
||||
else if (slope > 0) {
|
||||
if (slope <= 3) return slopeColors[7];
|
||||
else if (slope <= 5) return slopeColors[8];
|
||||
else if (slope <= 7) return slopeColors[9];
|
||||
else if (slope <= 10) return slopeColors[10];
|
||||
else if (slope <= 15) return slopeColors[11];
|
||||
else return slopeColors[12];
|
||||
} else {
|
||||
if (slope >= -3) return slopeColors[5];
|
||||
else if (slope >= -5) return slopeColors[4];
|
||||
else if (slope >= -7) return slopeColors[3];
|
||||
else if (slope >= -10) return slopeColors[2];
|
||||
else if (slope >= -15) return slopeColors[1];
|
||||
else return slopeColors[0];
|
||||
}
|
||||
}
|
||||
|
||||
function surfaceFillCallback(context) {
|
||||
let surface = context.p0.raw.surface;
|
||||
return surfaceColors[surface] ? surfaceColors[surface] : surfaceColors.missing;
|
||||
}
|
||||
|
||||
$: if (chart) {
|
||||
if (elevationFill === 'slope') {
|
||||
chart.data.datasets[0]['segment'] = {
|
||||
backgroundColor: slopeFillCallback
|
||||
};
|
||||
} else if (elevationFill === 'surface') {
|
||||
chart.data.datasets[0]['segment'] = {
|
||||
backgroundColor: surfaceFillCallback
|
||||
};
|
||||
} else {
|
||||
chart.data.datasets[0]['segment'] = {};
|
||||
}
|
||||
chart.update();
|
||||
}
|
||||
|
||||
$: if (additionalDatasets && chart) {
|
||||
let includeSpeed = additionalDatasets.includes('speed');
|
||||
let includeHeartRate = additionalDatasets.includes('hr');
|
||||
|
@@ -28,7 +28,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card.Root class="h-full overflow-hidden border-none">
|
||||
<Card.Root class="h-full overflow-hidden border-none min-w-60">
|
||||
<Card.Content class="h-full flex flex-col flex-wrap gap-4 justify-center">
|
||||
<Tooltip>
|
||||
<span slot="data" class="flex flex-row items-center">
|
||||
|
Reference in New Issue
Block a user