mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-23 07:26:30 +00:00
feat(assistant): hike, walk and route cards with their lines on the map, and "Plan this"
This commit is contained in:
@@ -16,10 +16,37 @@ export interface ElevationProfileChartModel {
|
||||
areaPath: string
|
||||
}
|
||||
|
||||
/** The axes a chart is drawn on: its lowest and highest heights and its length. */
|
||||
interface ElevationProfileDomain {
|
||||
minElevation: number
|
||||
maxElevation: number
|
||||
maxDistance: number
|
||||
}
|
||||
|
||||
/**
|
||||
* One set of axes for several profiles drawn over each other (the ways a
|
||||
* route can take), so a way that climbs higher or runs longer looks it.
|
||||
* Null when none of them has a sample.
|
||||
*/
|
||||
export function sharedProfileDomain(
|
||||
profiles: ReadonlyArray<readonly DistanceIndexedProfileSample[]>,
|
||||
): ElevationProfileDomain | null {
|
||||
const samples = profiles.flat()
|
||||
if (samples.length === 0) return null
|
||||
const elevations = samples.map(sample => sample.elevationMeters)
|
||||
return {
|
||||
minElevation: Math.min(...elevations),
|
||||
maxElevation: Math.max(...elevations),
|
||||
maxDistance: Math.max(...profiles.map(profile => profile[profile.length - 1]?.distanceMeters ?? 0)),
|
||||
}
|
||||
}
|
||||
|
||||
/** The chart of a profile, on its own axes or on the `domain` it shares with others. */
|
||||
export function prepareElevationProfileChart(
|
||||
samples: readonly DistanceIndexedProfileSample[],
|
||||
width: number,
|
||||
height: number,
|
||||
domain: ElevationProfileDomain | null = null,
|
||||
): ElevationProfileChartModel {
|
||||
if (samples.length === 0) return {
|
||||
minElevation: 0,
|
||||
@@ -32,10 +59,10 @@ export function prepareElevationProfileChart(
|
||||
areaPath: '',
|
||||
}
|
||||
const elevations = samples.map(sample => sample.elevationMeters)
|
||||
const minElevation = Math.min(...elevations)
|
||||
const maxElevation = Math.max(...elevations)
|
||||
const minElevation = domain?.minElevation ?? Math.min(...elevations)
|
||||
const maxElevation = domain?.maxElevation ?? Math.max(...elevations)
|
||||
const elevationSpan = Math.max(maxElevation - minElevation, 1)
|
||||
const maxDistance = samples[samples.length - 1].distanceMeters || 1
|
||||
const maxDistance = (domain?.maxDistance ?? samples[samples.length - 1].distanceMeters) || 1
|
||||
const points = samples.map(sample => ({
|
||||
x: (sample.distanceMeters / maxDistance) * width,
|
||||
y: height - ((sample.elevationMeters - minElevation) / elevationSpan) * (height - 8) - 4,
|
||||
@@ -50,6 +77,9 @@ export function prepareElevationProfileChart(
|
||||
hasGeographicCoordinates: samples.every(sample => Number.isFinite(sample.lat) && Number.isFinite(sample.lng)),
|
||||
points,
|
||||
linePath,
|
||||
areaPath: `${linePath} L${width},${height} L0,${height} Z`,
|
||||
// On shared axes a shorter way ends before the right edge: its area closes under its own ends.
|
||||
areaPath: domain
|
||||
? `${linePath} L${points[points.length - 1].x.toFixed(1)},${height} L${points[0].x.toFixed(1)},${height} Z`
|
||||
: `${linePath} L${width},${height} L0,${height} Z`,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user