Route grade: compute over a ~30m distance window, not adjacent points
DEM elevations quantise to 30m cells; dense points inside a cell share one value and the whole rise lands on the single boundary segment -> a false steep spike in slope colouring. Compute each segment's grade as a central difference over a >=30m window (config gradeWindowM) so a cell step spreads across the cell and the colour reflects the real grade. maxGrade uses the windowed value too.
This commit is contained in:
parent
27c60a460a
commit
80ddff9b72
1 changed files with 20 additions and 4 deletions
|
|
@ -2453,14 +2453,30 @@ GPS.routeElevStats = function(points) {
|
|||
for (let i = 1; i < n; i++) {
|
||||
cumKm[i] = cumKm[i-1] + GPS.distance(points[i-1].lat, points[i-1].lon, points[i].lat, points[i].lon) / 1000;
|
||||
}
|
||||
// Grade over a DISTANCE window (~one DEM cell), not between adjacent points. DEM
|
||||
// elevations are quantised to 30m cells: dense points inside a cell share one value
|
||||
// and the whole rise lands on the single boundary segment → a false steep spike.
|
||||
// A windowed central difference spreads that step across the cell so the colour
|
||||
// reflects the real grade. Window W metres (config gradeWindowM, default 30).
|
||||
const W = GPS.config.gradeWindowM ?? 30;
|
||||
const cumM = cumKm.map(k => k * 1000);
|
||||
const grades = new Array(n).fill(0);
|
||||
let maxGrade = 0;
|
||||
for (let i = 0; i < n - 1; i++) {
|
||||
const dm = GPS.distance(points[i].lat, points[i].lon, points[i+1].lat, points[i+1].lon);
|
||||
const de = (smoothed[i] != null && smoothed[i+1] != null) ? (smoothed[i+1] - smoothed[i]) : 0;
|
||||
const g = dm > 1 ? (de / dm) * 100 : 0;
|
||||
const center = (cumM[i] + cumM[i+1]) / 2;
|
||||
let a = i, b = i + 1;
|
||||
while (a > 0 && center - cumM[a] < W / 2) a--;
|
||||
while (b < n - 1 && cumM[b] - center < W / 2) b++;
|
||||
// pull window ends in off any null-elevation points
|
||||
while (a < i && smoothed[a] == null) a++;
|
||||
while (b > i + 1 && smoothed[b] == null) b--;
|
||||
const span = cumM[b] - cumM[a];
|
||||
let g = 0;
|
||||
if (span > 1 && smoothed[a] != null && smoothed[b] != null) {
|
||||
g = ((smoothed[b] - smoothed[a]) / span) * 100;
|
||||
}
|
||||
grades[i] = g;
|
||||
if (dm > 10 && Math.abs(g) > Math.abs(maxGrade)) maxGrade = g;
|
||||
if (span > 10 && Math.abs(g) > Math.abs(maxGrade)) maxGrade = g;
|
||||
}
|
||||
let ascent = 0, descent = 0, ref = null;
|
||||
for (let i = 0; i < n; i++) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue