create slope segments

This commit is contained in:
vcoppe
2024-06-25 19:41:37 +02:00
parent 42fe819a72
commit f823bcade5
6 changed files with 101 additions and 26 deletions

View File

@@ -137,12 +137,16 @@
let context = contexts.filter((context) => context.datasetIndex === 0);
if (context.length === 0) return;
let point = context[0].raw;
let slope = point.slope.toFixed(1);
let slope = {
at: point.slope.at.toFixed(1),
segment: point.slope.segment.toFixed(1),
length: getDistanceWithUnits(point.slope.length)
};
let surface = point.surface ? point.surface : 'unknown';
return [
` ${$_('quantities.distance')}: ${getDistanceWithUnits(point.x, false)}`,
` ${$_('quantities.slope')}: ${slope} %`,
` ${$_('quantities.slope')}: ${slope.at} %${elevationFill === 'slope' ? ` (${slope.length} @${slope.segment} %)` : ''}`,
` ${$_('quantities.surface')}: ${$_(`toolbar.routing.surface.${surface}`)}`
];
}
@@ -317,7 +321,11 @@
return {
x: getConvertedDistance(data.local.distance.total[index]),
y: point.ele ? getConvertedElevation(point.ele) : 0,
slope: data.local.slope[index],
slope: {
at: data.local.slope.at[index],
segment: data.local.slope.segment[index],
length: data.local.slope.length[index]
},
surface: point.getSurface(),
coordinates: point.getCoordinates(),
index: index
@@ -421,7 +429,7 @@
];
function slopeFillCallback(context) {
let slope = context.p0.raw.slope;
let slope = context.p0.raw.slope.segment;
if (slope <= 1 && slope >= -1) return slopeColors[6];
else if (slope > 0) {
if (slope <= 3) return slopeColors[7];

View File

@@ -8,11 +8,10 @@
import { Filter } from 'lucide-svelte';
import { _ } from 'svelte-i18n';
import WithUnits from '$lib/components/WithUnits.svelte';
import { ramerDouglasPeucker, type SimplifiedTrackPoint } from '$lib/simplify';
import { dbUtils, fileObservers } from '$lib/db';
import { map } from '$lib/stores';
import { onDestroy } from 'svelte';
import { TrackPoint } from 'gpx';
import { ramerDouglasPeucker, TrackPoint, type SimplifiedTrackPoint } from 'gpx';
import { derived } from 'svelte/store';
let sliderValue = [50];

View File

@@ -1,5 +1,6 @@
import { earthRadius, ramerDouglasPeucker } from "$lib/simplify";
import type { GPXFile, TrackSegment } from "gpx";
import { ramerDouglasPeucker, type GPXFile, type TrackSegment } from "gpx";
const earthRadius = 6371008.8;
export function getZoomLevelForDistance(latitude: number, distance?: number): number {
if (distance === undefined) {

View File

@@ -1,99 +0,0 @@
import type { Coordinates, TrackPoint } from "gpx";
export type SimplifiedTrackPoint = { point: TrackPoint, distance?: number };
export const earthRadius = 6371008.8;
export function ramerDouglasPeucker(points: readonly TrackPoint[], epsilon: number = 50, start: number = 0, end: number = points.length - 1): SimplifiedTrackPoint[] {
if (points.length == 0) {
return [];
} else if (points.length == 1) {
return [{
point: points[0]
}];
}
let simplified = [{
point: points[start]
}];
ramerDouglasPeuckerRecursive(points, epsilon, start, end, simplified);
simplified.push({
point: points[end]
});
return simplified;
}
function ramerDouglasPeuckerRecursive(points: readonly TrackPoint[], epsilon: number, start: number, end: number, simplified: SimplifiedTrackPoint[]) {
let largest = {
index: 0,
distance: 0
};
for (let i = start + 1; i < end; i++) {
let distance = crossarc(points[start].getCoordinates(), points[end].getCoordinates(), points[i].getCoordinates());
if (distance > largest.distance) {
largest.index = i;
largest.distance = distance;
}
}
if (largest.distance > epsilon && largest.index != 0) {
ramerDouglasPeuckerRecursive(points, epsilon, start, largest.index, simplified);
simplified.push({ point: points[largest.index], distance: largest.distance });
ramerDouglasPeuckerRecursive(points, epsilon, largest.index, end, simplified);
}
}
function crossarc(coord1: Coordinates, coord2: Coordinates, coord3: Coordinates): number {
// Calculates the shortest distance in meters
// between an arc (defined by p1 and p2) and a third point, p3.
// Input lat1,lon1,lat2,lon2,lat3,lon3 in degrees.
const rad = Math.PI / 180;
const lat1 = coord1.lat * rad;
const lat2 = coord2.lat * rad;
const lat3 = coord3.lat * rad;
const lon1 = coord1.lon * rad;
const lon2 = coord2.lon * rad;
const lon3 = coord3.lon * rad;
// Prerequisites for the formulas
const bear12 = bearing(lat1, lon1, lat2, lon2);
const bear13 = bearing(lat1, lon1, lat3, lon3);
let dis13 = distance(lat1, lon1, lat3, lon3);
let diff = Math.abs(bear13 - bear12);
if (diff > Math.PI) {
diff = 2 * Math.PI - diff;
}
// Is relative bearing obtuse?
if (diff > (Math.PI / 2)) {
return dis13;
}
// Find the cross-track distance.
let dxt = Math.asin(Math.sin(dis13 / earthRadius) * Math.sin(bear13 - bear12)) * earthRadius;
// Is p4 beyond the arc?
let dis12 = distance(lat1, lon1, lat2, lon2);
let dis14 = Math.acos(Math.cos(dis13 / earthRadius) / Math.cos(dxt / earthRadius)) * earthRadius;
if (dis14 > dis12) {
return distance(lat2, lon2, lat3, lon3);
} else {
return Math.abs(dxt);
}
}
function distance(latA: number, lonA: number, latB: number, lonB: number): number {
// Finds the distance between two lat / lon points.
return Math.acos(Math.sin(latA) * Math.sin(latB) + Math.cos(latA) * Math.cos(latB) * Math.cos(lonB - lonA)) * earthRadius;
}
function bearing(latA: number, lonA: number, latB: number, lonB: number): number {
// Finds the bearing from one lat / lon point to another.
return Math.atan2(Math.sin(lonB - lonA) * Math.cos(latB),
Math.cos(latA) * Math.sin(latB) - Math.sin(latA) * Math.cos(latB) * Math.cos(lonB - lonA));
}