mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-12-02 10:02:12 +00:00
simplify computations
This commit is contained in:
130
gpx/src/gpx.ts
130
gpx/src/gpx.ts
@@ -818,9 +818,6 @@ export class TrackSegment extends GPXTreeLeaf {
|
|||||||
|
|
||||||
statistics.local.points = this.trkpt.map((point) => point);
|
statistics.local.points = this.trkpt.map((point) => point);
|
||||||
|
|
||||||
statistics.local.elevation.smoothed = this._computeSmoothedElevation();
|
|
||||||
statistics.local.slope.at = this._computeSlope();
|
|
||||||
|
|
||||||
const points = this.trkpt;
|
const points = this.trkpt;
|
||||||
for (let i = 0; i < points.length; i++) {
|
for (let i = 0; i < points.length; i++) {
|
||||||
points[i]._data['index'] = i;
|
points[i]._data['index'] = i;
|
||||||
@@ -961,55 +958,18 @@ export class TrackSegment extends GPXTreeLeaf {
|
|||||||
? statistics.global.distance.moving / (statistics.global.time.moving / 3600)
|
? statistics.global.distance.moving / (statistics.global.time.moving / 3600)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
statistics.local.speed = timeWindowSmoothing(
|
statistics.local.speed = timeWindowSmoothing(points, 10000, (start, end) =>
|
||||||
points,
|
points[start].time && points[end].time
|
||||||
10000,
|
? (3600 *
|
||||||
(index) =>
|
(statistics.local.distance.total[end] -
|
||||||
index > 0
|
statistics.local.distance.total[start])) /
|
||||||
? distance(points[index - 1].getCoordinates(), points[index].getCoordinates())
|
Math.max((points[end].time.getTime() - points[start].time.getTime()) / 1000, 1)
|
||||||
: 0,
|
|
||||||
(accumulated, start, end) =>
|
|
||||||
points[start].time &&
|
|
||||||
points[end].time &&
|
|
||||||
points[end].time.getTime() - points[start].time.getTime() > 0
|
|
||||||
? (3600 * accumulated) /
|
|
||||||
(points[end].time.getTime() - points[start].time.getTime())
|
|
||||||
: undefined
|
: undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
return statistics;
|
return statistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
_computeSmoothedElevation(): number[] {
|
|
||||||
const points = this.trkpt;
|
|
||||||
|
|
||||||
let smoothed = distanceWindowSmoothing(
|
|
||||||
points,
|
|
||||||
100,
|
|
||||||
(index) => points[index].ele ?? 0,
|
|
||||||
(accumulated, start, end) => accumulated / (end - start + 1)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (points.length > 0) {
|
|
||||||
smoothed[0] = points[0].ele ?? 0;
|
|
||||||
smoothed[points.length - 1] = points[points.length - 1].ele ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return smoothed;
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeSlope(): number[] {
|
|
||||||
const points = this.trkpt;
|
|
||||||
|
|
||||||
return distanceWindowSmoothingWithDistanceAccumulator(
|
|
||||||
points,
|
|
||||||
50,
|
|
||||||
(accumulated, start, end) =>
|
|
||||||
(100 * ((points[end].ele ?? 0) - (points[start].ele ?? 0))) /
|
|
||||||
(accumulated > 0 ? accumulated : 1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_elevationComputation(statistics: GPXStatistics) {
|
_elevationComputation(statistics: GPXStatistics) {
|
||||||
let simplified = ramerDouglasPeucker(
|
let simplified = ramerDouglasPeucker(
|
||||||
this.trkpt,
|
this.trkpt,
|
||||||
@@ -1068,6 +1028,12 @@ export class TrackSegment extends GPXTreeLeaf {
|
|||||||
|
|
||||||
statistics.local.slope.segment = slope;
|
statistics.local.slope.segment = slope;
|
||||||
statistics.local.slope.length = length;
|
statistics.local.slope.length = length;
|
||||||
|
statistics.local.slope.at = distanceWindowSmoothing(statistics, 0.05, (start, end) => {
|
||||||
|
const ele = this.trkpt[end].ele - this.trkpt[start].ele || 0;
|
||||||
|
const dist =
|
||||||
|
statistics.local.distance.total[end] - statistics.local.distance.total[start];
|
||||||
|
return dist > 0 ? (0.1 * ele) / dist : 0;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getNumberOfTrackPoints(): number {
|
getNumberOfTrackPoints(): number {
|
||||||
@@ -1314,8 +1280,14 @@ export class TrackSegment extends GPXTreeLeaf {
|
|||||||
lastPoint: TrackPoint | undefined
|
lastPoint: TrackPoint | undefined
|
||||||
) {
|
) {
|
||||||
let og = getOriginal(this); // Read as much as possible from the original object because it is faster
|
let og = getOriginal(this); // Read as much as possible from the original object because it is faster
|
||||||
let slope = og._computeSlope();
|
let statistics = og._computeStatistics();
|
||||||
let trkpt = withArtificialTimestamps(og.trkpt, totalTime, lastPoint, startTime, slope);
|
let trkpt = withArtificialTimestamps(
|
||||||
|
og.trkpt,
|
||||||
|
totalTime,
|
||||||
|
lastPoint,
|
||||||
|
startTime,
|
||||||
|
statistics.local.slope.at
|
||||||
|
);
|
||||||
this.trkpt = freeze(trkpt); // Pre-freeze the array, faster as well
|
this.trkpt = freeze(trkpt); // Pre-freeze the array, faster as well
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1671,7 +1643,6 @@ export class GPXStatistics {
|
|||||||
};
|
};
|
||||||
speed: number[];
|
speed: number[];
|
||||||
elevation: {
|
elevation: {
|
||||||
smoothed: number[];
|
|
||||||
gain: number[];
|
gain: number[];
|
||||||
loss: number[];
|
loss: number[];
|
||||||
};
|
};
|
||||||
@@ -1742,7 +1713,6 @@ export class GPXStatistics {
|
|||||||
},
|
},
|
||||||
speed: [],
|
speed: [],
|
||||||
elevation: {
|
elevation: {
|
||||||
smoothed: [],
|
|
||||||
gain: [],
|
gain: [],
|
||||||
loss: [],
|
loss: [],
|
||||||
},
|
},
|
||||||
@@ -1777,9 +1747,6 @@ export class GPXStatistics {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.local.speed = this.local.speed.concat(other.local.speed);
|
this.local.speed = this.local.speed.concat(other.local.speed);
|
||||||
this.local.elevation.smoothed = this.local.elevation.smoothed.concat(
|
|
||||||
other.local.elevation.smoothed
|
|
||||||
);
|
|
||||||
this.local.slope.at = this.local.slope.at.concat(other.local.slope.at);
|
this.local.slope.at = this.local.slope.at.concat(other.local.slope.at);
|
||||||
this.local.slope.segment = this.local.slope.segment.concat(other.local.slope.segment);
|
this.local.slope.segment = this.local.slope.segment.concat(other.local.slope.segment);
|
||||||
this.local.slope.length = this.local.slope.length.concat(other.local.slope.length);
|
this.local.slope.length = this.local.slope.length.concat(other.local.slope.length);
|
||||||
@@ -1971,83 +1938,52 @@ export function getElevationDistanceFunction(statistics: GPXStatistics) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function windowSmoothing(
|
function windowSmoothing(
|
||||||
points: TrackPoint[],
|
length: number,
|
||||||
distance: (index1: number, index2: number) => number,
|
distance: (index1: number, index2: number) => number,
|
||||||
window: number,
|
window: number,
|
||||||
accumulate: (index: number) => number,
|
compute: (start: number, end: number) => number
|
||||||
compute: (accumulated: number, start: number, end: number) => number,
|
|
||||||
remove?: (index: number) => number
|
|
||||||
): number[] {
|
): number[] {
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
let start = 0,
|
let start = 0,
|
||||||
end = 0,
|
end = 0;
|
||||||
accumulated = 0;
|
for (var i = 0; i < length; i++) {
|
||||||
for (var i = 0; i < points.length; i++) {
|
|
||||||
while (start + 1 < i && distance(start, i) > window) {
|
while (start + 1 < i && distance(start, i) > window) {
|
||||||
if (remove) {
|
|
||||||
accumulated -= remove(start);
|
|
||||||
} else {
|
|
||||||
accumulated -= accumulate(start);
|
|
||||||
}
|
|
||||||
start++;
|
start++;
|
||||||
}
|
}
|
||||||
while (end < points.length && distance(i, end) <= window) {
|
end = Math.min(i + 2, length);
|
||||||
accumulated += accumulate(end);
|
while (end < length && distance(i, end) <= window) {
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
result[i] = compute(accumulated, start, end - 1);
|
result[i] = compute(start, end - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function distanceWindowSmoothing(
|
function distanceWindowSmoothing(
|
||||||
points: TrackPoint[],
|
statistics: GPXStatistics,
|
||||||
window: number,
|
window: number,
|
||||||
accumulate: (index: number) => number,
|
compute: (start: number, end: number) => number
|
||||||
compute: (accumulated: number, start: number, end: number) => number
|
|
||||||
): number[] {
|
): number[] {
|
||||||
return windowSmoothing(
|
return windowSmoothing(
|
||||||
points,
|
statistics.local.points.length,
|
||||||
(index1, index2) =>
|
(index1, index2) =>
|
||||||
distance(points[index1].getCoordinates(), points[index2].getCoordinates()),
|
statistics.local.distance.total[index2] - statistics.local.distance.total[index1],
|
||||||
window,
|
window,
|
||||||
accumulate,
|
|
||||||
compute
|
compute
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function distanceWindowSmoothingWithDistanceAccumulator(
|
|
||||||
points: TrackPoint[],
|
|
||||||
distanceWindow: number,
|
|
||||||
compute: (accumulated: number, start: number, end: number) => number
|
|
||||||
): number[] {
|
|
||||||
return windowSmoothing(
|
|
||||||
points,
|
|
||||||
(index1, index2) =>
|
|
||||||
distance(points[index1].getCoordinates(), points[index2].getCoordinates()),
|
|
||||||
distanceWindow,
|
|
||||||
(index) =>
|
|
||||||
index > 0
|
|
||||||
? distance(points[index - 1].getCoordinates(), points[index].getCoordinates())
|
|
||||||
: 0,
|
|
||||||
compute,
|
|
||||||
(index) => distance(points[index].getCoordinates(), points[index + 1].getCoordinates())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function timeWindowSmoothing(
|
function timeWindowSmoothing(
|
||||||
points: TrackPoint[],
|
points: TrackPoint[],
|
||||||
window: number,
|
window: number,
|
||||||
accumulate: (index: number) => number,
|
compute: (start: number, end: number) => number
|
||||||
compute: (accumulated: number, start: number, end: number) => number
|
|
||||||
): number[] {
|
): number[] {
|
||||||
return windowSmoothing(
|
return windowSmoothing(
|
||||||
points,
|
points.length,
|
||||||
(index1, index2) => points[index2].time?.getTime() - points[index1].time?.getTime() || 0,
|
(index1, index2) => points[index2].time?.getTime() - points[index1].time?.getTime() || 0,
|
||||||
window,
|
window,
|
||||||
accumulate,
|
|
||||||
compute
|
compute
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user