7

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>```
0

2 Answers 2

7

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
  • Is there a way to export the profile generated by this code directly to a page in Print Layout instead open it in a new window? Apr 18 at 13:54
5

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
11
  • 1
    Your'e welcome! ... yes I have some ideas, but need some time for implementation. Will update my answer soon ...
    – christoph
    Aug 31, 2020 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, 2020 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, 2020 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, 2020 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, 2020 at 18:43

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.