4

I would like to plot many elevation profiles with labels on specific waypoints (Points of Interest). In the end it should look like this: enter image description here Or like here: https://www.birdandhike.com/Hike/Mt_Char/Sawmill_Big/maps-sb/Sawmill_Big_Prof.htm

The DEM and the Tracks (gpx and other formats) are already there. Now I want to create the elevation profiles with names using QGIS and scripts.

I already checked the profile plugins in QGIS but none of them is able to output the names of specific waypoints.

Do you know a easy workaround to achieve this?

EDIT1: The gpx track looks like this. I want to have the names of the WPT-Features (e.g. "valley","start","peak") written on the elevation profile

<?xml version="1.0" encoding="UTF-8"?>
<!-- track-length = 4644 filtered ascend = 159 plain-ascend = -764 cost=12636 energy=.0kwh time=2h 9m 17s -->
<gpx 
 xmlns="http://www.topografix.com/GPX/1/1" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" 
 creator="BRouter-1.6.1" version="1.1">
 <wpt lon="6.005273" lat="44.910205">
  <name>start</name>
 </wpt>
 <wpt lon="6.000938" lat="44.907256">
  <name>valley</name>
 </wpt>
 <wpt lon="6.000209" lat="44.904671">
  <name>peak1</name>
 </wpt>
 <wpt lon="5.984759" lat="44.905219">
  <name>peak2</name>
 </wpt>
 <wpt lon="5.988064" lat="44.915039">
  <name>end</name>
 </wpt>
 <trk>
  <name>hike</name>
  <trkseg>
   <trkpt lon="6.005280" lat="44.910300"><ele>2399.25</ele></trkpt>
   <trkpt lon="6.005140" lat="44.910209"><ele>2397.5</ele></trkpt>
   <trkpt lon="6.004897" lat="44.909971"><ele>2395.0</ele></trkpt>
   <trkpt lon="6.004762" lat="44.909907"><ele>2396.0</ele></trkpt>
   <trkpt lon="6.004484" lat="44.909822"><ele>2399.0</ele></trkpt>
   <trkpt lon="6.004411" lat="44.909778"><ele>2399.5</ele></trkpt>
   <trkpt lon="6.004219" lat="44.909626"><ele>2400.25</ele></trkpt>
   <trkpt lon="6.004030" lat="44.909456"><ele>2403.5</ele></trkpt>
   <trkpt lon="6.003947" lat="44.909340"><ele>2404.75</ele></trkpt>
   <trkpt lon="6.003913" lat="44.909181"><ele>2403.75</ele></trkpt>
   <trkpt lon="6.003748" lat="44.908935"><ele>2405.5</ele></trkpt>
   <trkpt lon="6.003613" lat="44.908836"><ele>2408.5</ele></trkpt>
   <trkpt lon="6.003452" lat="44.908730"><ele>2411.75</ele></trkpt>
   <trkpt lon="6.002808" lat="44.908451"><ele>2429.75</ele></trkpt>
   <trkpt lon="6.002544" lat="44.908326"><ele>2436.25</ele></trkpt>
   <trkpt lon="6.002435" lat="44.908241"><ele>2440.75</ele></trkpt>
   <trkpt lon="6.002347" lat="44.908140"><ele>2444.5</ele></trkpt>
   <trkpt lon="6.002221" lat="44.908055"><ele>2450.5</ele></trkpt>
   <trkpt lon="6.002068" lat="44.907923"><ele>2456.0</ele></trkpt>
   <trkpt lon="6.001889" lat="44.907816"><ele>2462.75</ele></trkpt>
   <trkpt lon="6.001722" lat="44.907700"><ele>2467.75</ele></trkpt>
   <trkpt lon="6.001472" lat="44.907585"><ele>2469.5</ele></trkpt>
   <trkpt lon="6.001398" lat="44.907565"><ele>2470.0</ele></trkpt>
   <trkpt lon="6.001246" lat="44.907489"><ele>2470.5</ele></trkpt>
   <trkpt lon="6.001149" lat="44.907422"><ele>2473.0</ele></trkpt>
   <trkpt lon="6.001003" lat="44.907193"><ele>2478.5</ele></trkpt>
   <trkpt lon="6.000930" lat="44.907129"><ele>2480.75</ele></trkpt>
   <trkpt lon="6.000901" lat="44.907128"><ele>2481.25</ele></trkpt>
   <trkpt lon="6.000833" lat="44.907182"><ele>2481.5</ele></trkpt>
   <trkpt lon="6.000867" lat="44.907061"><ele>2482.75</ele></trkpt>
   <trkpt lon="6.000851" lat="44.906900"><ele>2485.25</ele></trkpt>
   <trkpt lon="6.000802" lat="44.906802"><ele>2485.75</ele></trkpt>
   <trkpt lon="6.000807" lat="44.906625"><ele>2490.75</ele></trkpt>
   <trkpt lon="6.000757" lat="44.906530"><ele>2495.75</ele></trkpt>
   <trkpt lon="6.000682" lat="44.906473"><ele>2497.25</ele></trkpt>
   <trkpt lon="6.000661" lat="44.906423"><ele>2500.0</ele></trkpt>
   <trkpt lon="6.000669" lat="44.906386"><ele>2502.75</ele></trkpt>
   <trkpt lon="6.000735" lat="44.906334"><ele>2508.0</ele></trkpt>
   <trkpt lon="6.000799" lat="44.906164"><ele>2521.25</ele></trkpt>
   <trkpt lon="6.000794" lat="44.906026"><ele>2530.25</ele></trkpt>
   <trkpt lon="6.000741" lat="44.905909"><ele>2536.75</ele></trkpt>
   <trkpt lon="6.000755" lat="44.905811"><ele>2542.25</ele></trkpt>
   <trkpt lon="6.000830" lat="44.905601"><ele>2543.75</ele></trkpt>
   <trkpt lon="6.000800" lat="44.905520"><ele>2543.75</ele></trkpt>
   <trkpt lon="6.000422" lat="44.905142"><ele>2549.25</ele></trkpt>
   <trkpt lon="6.000330" lat="44.905084"><ele>2552.0</ele></trkpt>
   <trkpt lon="6.000293" lat="44.904982"><ele>2554.0</ele></trkpt>
   <trkpt lon="6.000324" lat="44.904927"><ele>2550.5</ele></trkpt>
   <trkpt lon="6.000328" lat="44.904885"><ele>2548.25</ele></trkpt>
   <trkpt lon="6.000324" lat="44.904927"><ele>2550.5</ele></trkpt>
   <trkpt lon="6.000293" lat="44.904982"><ele>2554.0</ele></trkpt>
   <trkpt lon="6.000330" lat="44.905084"><ele>2552.0</ele></trkpt>
   <trkpt lon="6.000422" lat="44.905142"><ele>2549.25</ele></trkpt>
   <trkpt lon="6.000800" lat="44.905520"><ele>2543.75</ele></trkpt>
   <trkpt lon="6.000830" lat="44.905601"><ele>2543.75</ele></trkpt>
   <trkpt lon="6.000755" lat="44.905811"><ele>2542.25</ele></trkpt>
   <trkpt lon="6.000741" lat="44.905909"><ele>2536.75</ele></trkpt>
   <trkpt lon="6.000794" lat="44.906026"><ele>2530.25</ele></trkpt>
   <trkpt lon="6.000799" lat="44.906164"><ele>2521.25</ele></trkpt>
   <trkpt lon="6.000735" lat="44.906334"><ele>2508.0</ele></trkpt>
   <trkpt lon="6.000669" lat="44.906386"><ele>2502.75</ele></trkpt>
   <trkpt lon="6.000661" lat="44.906423"><ele>2500.0</ele></trkpt>
   <trkpt lon="6.000682" lat="44.906473"><ele>2497.25</ele></trkpt>
   <trkpt lon="6.000757" lat="44.906530"><ele>2495.75</ele></trkpt>
   <trkpt lon="6.000807" lat="44.906625"><ele>2490.75</ele></trkpt>
   <trkpt lon="6.000802" lat="44.906802"><ele>2485.75</ele></trkpt>
   <trkpt lon="6.000851" lat="44.906900"><ele>2485.25</ele></trkpt>
   <trkpt lon="6.000867" lat="44.907061"><ele>2482.75</ele></trkpt>
   <trkpt lon="6.000833" lat="44.907182"><ele>2481.5</ele></trkpt>
   <trkpt lon="6.000811" lat="44.907142"><ele>2481.25</ele></trkpt>
   <trkpt lon="6.000757" lat="44.907090"><ele>2479.75</ele></trkpt>
   <trkpt lon="6.000693" lat="44.907132"><ele>2476.75</ele></trkpt>
   <trkpt lon="6.000655" lat="44.907074"><ele>2476.25</ele></trkpt>
   <trkpt lon="6.000438" lat="44.906983"><ele>2469.75</ele></trkpt>
   <trkpt lon="6.000253" lat="44.906933"><ele>2464.25</ele></trkpt>
   <trkpt lon="6.000092" lat="44.906899"><ele>2459.5</ele></trkpt>
   <trkpt lon="5.999980" lat="44.906887"><ele>2455.5</ele></trkpt>
   <trkpt lon="6.000002" lat="44.906966"><ele>2454.25</ele></trkpt>
   <trkpt lon="5.999879" lat="44.906957"><ele>2448.5</ele></trkpt>
   <trkpt lon="5.999941" lat="44.907034"><ele>2449.5</ele></trkpt>
   <trkpt lon="5.999770" lat="44.906997"><ele>2442.25</ele></trkpt>
   <trkpt lon="5.999880" lat="44.907079"><ele>2445.25</ele></trkpt>
   <trkpt lon="5.999554" lat="44.906959"><ele>2432.5</ele></trkpt>
   <trkpt lon="5.999477" lat="44.906917"><ele>2429.5</ele></trkpt>
   <trkpt lon="5.999288" lat="44.906888"><ele>2420.5</ele></trkpt>
   <trkpt lon="5.999219" lat="44.906853"><ele>2417.75</ele></trkpt>
   <trkpt lon="5.999168" lat="44.906804"><ele>2415.75</ele></trkpt>
   <trkpt lon="5.999093" lat="44.906804"><ele>2412.75</ele></trkpt>
   <trkpt lon="5.999041" lat="44.906820"><ele>2410.5</ele></trkpt>
   <trkpt lon="5.998836" lat="44.907070"><ele>2398.75</ele></trkpt>
   <trkpt lon="5.998813" lat="44.907143"><ele>2397.0</ele></trkpt>
   <trkpt lon="5.998818" lat="44.907243"><ele>2395.75</ele></trkpt>
   <trkpt lon="5.998837" lat="44.907282"><ele>2395.75</ele></trkpt>
   <trkpt lon="5.998813" lat="44.907334"><ele>2394.25</ele></trkpt>
   <trkpt lon="5.998765" lat="44.907349"><ele>2392.0</ele></trkpt>
   <trkpt lon="5.998554" lat="44.907373"><ele>2383.75</ele></trkpt>
   <trkpt lon="5.998392" lat="44.907353"><ele>2378.0</ele></trkpt>
   <trkpt lon="5.998365" lat="44.907404"><ele>2376.25</ele></trkpt>
   <trkpt lon="5.998311" lat="44.907396"><ele>2374.5</ele></trkpt>
   <trkpt lon="5.998195" lat="44.907534"><ele>2369.0</ele></trkpt>
   <trkpt lon="5.998130" lat="44.907536"><ele>2366.5</ele></trkpt>
   <trkpt lon="5.998117" lat="44.907497"><ele>2366.0</ele></trkpt>
   <trkpt lon="5.998067" lat="44.907483"><ele>2364.5</ele></trkpt>
   <trkpt lon="5.997989" lat="44.907420"><ele>2362.5</ele></trkpt>
   <trkpt lon="5.997918" lat="44.907414"><ele>2360.0</ele></trkpt>
   <trkpt lon="5.997902" lat="44.907449"><ele>2359.0</ele></trkpt>
   <trkpt lon="5.997845" lat="44.907478"><ele>2356.5</ele></trkpt>
   <trkpt lon="5.997517" lat="44.907407"><ele>2345.75</ele></trkpt>
   <trkpt lon="5.997472" lat="44.907390"><ele>2344.25</ele></trkpt>
   <trkpt lon="5.997429" lat="44.907355"><ele>2343.0</ele></trkpt>
   <trkpt lon="5.997311" lat="44.907299"><ele>2338.75</ele></trkpt>
   <trkpt lon="5.997230" lat="44.907231"><ele>2336.25</ele></trkpt>
   <trkpt lon="5.997098" lat="44.907086"><ele>2333.25</ele></trkpt>
   <trkpt lon="5.996286" lat="44.906681"><ele>2311.5</ele></trkpt>
   <trkpt lon="5.996041" lat="44.906621"><ele>2306.0</ele></trkpt>
   <trkpt lon="5.995998" lat="44.906603"><ele>2305.25</ele></trkpt>
   <trkpt lon="5.995972" lat="44.906573"><ele>2305.5</ele></trkpt>
   <trkpt lon="5.995893" lat="44.906551"><ele>2303.5</ele></trkpt>
   <trkpt lon="5.995833" lat="44.906562"><ele>2301.25</ele></trkpt>
   <trkpt lon="5.995779" lat="44.906580"><ele>2298.25</ele></trkpt>
   <trkpt lon="5.995676" lat="44.906572"><ele>2294.0</ele></trkpt>
   <trkpt lon="5.995571" lat="44.906544"><ele>2290.25</ele></trkpt>
   <trkpt lon="5.995325" lat="44.906415"><ele>2283.75</ele></trkpt>
   <trkpt lon="5.995182" lat="44.906422"><ele>2277.25</ele></trkpt>
   <trkpt lon="5.995133" lat="44.906436"><ele>2274.75</ele></trkpt>
   <trkpt lon="5.994957" lat="44.906380"><ele>2269.5</ele></trkpt>
   <trkpt lon="5.994905" lat="44.906353"><ele>2268.5</ele></trkpt>
   <trkpt lon="5.994890" lat="44.906317"><ele>2269.25</ele></trkpt>
   <trkpt lon="5.994851" lat="44.906298"><ele>2268.5</ele></trkpt>
   <trkpt lon="5.994781" lat="44.906290"><ele>2266.5</ele></trkpt>
   <trkpt lon="5.994744" lat="44.906318"><ele>2264.25</ele></trkpt>
   <trkpt lon="5.994574" lat="44.906294"><ele>2259.0</ele></trkpt>
   <trkpt lon="5.994560" lat="44.906320"><ele>2258.0</ele></trkpt>
   <trkpt lon="5.994521" lat="44.906319"><ele>2256.75</ele></trkpt>
   <trkpt lon="5.994493" lat="44.906327"><ele>2255.5</ele></trkpt>
   <trkpt lon="5.994489" lat="44.906397"><ele>2253.5</ele></trkpt>
   <trkpt lon="5.994439" lat="44.906394"><ele>2252.0</ele></trkpt>
   <trkpt lon="5.994415" lat="44.906489"><ele>2249.0</ele></trkpt>
   <trkpt lon="5.994384" lat="44.906510"><ele>2247.5</ele></trkpt>
   <trkpt lon="5.994303" lat="44.906525"><ele>2244.75</ele></trkpt>
   <trkpt lon="5.994213" lat="44.906508"><ele>2242.25</ele></trkpt>
   <trkpt lon="5.994150" lat="44.906575"><ele>2239.0</ele></trkpt>
   <trkpt lon="5.994088" lat="44.906677"><ele>2234.75</ele></trkpt>
   <trkpt lon="5.994013" lat="44.906706"><ele>2230.75</ele></trkpt>
   <trkpt lon="5.994017" lat="44.906674"><ele>2232.5</ele></trkpt>
   <trkpt lon="5.993983" lat="44.906629"><ele>2232.25</ele></trkpt>
   <trkpt lon="5.993935" lat="44.906635"><ele>2230.5</ele></trkpt>
   <trkpt lon="5.993800" lat="44.906712"><ele>2223.25</ele></trkpt>
   <trkpt lon="5.993695" lat="44.906656"><ele>2222.25</ele></trkpt>
   <trkpt lon="5.993605" lat="44.906543"><ele>2220.5</ele></trkpt>
   <trkpt lon="5.993428" lat="44.906284"><ele>2217.25</ele></trkpt>
   <trkpt lon="5.993208" lat="44.906129"><ele>2210.5</ele></trkpt>
   <trkpt lon="5.993070" lat="44.906092"><ele>2205.75</ele></trkpt>
   <trkpt lon="5.993031" lat="44.906032"><ele>2205.0</ele></trkpt>
   <trkpt lon="5.992923" lat="44.905985"><ele>2201.25</ele></trkpt>
   <trkpt lon="5.992850" lat="44.905916"><ele>2199.25</ele></trkpt>
   <trkpt lon="5.992692" lat="44.905853"><ele>2193.75</ele></trkpt>
   <trkpt lon="5.992457" lat="44.905717"><ele>2188.5</ele></trkpt>
   <trkpt lon="5.992328" lat="44.905652"><ele>2187.0</ele></trkpt>
   <trkpt lon="5.992267" lat="44.905600"><ele>2186.5</ele></trkpt>
   <trkpt lon="5.992120" lat="44.905586"><ele>2183.25</ele></trkpt>
   <trkpt lon="5.991976" lat="44.905558"><ele>2180.25</ele></trkpt>
   <trkpt lon="5.991574" lat="44.905673"><ele>2171.25</ele></trkpt>
   <trkpt lon="5.991336" lat="44.905703"><ele>2169.0</ele></trkpt>
   <trkpt lon="5.991148" lat="44.905779"><ele>2168.0</ele></trkpt>
   <trkpt lon="5.991032" lat="44.905788"><ele>2167.5</ele></trkpt>
   <trkpt lon="5.990534" lat="44.905676"><ele>2161.75</ele></trkpt>
   <trkpt lon="5.990394" lat="44.905665"><ele>2160.0</ele></trkpt>
   <trkpt lon="5.990168" lat="44.905593"><ele>2155.75</ele></trkpt>
   <trkpt lon="5.990106" lat="44.905559"><ele>2154.0</ele></trkpt>
   <trkpt lon="5.989688" lat="44.905474"><ele>2145.25</ele></trkpt>
   <trkpt lon="5.989577" lat="44.905456"><ele>2143.25</ele></trkpt>
   <trkpt lon="5.989275" lat="44.905432"><ele>2138.25</ele></trkpt>
   <trkpt lon="5.989205" lat="44.905436"><ele>2137.5</ele></trkpt>
   <trkpt lon="5.988909" lat="44.905409"><ele>2133.0</ele></trkpt>
   <trkpt lon="5.988484" lat="44.905395"><ele>2127.5</ele></trkpt>
   <trkpt lon="5.988252" lat="44.905430"><ele>2125.5</ele></trkpt>
   <trkpt lon="5.987537" lat="44.905468"><ele>2115.5</ele></trkpt>
   <trkpt lon="5.987238" lat="44.905502"><ele>2113.0</ele></trkpt>
   <trkpt lon="5.986975" lat="44.905555"><ele>2111.25</ele></trkpt>
   <trkpt lon="5.986619" lat="44.905669"><ele>2110.75</ele></trkpt>
   <trkpt lon="5.986503" lat="44.905677"><ele>2110.0</ele></trkpt>
   <trkpt lon="5.986126" lat="44.905588"><ele>2106.0</ele></trkpt>
   <trkpt lon="5.986047" lat="44.905598"><ele>2105.75</ele></trkpt>
   <trkpt lon="5.985758" lat="44.905512"><ele>2103.0</ele></trkpt>
   <trkpt lon="5.985445" lat="44.905491"><ele>2099.75</ele></trkpt>
   <trkpt lon="5.985340" lat="44.905495"><ele>2099.0</ele></trkpt>
   <trkpt lon="5.985190" lat="44.905445"><ele>2098.25</ele></trkpt>
   <trkpt lon="5.985037" lat="44.905384"><ele>2098.5</ele></trkpt>
   <trkpt lon="5.985190" lat="44.905445"><ele>2098.25</ele></trkpt>
   <trkpt lon="5.985221" lat="44.905493"><ele>2097.75</ele></trkpt>
   <trkpt lon="5.985136" lat="44.905490"><ele>2097.0</ele></trkpt>
   <trkpt lon="5.985178" lat="44.905560"><ele>2096.5</ele></trkpt>
   <trkpt lon="5.985038" lat="44.905540"><ele>2095.25</ele></trkpt>
   <trkpt lon="5.985123" lat="44.905617"><ele>2095.0</ele></trkpt>
   <trkpt lon="5.985064" lat="44.905625"><ele>2094.0</ele></trkpt>
   <trkpt lon="5.985104" lat="44.905656"><ele>2094.0</ele></trkpt>
   <trkpt lon="5.984989" lat="44.905664"><ele>2092.0</ele></trkpt>
   <trkpt lon="5.985159" lat="44.905725"><ele>2094.0</ele></trkpt>
   <trkpt lon="5.985285" lat="44.905789"><ele>2095.75</ele></trkpt>
   <trkpt lon="5.985422" lat="44.905886"><ele>2095.0</ele></trkpt>
   <trkpt lon="5.985524" lat="44.906057"><ele>2085.5</ele></trkpt>
   <trkpt lon="5.985463" lat="44.906047"><ele>2084.75</ele></trkpt>
   <trkpt lon="5.985492" lat="44.906090"><ele>2082.5</ele></trkpt>
   <trkpt lon="5.985658" lat="44.906176"><ele>2080.5</ele></trkpt>
   <trkpt lon="5.985882" lat="44.906244"><ele>2081.0</ele></trkpt>
   <trkpt lon="5.985966" lat="44.906256"><ele>2081.25</ele></trkpt>
   <trkpt lon="5.986099" lat="44.906348"><ele>2076.75</ele></trkpt>
   <trkpt lon="5.986204" lat="44.906556"><ele>2064.75</ele></trkpt>
   <trkpt lon="5.986443" lat="44.906692"><ele>2059.25</ele></trkpt>
   <trkpt lon="5.986593" lat="44.906739"><ele>2057.5</ele></trkpt>
   <trkpt lon="5.986526" lat="44.906776"><ele>2053.25</ele></trkpt>
   <trkpt lon="5.986664" lat="44.906838"><ele>2050.5</ele></trkpt>
   <trkpt lon="5.986750" lat="44.907042"><ele>2034.0</ele></trkpt>
   <trkpt lon="5.986980" lat="44.907108"><ele>2030.75</ele></trkpt>
   <trkpt lon="5.987027" lat="44.907162"><ele>2026.75</ele></trkpt>
   <trkpt lon="5.987179" lat="44.907258"><ele>2020.25</ele></trkpt>
   <trkpt lon="5.987211" lat="44.907310"><ele>2016.25</ele></trkpt>
   <trkpt lon="5.987352" lat="44.907399"><ele>2010.5</ele></trkpt>
   <trkpt lon="5.987336" lat="44.907467"><ele>2004.75</ele></trkpt>
   <trkpt lon="5.987291" lat="44.907563"><ele>1997.0</ele></trkpt>
   <trkpt lon="5.987226" lat="44.907583"><ele>1994.75</ele></trkpt>
   <trkpt lon="5.987252" lat="44.907657"><ele>1989.5</ele></trkpt>
   <trkpt lon="5.987219" lat="44.907711"><ele>1985.0</ele></trkpt>
   <trkpt lon="5.987090" lat="44.907629"><ele>1989.75</ele></trkpt>
   <trkpt lon="5.986956" lat="44.907945"><ele>1965.0</ele></trkpt>
   <trkpt lon="5.986843" lat="44.907916"><ele>1966.25</ele></trkpt>
   <trkpt lon="5.986798" lat="44.907829"><ele>1972.0</ele></trkpt>
   <trkpt lon="5.986731" lat="44.907914"><ele>1965.25</ele></trkpt>
   <trkpt lon="5.986618" lat="44.908247"><ele>1939.0</ele></trkpt>
   <trkpt lon="5.986650" lat="44.908408"><ele>1928.75</ele></trkpt>
   <trkpt lon="5.986554" lat="44.908520"><ele>1919.25</ele></trkpt>
   <trkpt lon="5.986637" lat="44.908615"><ele>1915.25</ele></trkpt>
   <trkpt lon="5.986511" lat="44.908657"><ele>1909.5</ele></trkpt>
   <trkpt lon="5.986589" lat="44.908769"><ele>1904.25</ele></trkpt>
   <trkpt lon="5.986669" lat="44.908813"><ele>1903.25</ele></trkpt>
   <trkpt lon="5.986556" lat="44.908857"><ele>1898.0</ele></trkpt>
   <trkpt lon="5.986677" lat="44.908940"><ele>1895.25</ele></trkpt>
   <trkpt lon="5.986535" lat="44.908980"><ele>1889.75</ele></trkpt>
   <trkpt lon="5.986712" lat="44.909071"><ele>1886.5</ele></trkpt>
   <trkpt lon="5.986575" lat="44.909075"><ele>1884.5</ele></trkpt>
   <trkpt lon="5.986664" lat="44.909149"><ele>1882.0</ele></trkpt>
   <trkpt lon="5.986618" lat="44.909461"><ele>1866.25</ele></trkpt>
   <trkpt lon="5.986406" lat="44.909732"><ele>1848.25</ele></trkpt>
   <trkpt lon="5.986436" lat="44.909831"><ele>1844.5</ele></trkpt>
   <trkpt lon="5.986253" lat="44.909687"><ele>1846.5</ele></trkpt>
   <trkpt lon="5.986243" lat="44.909896"><ele>1836.25</ele></trkpt>
   <trkpt lon="5.985945" lat="44.909687"><ele>1838.5</ele></trkpt>
   <trkpt lon="5.985972" lat="44.910091"><ele>1820.0</ele></trkpt>
   <trkpt lon="5.986135" lat="44.910473"><ele>1807.75</ele></trkpt>
   <trkpt lon="5.985620" lat="44.910260"><ele>1801.75</ele></trkpt>
   <trkpt lon="5.985610" lat="44.910456"><ele>1793.75</ele></trkpt>
   <trkpt lon="5.985671" lat="44.910587"><ele>1791.0</ele></trkpt>
   <trkpt lon="5.985376" lat="44.910428"><ele>1786.5</ele></trkpt>
   <trkpt lon="5.985341" lat="44.910695"><ele>1775.5</ele></trkpt>
   <trkpt lon="5.985368" lat="44.910857"><ele>1770.5</ele></trkpt>
   <trkpt lon="5.985516" lat="44.911149"><ele>1763.5</ele></trkpt>
   <trkpt lon="5.985607" lat="44.911073"><ele>1769.0</ele></trkpt>
   <trkpt lon="5.985647" lat="44.911184"><ele>1765.25</ele></trkpt>
   <trkpt lon="5.985524" lat="44.911216"><ele>1761.0</ele></trkpt>
   <trkpt lon="5.985454" lat="44.911514"><ele>1747.75</ele></trkpt>
   <trkpt lon="5.985248" lat="44.911484"><ele>1745.5</ele></trkpt>
   <trkpt lon="5.985248" lat="44.911729"><ele>1736.25</ele></trkpt>
   <trkpt lon="5.985170" lat="44.911674"><ele>1738.25</ele></trkpt>
   <trkpt lon="5.985159" lat="44.911790"><ele>1732.5</ele></trkpt>
   <trkpt lon="5.985175" lat="44.911913"><ele>1726.5</ele></trkpt>
   <trkpt lon="5.985363" lat="44.911942"><ele>1726.0</ele></trkpt>
   <trkpt lon="5.985502" lat="44.911902"><ele>1729.0</ele></trkpt>
   <trkpt lon="5.986555" lat="44.911819"><ele>1719.75</ele></trkpt>
   <trkpt lon="5.986762" lat="44.911848"><ele>1715.25</ele></trkpt>
   <trkpt lon="5.987243" lat="44.912001"><ele>1706.25</ele></trkpt>
   <trkpt lon="5.987372" lat="44.912018"><ele>1705.25</ele></trkpt>
   <trkpt lon="5.987527" lat="44.912019"><ele>1705.75</ele></trkpt>
   <trkpt lon="5.987582" lat="44.912040"><ele>1705.75</ele></trkpt>
   <trkpt lon="5.987537" lat="44.912127"><ele>1701.25</ele></trkpt>
   <trkpt lon="5.987389" lat="44.912334"><ele>1690.75</ele></trkpt>
   <trkpt lon="5.987405" lat="44.912382"><ele>1688.5</ele></trkpt>
   <trkpt lon="5.987513" lat="44.912461"><ele>1686.0</ele></trkpt>
   <trkpt lon="5.987538" lat="44.912604"><ele>1681.5</ele></trkpt>
   <trkpt lon="5.987607" lat="44.912670"><ele>1681.0</ele></trkpt>
   <trkpt lon="5.987881" lat="44.913527"><ele>1661.5</ele></trkpt>
   <trkpt lon="5.988041" lat="44.913646"><ele>1661.5</ele></trkpt>
   <trkpt lon="5.988053" lat="44.913688"><ele>1660.75</ele></trkpt>
   <trkpt lon="5.988113" lat="44.913738"><ele>1660.5</ele></trkpt>
   <trkpt lon="5.988191" lat="44.913757"><ele>1661.5</ele></trkpt>
   <trkpt lon="5.988359" lat="44.913881"><ele>1661.5</ele></trkpt>
   <trkpt lon="5.988366" lat="44.914059"><ele>1656.75</ele></trkpt>
   <trkpt lon="5.988521" lat="44.914075"><ele>1661.0</ele></trkpt>
   <trkpt lon="5.988564" lat="44.914108"><ele>1661.25</ele></trkpt>
   <trkpt lon="5.988576" lat="44.914149"><ele>1660.75</ele></trkpt>
   <trkpt lon="5.988557" lat="44.914248"><ele>1658.25</ele></trkpt>
   <trkpt lon="5.988514" lat="44.914299"><ele>1656.25</ele></trkpt>
   <trkpt lon="5.988301" lat="44.914436"><ele>1648.5</ele></trkpt>
   <trkpt lon="5.988178" lat="44.914623"><ele>1643.5</ele></trkpt>
   <trkpt lon="5.988187" lat="44.914673"><ele>1643.0</ele></trkpt>
   <trkpt lon="5.988063" lat="44.914907"><ele>1637.25</ele></trkpt>
   <trkpt lon="5.988018" lat="44.914938"><ele>1636.0</ele></trkpt>
   <trkpt lon="5.987995" lat="44.914997"><ele>1634.75</ele></trkpt>
   <trkpt lon="5.988072" lat="44.915077"><ele>1634.75</ele></trkpt>
   <trkpt lon="5.988057" lat="44.915096"><ele>1634.0</ele></trkpt>
  </trkseg>
 </trk>
</gpx>```
4

You could combine QGIS with HTML/Javascript (Highcharts or any other framework) to produce appealing elevation profiles. With the help of some Python expression functions, it's possible to use the QGIS Atlas feature to show multiple tracks together with their corresponding waypoints. The idea is, to create a virtual waypoints layer that will be filtered by the name of the tracks:

enter image description here All you have to do is:

  1. Drag&Drop your GPX file into QGIS map canvas, import and convert your track layer from MultiLinestring to Linestring. Call the resulting layer "track". Then import your waypoint layer and rename it to "waypoints_orig".
  2. Add a column "name" to your "track" layer and give your tracks some meaningful names. Then add a column "track" to your "waypoints_orig" layer and assign the corresponding track names to the waypoints. Add the virtual layer "waypoints" to your project:
vlayer = QgsVectorLayer("?query=select * from waypoints_orig where track=''&geometry=geometry",'waypoints','virtual')
QgsProject.instance().addMapLayer(vlayer)
  1. Put the following Python Code into the Macro section of your QGIS project and enable Python Macros:
from qgis.core import qgsfunction,QgsCoordinateTransform,QgsProject
from qgis.PyQt.QtCore import QTimer,QEventLoop
from itertools import accumulate
@qgsfunction(args=0, group='Custom', usesgeometry=True)
def GetProfileData(values, feature, parent):
    vertices = list(feature.geometry().vertices())
    dList,zList = zip(*[[vertices[i-1].distance(vertex),vertex.z()] for i,vertex in enumerate(vertices) if i > 0])
    dList = tuple(accumulate(dList))
    data = [list(elem) for elem in list(zip(dList,zList))]
    data.insert(0,[0,vertices[0].z()])
    return str(data)

@qgsfunction(args=0, group='Custom')
def wait1000(values, feature, parent):
    loop = QEventLoop()
    QTimer.singleShot(1000,loop.quit)
    loop.exec_()
    return 0
    
@qgsfunction(args=3, group='Custom', usesgeometry=True)
def GetWaypoints(values, feature, parent):
    waypointLayer = values[0]
    trackLayer = values[1]
    nameFilter = values[2]
    wplayer = QgsProject.instance().mapLayersByName(waypointLayer)[0]
    wplayer.setDataSource("?query=select * from waypoints_orig where track='%s'&geometry=geometry" % nameFilter,waypointLayer,'virtual')
    
    loop = QEventLoop()
    QTimer.singleShot(1000,loop.quit)
    loop.exec_()
    
    trlayer = QgsProject.instance().mapLayersByName(trackLayer)[0]
    geom = feature.geometry()
    
    crsSrc = wplayer.crs()
    crsDest = trlayer.crs()
    xform = QgsCoordinateTransform(crsSrc, crsDest,QgsProject.instance())
       
    ret = ''
    for wpf in wplayer.getFeatures():
        wpgeom =  wpf.geometry()
        wpgeom.transform(xform)
        vtx = geom.closestVertex(wpgeom.asPoint())[1]
        elev = geom.vertexAt(vtx).z()
        d = geom.distanceToVertex(vtx)
        print(d)
        ret += "{point: { xAxis: 0, yAxis: 0, x: %s, y: %s}, text: '%s'}," % (d,elev, wpf["name"])
     
    ret = ret[0:-1]
    return ret
  1. Generate an Atlas with your "track" layer as "Coverage layer"
  2. Add a HTML frame to your layout:
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
    #container {
    max-width: 850px;
    height: 350px;
    margin: 1em auto;
}
</style>

<title>Highcharts Demo</title>
</head>

<body>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/annotations.js"></script>

<div id="container" style="height: 400px; min-width: 380px;"></div>

<script type="text/javascript">//<![CDATA[

var elevationData = [%GetProfileData()%];

Highcharts.chart('container', {
    chart: {
        type: 'area'
    },

    title: {
         style: { color: "#2b435d" },
        text: "Mountain Trail"
    },

    subtitle: {
         style: { color: "#2b435d" },
        text: 'Total Length: [%round($length)%]m'
    },
    xAxis: {
        labels: {
              style: { color: "#2b435d" },
            format: '{value}'
        },
        minTickInterval: 250,
        title: {
            text: 'Distance [m]'
        }
    },

    yAxis: {
        startOnTick: true,
        endOnTick: false,
        maxPadding: 0.35,
        title: {
            text: 'Elevation [m]'
        },
        labels: {
              style: { color: "#2b435d" },
            format: '{value}'
        }
    },

    legend: {
        enabled: false
    },
    annotations: [{
        labelOptions: {
            backgroundColor: 'rgba(255,255,255,0.5)'
        },
        labels: [[% GetWaypoints('waypoints','track',"name") %]]}
    ],
    plotOptions: {
                area: {
                    fillColor: {
                        linearGradient: {
                            x1: 0,
                            y1: 0,
                            x2: 0,
                            y2: 1
                        },
                        stops: [
                            [0,'#8B4513'],
                            [1, Highcharts.Color(Highcharts.getOptions().colors[2]).setOpacity(0.3).get('rgba')]
                        ]
                    },
                    marker: {
                        radius: 2
                    },
                    lineWidth: 1,
                    states: {
                        hover: {
                            lineWidth: 1
                        }
                    },
                    threshold: null
                }
            },    

    series: [{
        data: elevationData,
        lineColor: Highcharts.getOptions().colors[1],
        color: Highcharts.getOptions().colors[2],
        fillOpacity: 0.5,
        name: 'Elevation',
        marker: {
            enabled: false
        },
        threshold: null
    }]

});
//]]> 

</script>
</body>
</html>
  1. Because of timing problems we have to add the Python expression function wait1000() to the HTML frame (i.e. use data defined override for "Exclude item from exports") enter image description here
  • 1
    Your'e welcome! ... yes I have some ideas, but need some time for implementation. Will update my answer soon ... – christoph Aug 31 '20 at 13:54
  • 1
    @bergjon I changed my answer to support the waypoint annotations. It's not perfect, but a good starting point. – christoph Sep 6 '20 at 14:56
  • 1
    Hi @bergjon! I changed the first lines of the code. Now you can load the code as Python Macro. The layers have to be named "track" and "waypoints" and "track" must be your Atlas layer. – christoph Sep 8 '20 at 8:31
  • 1
    You have many options to change the look of the profile. Just check the Highchart Demo pages and dive into the visible sources. – christoph Sep 8 '20 at 17:44
  • 1
    Ok, I guess we could add all positive delta z values and all abs() of the negative ones. – christoph Sep 8 '20 at 18:43
4

Using your xml file and matplotlib you can achieve nice results if you put some effort in it. Matplotlib plots can be tweaked to look alot like your example. The trickiest part was to calculate where to place the labels.

import matplotlib.pyplot as plt
import numpy as np

#Function to project geometries to get distances in meters instead of degrees
#From: https://gis.stackexchange.com/questions/163645/transforming-single-qgsgeometry-object-from-one-crs-to-another-using-pyqgis
def pr(ingeom):
    sourceCrs = QgsCoordinateReferenceSystem(4326)
    destCrs = QgsCoordinateReferenceSystem(32632)
    tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance())
    ingeom.transform(tr)
    return ingeom

tp = QgsProject.instance().mapLayersByName('track_points')[0]
zfield = 'ele'
orderfield = 'track_seg_point_id'
tpfeats = [f for f in tp.getFeatures()] #List all trackpoints
tpfeats.sort(key=lambda x: x[orderfield]) #Sort by orderfield (maybe they already are(?), doesnt matter)

#List all horizontal distances, the plot x values
hdist = [pr(p1.geometry()).distance(pr(p2.geometry())) for p1,p2 in zip(tpfeats, tpfeats[1:])]
hdist.insert(0,0) #First point
hdist = np.cumsum(hdist)
#List heights
zs = [f[zfield] for f in tpfeats] #The plot y values

#Which track point is closest to each waypoint?
#To know where to place each label in horizontal and height directions 
wp = QgsProject.instance().mapLayersByName('waypoints')[0]
placenamefield = 'name'
wpfeats = [f for f in wp.getFeatures()]
labels = [] #Each waypoints name attribute and the index of the closest trackpoint
for wpf in wpfeats:
    closest_trackpoint = min(tpfeats, key=lambda x: pr(x.geometry()).distance(pr(wpf.geometry())))
    ix = [tpf.id() for tpf in tpfeats].index(closest_trackpoint.id())
    labels.append([wpf[placenamefield], ix])

labels = [[l[0], hdist[l[1]]-100, zs[l[1]]+25] for l in labels] #List of lists like this: [['somelabeltext',horizontal distance, height], ['somelabeltext2',...

#Plot
plt.plot(hdist, zs, 'g')
plt.xlabel("Distance")
plt.ylabel("Elevation")
plt.title("Forgiving terrain 50k")
plt.hlines(range(1600,2700,100), xmin=0, xmax=4500, colors='silver', linestyles='solid')
x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,1600,2600))
plt.fill_between(hdist, zs, color='#c1daba')

for labeltext, x, y, in labels:
    plt.annotate(labeltext, (x, y), color='g')
plt.show()

enter image description here

enter image description here

  • 1
    Many thanks BERA! Great code. What if I already have the line as a GPX file in a layer? And as I see it, do I have to add the points manually ? – POGO Aug 30 '20 at 10:39
  • BERA, thank you! I updated the question with the code of the gpx file. I try to get names of the WPT-Features (e.g. "valley","start","peak") written on the elevation profile – POGO Aug 30 '20 at 10:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.