How to Implement Elevation Profile Analysis in GeoLibre
GeoLibre's elevation profile feature enables users to draw a line on a MapLibre GL map, sample terrain elevations via the Open-Meteo API, compute distance statistics, and render interactive SVG charts that export to CSV and SVG formats.
This implementation provides a complete end-to-end workflow for terrain analysis in geographic web applications. By combining client-side geometry processing with external elevation services, GeoLibre delivers a lightweight yet powerful tool for outdoor planning and terrain visualization. The following guide explains how to implement elevation profile analysis using the official GeoLibre source architecture.
Architecture Overview
The elevation profile system in opengeos/GeoLibre follows a modular design split across five logical layers. Each layer handles specific responsibilities from user interaction to data persistence.
- UI Control Layer –
ElevationProfileControl.tsmanages the MapLibre GL control button, floating panel interface, and user interactions including line drawing, unit toggling, and state persistence. - Geometry & Statistics Layer –
geometry.tsprovides pure-math utilities for resampling polylines, calculating haversine distances, and aggregating elevation statistics. - Data Fetching Layer –
client.tsinterfaces with the Open-Meteo API endpoint (https://api.open-meteo.com/v1/elevation), handling timeouts and error classification. - Chart Rendering Layer –
profileChart.tsgenerates SVG paths for line visualization and area fills, plus scaling functions for hover interactions. - Export Layer – Helper methods in
ElevationProfileControlserialize data to CSV and SVG formats, supporting both browser downloads and native file system integration via Tauri.
Step-by-Step Implementation Workflow
1. Initialize the Map Control
The process begins when users activate the elevation profile button. The _createMountainIcon method renders the control interface, while the panel registers click handlers for the drawing mode. When activated, the system listens for map clicks via _onMapClick, storing vertices in the _drawVertices array until the user double-clicks or presses Enter to finish.
2. Resample the Line Geometry
Once drawing completes, the _profileLine method calls resampleLine from packages/plugins/src/plugins/elevation-profile/elevation/geometry.ts. This function interpolates the user-drawn polyline into uniformly spaced segments, producing sampled.coords and sampled.distances arrays. The resampling respects the MAX_POINTS_PER_REQUEST constant (set to 100), ensuring API compliance while maintaining geographic accuracy.
3. Fetch Elevation Data
The fetchElevations function in client.ts constructs a query string from the resampled coordinates and sends a GET request to the Open-Meteo elevation endpoint. The implementation includes:
- Timeout handling for network resilience
- Response validation ensuring coordinate/elevation array length parity
- Error wrapping via the custom
ElevationFetchErrorclass for debugging
4. Calculate Terrain Statistics
With elevation data returned, computeStats (in geometry.ts) iterates through the height array to derive:
- Minimum and maximum elevation values
- Cumulative ascent (gain) and descent (loss)
- Total distance along the profile line
These metrics update the statistics panel in real-time.
5. Build Chart Geometry
The buildChartGeometry function in profileChart.ts transforms the distance/elevation pairs into SVG-ready data structures:
linePath– SVG path commands for the profile lineareaPath– Closed path for the filled area beneath the linexScale/yScale– Linear mapping functions between data values and pixel coordinatesindexForX– Binary search utility for hover position lookup
6. Render Interactive Visualization
The _renderChart method constructs the SVG DOM element, attaches mousemove handlers for hover tracking, and updates the read-out box with distance and elevation values at the cursor position. The chart automatically adapts to the panelWidth configuration parameter.
7. Export Results
Users export data through two pathways:
- CSV Export:
_exportCsvcallsprofileToCsv(inexport/csv.ts) to format coordinates and elevations as comma-separated values - SVG Export:
_exportSvginlines computed CSS styles and adds a background rectangle via_buildExportSvgfor print-ready graphics
Both methods use the injected ExportTextFile callback when running in Tauri environments, falling back to browser Blob downloads otherwise.
8. Persist State
The getState and setState methods enable serialization of the profile state (collapsed, unitSystem, line), allowing GeoLibre to restore profiles from project files or deep-link URLs via the loadLine method.
Key Source Files and Their Functions
| File | Key Function | Purpose |
|---|---|---|
core/ElevationProfileControl.ts |
loadLine(), _exportCsv(), _exportSvg() |
Main MapLibre control class managing UI lifecycle, drawing logic, and exports |
elevation/geometry.ts |
resampleLine(), computeStats() |
Pure geometric calculations including haversine distance and elevation aggregation |
elevation/client.ts |
fetchElevations() |
Open-Meteo API wrapper with error handling and timeout management |
chart/profileChart.ts |
buildChartGeometry() |
SVG path generation and scaling function creation |
export/csv.ts |
profileToCsv() |
Data serialization for spreadsheet export |
utils/deep-link.ts |
URL parameter parsing | Helper for restoring profiles from query strings |
Practical Implementation Examples
Adding the Control to Your Map
Instantiate the control with your preferred units and sample limits:
import { ElevationProfileControl } from
'packages/plugins/src/plugins/elevation-profile/core/ElevationProfileControl';
const elevationControl = new ElevationProfileControl({
title: 'Elevation Profile',
unitSystem: 'metric', // or 'imperial'
panelWidth: 340,
maxSamples: 80, // Must be < MAX_POINTS_PER_REQUEST (100)
});
map.addControl(elevationControl, 'top-right');
Loading a Line Programmatically
Restore profiles from saved coordinates or deep links:
const line = [
[-122.45, 37.78],
[-122.44, 37.79],
[-122.43, 37.80],
];
await elevationControl.loadLine(line); // Draws line, fetches data, fits bounds
Triggering Exports
Call export methods directly from UI event handlers:
// Download as CSV
elevationControl._exportCsv();
// Download as SVG
elevationControl._exportSvg();
Switching Unit Systems
Cycle between measurement systems programmatically:
elevationControl._cycleUnits(); // Toggles metric ↔ imperial, updates labels
Error Handling and Performance Considerations
The implementation includes robust error boundaries. When fetchElevations encounters network timeouts, HTTP failures, or payload mismatches, it throws ElevationFetchError with descriptive context rather than failing silently.
For performance, the maxSamples configuration parameter (defaulting to 100) prevents API rate limiting while maintaining visual fidelity. The resampling algorithm in geometry.ts uses spherical haversine calculations for accurate distance measurement across large geographic spans.
Summary
- GeoLibre implements elevation profile analysis through a five-layer architecture separating UI, geometry, network, rendering, and export concerns.
- The Open-Meteo API provides free elevation data with a 100-point limit per request, handled transparently by the resampling logic in
geometry.ts. - Interactive SVG charts are generated serverlessly via
profileChart.ts, supporting hover interactions and responsive scaling. - State persistence methods enable deep-linking and project save/restore functionality across sessions.
- Export utilities support both CSV (data analysis) and SVG (visualization) workflows with automatic environment detection.
Frequently Asked Questions
How does GeoLibre handle the Open-Meteo API's 100-point limit?
The resampleLine function in geometry.ts automatically interpolates user-drawn lines to meet the MAX_POINTS_PER_REQUEST constant (100 points). You can configure a lower limit via the maxSamples option in the control constructor to reduce API calls, though this reduces profile resolution.
What coordinate format does the elevation profile expect?
All internal functions expect arrays of [longitude, latitude] number pairs (EPSG:4326). The loadLine() method validates that input arrays contain at least two points before processing, throwing descriptive errors for malformed input.
Can I customize the chart appearance?
The buildChartGeometry function in profileChart.ts returns raw SVG path data and scaling functions, allowing you to override the _renderChart method in ElevationProfileControl.ts to inject custom CSS classes or modify the SVG structure before DOM insertion.
Does the elevation profile work offline?
No, the current implementation requires internet connectivity to reach https://api.open-meteo.com/v1/elevation. However, the geometry calculation and chart rendering modules are pure JavaScript functions that operate offline once elevation data is cached or provided programmatically via loadLine().
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →